From 8197f489f4c4398391746a377c10501076b05168 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Mon, 6 Nov 2017 10:38:23 -0800 Subject: spi: imx: Fix failure path leak on GPIO request error correctly In commit 974488e4ce1e ("spi: imx: Fix failure path leak on GPIO request error"), spi_bitbang_start() was moved later in the probe sequence. But this doesn't work, as spi_bitbang_start() has to be called before requesting GPIOs because the GPIO data in the spi master is populated when the master is registed, and that doesn't happen until spi_bitbang_start() is called. The default only works if one uses one CS. So add a failure path call to spi_bitbang_stop() to fix the leak. CC: Shawn Guo CC: Sascha Hauer CC: Fabio Estevam CC: Mark Brown CC: Oleksij Rempel Signed-off-by: Trent Piepho Reviewed-by: Oleksij Rempel Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 5ddd32ba2521..301cdb721bad 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1613,6 +1613,11 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx->devtype_data->intctrl(spi_imx, 0); master->dev.of_node = pdev->dev.of_node; + ret = spi_bitbang_start(&spi_imx->bitbang); + if (ret) { + dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); + goto out_clk_put; + } if (!spi_imx->slave_mode) { if (!master->cs_gpios) { @@ -1631,23 +1636,19 @@ static int spi_imx_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Can't get CS GPIO %i\n", master->cs_gpios[i]); - goto out_clk_put; + goto out_spi_bitbang; } } } - ret = spi_bitbang_start(&spi_imx->bitbang); - if (ret) { - dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); - goto out_clk_put; - } - dev_info(&pdev->dev, "probed\n"); clk_disable(spi_imx->clk_ipg); clk_disable(spi_imx->clk_per); return ret; +out_spi_bitbang: + spi_bitbang_stop(&spi_imx->bitbang); out_clk_put: clk_disable_unprepare(spi_imx->clk_ipg); out_put_per: -- cgit v1.2.3 From 54f0a51a73acba08f047881c397e4040a573339b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 13 Nov 2017 21:05:35 +0800 Subject: regulator: tps65218: Remove unused enum tps65218_regulators The enum tps65218_regulators is no longer being used after commit 2dc4940360d4 ("regulator: tps65218: Remove all the compatibles"). Signed-off-by: Axel Lin Reviewed-by: Keerthy Signed-off-by: Mark Brown --- drivers/regulator/tps65218-regulator.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index bc489958fed7..b6f705292aef 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c @@ -28,9 +28,6 @@ #include #include -enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, - DCDC5, DCDC6, LDO1, LS3 }; - #define TPS65218_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \ _em, _cr, _cm, _lr, _nlr, _delay, _fuv, _sr, _sm) \ { \ -- cgit v1.2.3 From 5597bfb474d3ed84c1e0c73db620a257bbe127b6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 13 Nov 2017 20:52:32 +0800 Subject: regulator: tps65218: Add NULL test for devm_kzalloc call Signed-off-by: Axel Lin Reviewed-by: Keerthy Signed-off-by: Mark Brown --- drivers/regulator/tps65218-regulator.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index b6f705292aef..1827185beacc 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c @@ -326,6 +326,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev) /* Allocate memory for strobes */ tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) * TPS65218_NUM_REGULATOR, GFP_KERNEL); + if (!tps->strobes) + return -ENOMEM; for (i = 0; i < ARRAY_SIZE(regulators); i++) { rdev = devm_regulator_register(&pdev->dev, ®ulators[i], -- cgit v1.2.3 From 00ac9562158e8541d60e91eb72aa9ed0674d4a6a Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Mon, 13 Nov 2017 08:47:21 +0100 Subject: spi: spi-fsl-dspi: add SPI_LSB_FIRST to driver capabilities The driver as well as the controller support the SPI lsb first mode. However, it's not possible to configure it e.g. when using spidev. Adding this flag to mode_bits resolves the issue and lsb first mode can be used. Signed-off-by: Kurt Kanzenbach Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index f652f70cb8db..02d3ed7f2558 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -980,7 +980,7 @@ static int dspi_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; master->cleanup = dspi_cleanup; - master->mode_bits = SPI_CPOL | SPI_CPHA; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; master->bits_per_word_mask = SPI_BPW_MASK(4) | SPI_BPW_MASK(8) | SPI_BPW_MASK(16); -- cgit v1.2.3 From d5d3e202753cc023100a854788a4ad83d7c2821a Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 20 Nov 2017 11:48:41 +0100 Subject: HID: core: move the dynamic quirks handling in core usbhid has a list of dynamic quirks in addition to a list of static quirks. There is not much USB specific in that, so move this part of the module in core so we can have one central place for quirks. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/Makefile | 2 +- drivers/hid/hid-core.c | 10 +- drivers/hid/hid-quirks.c | 399 +++++++++++++++++++++++++++++++++++++++ drivers/hid/usbhid/Makefile | 2 +- drivers/hid/usbhid/hid-core.c | 10 +- drivers/hid/usbhid/hid-quirks.c | 402 ---------------------------------------- include/linux/hid.h | 10 +- 7 files changed, 418 insertions(+), 417 deletions(-) create mode 100644 drivers/hid/hid-quirks.c delete mode 100644 drivers/hid/usbhid/hid-quirks.c (limited to 'drivers') diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 235bd2a7b333..2be460d44c69 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -2,7 +2,7 @@ # # Makefile for the HID driver # -hid-y := hid-core.o hid-input.o +hid-y := hid-core.o hid-input.o hid-quirks.o hid-$(CONFIG_DEBUG_FS) += hid-debug.o obj-$(CONFIG_HID) += hid.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f3fcb836a1f9..e11caea05f8d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1597,8 +1597,8 @@ unlock: } EXPORT_SYMBOL_GPL(hid_input_report); -static bool hid_match_one_id(struct hid_device *hdev, - const struct hid_device_id *id) +bool hid_match_one_id(const struct hid_device *hdev, + const struct hid_device_id *id) { return (id->bus == HID_BUS_ANY || id->bus == hdev->bus) && (id->group == HID_GROUP_ANY || id->group == hdev->group) && @@ -1606,7 +1606,7 @@ static bool hid_match_one_id(struct hid_device *hdev, (id->product == HID_ANY_ID || id->product == hdev->product); } -const struct hid_device_id *hid_match_id(struct hid_device *hdev, +const struct hid_device_id *hid_match_id(const struct hid_device *hdev, const struct hid_device_id *id) { for (; id->bus; id++) @@ -2613,6 +2613,7 @@ static struct bus_type hid_bus_type = { .remove = hid_device_remove, .uevent = hid_uevent, }; +EXPORT_SYMBOL(hid_bus_type); /* a list of devices that shouldn't be handled by HID core at all */ static const struct hid_device_id hid_ignore_list[] = { @@ -2931,6 +2932,8 @@ int hid_add_device(struct hid_device *hdev) if (WARN_ON(hdev->status & HID_STAT_ADDED)) return -EBUSY; + hdev->quirks = hid_lookup_quirk(hdev); + /* we need to kill them here, otherwise they will stay allocated to * wait for coming driver */ if (hid_ignore(hdev)) @@ -3117,6 +3120,7 @@ static void __exit hid_exit(void) hid_debug_exit(); hidraw_exit(); bus_unregister(&hid_bus_type); + hid_quirks_exit(HID_BUS_ANY); } module_init(hid_init); diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c new file mode 100644 index 000000000000..ffb513a82581 --- /dev/null +++ b/drivers/hid/hid-quirks.c @@ -0,0 +1,399 @@ +/* + * HID quirks support for Linux + * + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2005 Vojtech Pavlik + * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2006-2007 Jiri Kosina + * Copyright (c) 2007 Paul Walmsley + */ + +/* + * 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. + */ + +#include +#include +#include +#include + +#include "hid-ids.h" + +/* + * Alphabetically sorted by vendor then product. + */ + +const struct hid_device_id hid_quirks[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD), HID_QUIRK_BADPAD }, + { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR), HID_QUIRK_BADPAD }, + { HID_USB_DEVICE(USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016), HID_QUIRK_FULLSPEED_INTERVAL }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD }, + { HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS1758), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD), HID_QUIRK_BADPAD }, + { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH_2968), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD), HID_QUIRK_BADPAD }, + { HID_USB_DEVICE(USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD), HID_QUIRK_BADPAD }, + { HID_USB_DEVICE(USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_NEXTWINDOW, USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN), HID_QUIRK_MULTI_INPUT}, + { HID_USB_DEVICE(USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK), HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1640), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL), HID_QUIRK_HIDINPUT_FORCE }, + { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD }, + { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD }, + { HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, + + { 0 } +}; + +/* Dynamic HID quirks list - specified at runtime */ +struct quirks_list_struct { + struct hid_device_id hid_bl_item; + struct list_head node; +}; + +static LIST_HEAD(dquirks_list); +static DEFINE_MUTEX(dquirks_lock); + +/* Runtime ("dynamic") quirks manipulation functions */ + +/** + * hid_exists_dquirk: find any dynamic quirks for a HID device + * @hdev: the HID device to match + * + * Description: + * Scans dquirks_list for a matching dynamic quirk and returns + * the pointer to the relevant struct hid_device_id if found. + * Must be called with a read lock held on dquirks_lock. + * + * Returns: NULL if no quirk found, struct hid_device_id * if found. + */ +static struct hid_device_id *hid_exists_dquirk(const struct hid_device *hdev) +{ + struct quirks_list_struct *q; + struct hid_device_id *bl_entry = NULL; + + list_for_each_entry(q, &dquirks_list, node) { + if (hid_match_one_id(hdev, &q->hid_bl_item)) { + bl_entry = &q->hid_bl_item; + break; + } + } + + if (bl_entry != NULL) + dbg_hid("Found dynamic quirk 0x%lx for HID device 0x%hx:0x%hx\n", + bl_entry->driver_data, bl_entry->vendor, + bl_entry->product); + + return bl_entry; +} + + +/** + * hid_modify_dquirk: add/replace a HID quirk + * @id: the HID device to match + * @quirks: the unsigned long quirks value to add/replace + * + * Description: + * If an dynamic quirk exists in memory for this device, replace its + * quirks value with what was provided. Otherwise, add the quirk + * to the dynamic quirks list. + * + * Returns: 0 OK, -error on failure. + */ +static int hid_modify_dquirk(const struct hid_device_id *id, + const unsigned long quirks) +{ + struct hid_device *hdev; + struct quirks_list_struct *q_new, *q; + int list_edited = 0; + int ret = 0; + + hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); + if (!hdev) + return -ENOMEM; + + q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL); + if (!q_new) { + ret = -ENOMEM; + goto out; + } + + hdev->bus = q_new->hid_bl_item.bus = id->bus; + hdev->group = q_new->hid_bl_item.group = id->group; + hdev->vendor = q_new->hid_bl_item.vendor = id->vendor; + hdev->product = q_new->hid_bl_item.product = id->product; + q_new->hid_bl_item.driver_data = quirks; + + mutex_lock(&dquirks_lock); + + list_for_each_entry(q, &dquirks_list, node) { + + if (hid_match_one_id(hdev, &q->hid_bl_item)) { + + list_replace(&q->node, &q_new->node); + kfree(q); + list_edited = 1; + break; + + } + + } + + if (!list_edited) + list_add_tail(&q_new->node, &dquirks_list); + + mutex_unlock(&dquirks_lock); + + out: + kfree(hdev); + return ret; +} + +/** + * hid_remove_all_dquirks: remove all runtime HID quirks from memory + * @bus: bus to match against. Use HID_BUS_ANY if all need to be removed. + * + * Description: + * Free all memory associated with dynamic quirks - called before + * module unload. + * + */ +static void hid_remove_all_dquirks(__u16 bus) +{ + struct quirks_list_struct *q, *temp; + + mutex_lock(&dquirks_lock); + list_for_each_entry_safe(q, temp, &dquirks_list, node) { + if (bus == HID_BUS_ANY || bus == q->hid_bl_item.bus) { + list_del(&q->node); + kfree(q); + } + } + mutex_unlock(&dquirks_lock); + +} + +/** + * hid_quirks_init: apply HID quirks specified at module load time + */ +int hid_quirks_init(char **quirks_param, __u16 bus, int count) +{ + struct hid_device_id id = { 0 }; + int n = 0, m; + unsigned short int vendor, product; + u32 quirks; + + id.bus = bus; + + for (; n < count && quirks_param[n]; n++) { + + m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x", + &vendor, &product, &quirks); + + id.vendor = (__u16)vendor; + id.product = (__u16)product; + + if (m != 3 || + hid_modify_dquirk(&id, quirks) != 0) { + pr_warn("Could not parse HID quirk module param %s\n", + quirks_param[n]); + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(hid_quirks_init); + +/** + * hid_quirks_exit: release memory associated with dynamic_quirks + * @bus: a bus to match against + * + * Description: + * Release all memory associated with dynamic quirks for a given bus. + * Called upon module unload. + * Use HID_BUS_ANY to remove all dynamic quirks. + * + * Returns: nothing + */ +void hid_quirks_exit(__u16 bus) +{ + hid_remove_all_dquirks(bus); +} +EXPORT_SYMBOL_GPL(hid_quirks_exit); + +/** + * hid_exists_squirk: return any static quirks for a HID device + * @hdev: the HID device to match + * + * Description: + * Given a HID device, return a pointer to the quirked hid_device_id entry + * associated with that device. + * + * Returns: pointer if quirk found, or NULL if no quirks found. + */ +static const struct hid_device_id *hid_exists_squirk(const struct hid_device *hdev) +{ + const struct hid_device_id *bl_entry; + + bl_entry = hid_match_id(hdev, hid_quirks); + + if (bl_entry != NULL) + dbg_hid("Found squirk 0x%lx for HID device 0x%hx:0x%hx\n", + bl_entry->driver_data, bl_entry->vendor, + bl_entry->product); + return bl_entry; +} + +/** + * hid_lookup_quirk: return any quirks associated with a HID device + * @hdev: the HID device to look for + * + * Description: + * Given a HID device, return any quirks associated with that device. + * + * Returns: an unsigned long quirks value. + */ +unsigned long hid_lookup_quirk(const struct hid_device *hdev) +{ + unsigned long quirks = 0; + const struct hid_device_id *quirk_entry = NULL; + + /* NCR devices must not be queried for reports */ + if (hdev->bus == BUS_USB && + hdev->vendor == USB_VENDOR_ID_NCR && + hdev->product >= USB_DEVICE_ID_NCR_FIRST && + hdev->product <= USB_DEVICE_ID_NCR_LAST) + return HID_QUIRK_NO_INIT_REPORTS; + + mutex_lock(&dquirks_lock); + quirk_entry = hid_exists_dquirk(hdev); + if (!quirk_entry) + quirk_entry = hid_exists_squirk(hdev); + if (quirk_entry) + quirks = quirk_entry->driver_data; + mutex_unlock(&dquirks_lock); + + return quirks; +} +EXPORT_SYMBOL_GPL(hid_lookup_quirk); diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile index 0ff227d0c033..b6349e30bd93 100644 --- a/drivers/hid/usbhid/Makefile +++ b/drivers/hid/usbhid/Makefile @@ -3,7 +3,7 @@ # Makefile for the USB input drivers # -usbhid-y := hid-core.o hid-quirks.o +usbhid-y := hid-core.o usbhid-$(CONFIG_USB_HIDDEV) += hiddev.o usbhid-$(CONFIG_HID_PID) += hid-pidff.o diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 640dfb937c69..cd1ccb6b90c9 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -978,8 +978,7 @@ static int usbhid_parse(struct hid_device *hid) int num_descriptors; size_t offset = offsetof(struct hid_descriptor, desc); - quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); + quirks = hid_lookup_quirk(hid); if (quirks & HID_QUIRK_IGNORE) return -ENODEV; @@ -1329,7 +1328,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * hid->vendor = le16_to_cpu(dev->descriptor.idVendor); hid->product = le16_to_cpu(dev->descriptor.idProduct); hid->name[0] = 0; - hid->quirks = usbhid_lookup_quirk(hid->vendor, hid->product); if (intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) hid->type = HID_TYPE_USBMOUSE; @@ -1641,7 +1639,7 @@ static int __init hid_init(void) { int retval = -ENOMEM; - retval = usbhid_quirks_init(quirks_param); + retval = hid_quirks_init(quirks_param, BUS_USB, MAX_USBHID_BOOT_QUIRKS); if (retval) goto usbhid_quirks_init_fail; retval = usb_register(&hid_driver); @@ -1651,7 +1649,7 @@ static int __init hid_init(void) return 0; usb_register_fail: - usbhid_quirks_exit(); + hid_quirks_exit(BUS_USB); usbhid_quirks_init_fail: return retval; } @@ -1659,7 +1657,7 @@ usbhid_quirks_init_fail: static void __exit hid_exit(void) { usb_deregister(&hid_driver); - usbhid_quirks_exit(); + hid_quirks_exit(BUS_USB); } module_init(hid_init); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c deleted file mode 100644 index 331f7f34ec14..000000000000 --- a/drivers/hid/usbhid/hid-quirks.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * USB HID quirks support for Linux - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik - * Copyright (c) 2005 Michael Haboustak for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - */ - -/* - * 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. - */ - -#include -#include -#include - -#include "../hid-ids.h" - -/* - * Alphabetically sorted blacklist by quirk type. - */ - -static const struct hid_blacklist { - __u16 idVendor; - __u16 idProduct; - __u32 quirks; -} hid_blacklist[] = { - { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, - { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_NEXTWINDOW, USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN, HID_QUIRK_MULTI_INPUT}, - { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, - - { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, - - { USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH_2968, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, - { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, - - { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS1758, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1640, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, - - { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, - - { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, - - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK, HID_QUIRK_MULTI_INPUT }, - - { 0, 0 } -}; - -/* Dynamic HID quirks list - specified at runtime */ -struct quirks_list_struct { - struct hid_blacklist hid_bl_item; - struct list_head node; -}; - -static LIST_HEAD(dquirks_list); -static DECLARE_RWSEM(dquirks_rwsem); - -/* Runtime ("dynamic") quirks manipulation functions */ - -/** - * usbhid_exists_dquirk: find any dynamic quirks for a USB HID device - * @idVendor: the 16-bit USB vendor ID, in native byteorder - * @idProduct: the 16-bit USB product ID, in native byteorder - * - * Description: - * Scans dquirks_list for a matching dynamic quirk and returns - * the pointer to the relevant struct hid_blacklist if found. - * Must be called with a read lock held on dquirks_rwsem. - * - * Returns: NULL if no quirk found, struct hid_blacklist * if found. - */ -static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor, - const u16 idProduct) -{ - struct quirks_list_struct *q; - struct hid_blacklist *bl_entry = NULL; - - list_for_each_entry(q, &dquirks_list, node) { - if (q->hid_bl_item.idVendor == idVendor && - q->hid_bl_item.idProduct == idProduct) { - bl_entry = &q->hid_bl_item; - break; - } - } - - if (bl_entry != NULL) - dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n", - bl_entry->quirks, bl_entry->idVendor, - bl_entry->idProduct); - - return bl_entry; -} - - -/** - * usbhid_modify_dquirk: add/replace a HID quirk - * @idVendor: the 16-bit USB vendor ID, in native byteorder - * @idProduct: the 16-bit USB product ID, in native byteorder - * @quirks: the u32 quirks value to add/replace - * - * Description: - * If an dynamic quirk exists in memory for this (idVendor, - * idProduct) pair, replace its quirks value with what was - * provided. Otherwise, add the quirk to the dynamic quirks list. - * - * Returns: 0 OK, -error on failure. - */ -static int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, - const u32 quirks) -{ - struct quirks_list_struct *q_new, *q; - int list_edited = 0; - - if (!idVendor) { - dbg_hid("Cannot add a quirk with idVendor = 0\n"); - return -EINVAL; - } - - q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL); - if (!q_new) - return -ENOMEM; - - q_new->hid_bl_item.idVendor = idVendor; - q_new->hid_bl_item.idProduct = idProduct; - q_new->hid_bl_item.quirks = quirks; - - down_write(&dquirks_rwsem); - - list_for_each_entry(q, &dquirks_list, node) { - - if (q->hid_bl_item.idVendor == idVendor && - q->hid_bl_item.idProduct == idProduct) { - - list_replace(&q->node, &q_new->node); - kfree(q); - list_edited = 1; - break; - - } - - } - - if (!list_edited) - list_add_tail(&q_new->node, &dquirks_list); - - up_write(&dquirks_rwsem); - - return 0; -} - -/** - * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory - * - * Description: - * Free all memory associated with dynamic quirks - called before - * module unload. - * - */ -static void usbhid_remove_all_dquirks(void) -{ - struct quirks_list_struct *q, *temp; - - down_write(&dquirks_rwsem); - list_for_each_entry_safe(q, temp, &dquirks_list, node) { - list_del(&q->node); - kfree(q); - } - up_write(&dquirks_rwsem); - -} - -/** - * usbhid_quirks_init: apply USB HID quirks specified at module load time - */ -int usbhid_quirks_init(char **quirks_param) -{ - u16 idVendor, idProduct; - u32 quirks; - int n = 0, m; - - for (; n < MAX_USBHID_BOOT_QUIRKS && quirks_param[n]; n++) { - - m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x", - &idVendor, &idProduct, &quirks); - - if (m != 3 || - usbhid_modify_dquirk(idVendor, idProduct, quirks) != 0) { - pr_warn("Could not parse HID quirk module param %s\n", - quirks_param[n]); - } - } - - return 0; -} - -/** - * usbhid_quirks_exit: release memory associated with dynamic_quirks - * - * Description: - * Release all memory associated with dynamic quirks. Called upon - * module unload. - * - * Returns: nothing - */ -void usbhid_quirks_exit(void) -{ - usbhid_remove_all_dquirks(); -} - -/** - * usbhid_exists_squirk: return any static quirks for a USB HID device - * @idVendor: the 16-bit USB vendor ID, in native byteorder - * @idProduct: the 16-bit USB product ID, in native byteorder - * - * Description: - * Given a USB vendor ID and product ID, return a pointer to - * the hid_blacklist entry associated with that device. - * - * Returns: pointer if quirk found, or NULL if no quirks found. - */ -static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor, - const u16 idProduct) -{ - const struct hid_blacklist *bl_entry = NULL; - int n = 0; - - for (; hid_blacklist[n].idVendor; n++) - if (hid_blacklist[n].idVendor == idVendor && - (hid_blacklist[n].idProduct == (__u16) HID_ANY_ID || - hid_blacklist[n].idProduct == idProduct)) - bl_entry = &hid_blacklist[n]; - - if (bl_entry != NULL) - dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n", - bl_entry->quirks, bl_entry->idVendor, - bl_entry->idProduct); - return bl_entry; -} - -/** - * usbhid_lookup_quirk: return any quirks associated with a USB HID device - * @idVendor: the 16-bit USB vendor ID, in native byteorder - * @idProduct: the 16-bit USB product ID, in native byteorder - * - * Description: - * Given a USB vendor ID and product ID, return any quirks associated - * with that device. - * - * Returns: a u32 quirks value. - */ -u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct) -{ - u32 quirks = 0; - const struct hid_blacklist *bl_entry = NULL; - - /* NCR devices must not be queried for reports */ - if (idVendor == USB_VENDOR_ID_NCR && - idProduct >= USB_DEVICE_ID_NCR_FIRST && - idProduct <= USB_DEVICE_ID_NCR_LAST) - return HID_QUIRK_NO_INIT_REPORTS; - - down_read(&dquirks_rwsem); - bl_entry = usbhid_exists_dquirk(idVendor, idProduct); - if (!bl_entry) - bl_entry = usbhid_exists_squirk(idVendor, idProduct); - if (bl_entry) - quirks = bl_entry->quirks; - up_read(&dquirks_rwsem); - - return quirks; -} - -EXPORT_SYMBOL_GPL(usbhid_lookup_quirk); diff --git a/include/linux/hid.h b/include/linux/hid.h index d491027a7c22..129a0d71e06a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -860,7 +860,9 @@ int hid_open_report(struct hid_device *device); int hid_check_keys_pressed(struct hid_device *hid); int hid_connect(struct hid_device *hid, unsigned int connect_mask); void hid_disconnect(struct hid_device *hid); -const struct hid_device_id *hid_match_id(struct hid_device *hdev, +bool hid_match_one_id(const struct hid_device *hdev, + const struct hid_device_id *id); +const struct hid_device_id *hid_match_id(const struct hid_device *hdev, const struct hid_device_id *id); s32 hid_snto32(__u32 value, unsigned n); __u32 hid_field_extract(const struct hid_device *hid, __u8 *report, @@ -1098,9 +1100,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, int interrupt); /* HID quirks API */ -u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct); -int usbhid_quirks_init(char **quirks_param); -void usbhid_quirks_exit(void); +unsigned long hid_lookup_quirk(const struct hid_device *hdev); +int hid_quirks_init(char **quirks_param, __u16 bus, int count); +void hid_quirks_exit(__u16 bus); #ifdef CONFIG_HID_PID int hid_pidff_init(struct hid_device *hid); -- cgit v1.2.3 From 6e65d9d5492f370dd0e5418bdd38265b2ca74f88 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 20 Nov 2017 11:48:42 +0100 Subject: HID: quirks: move the list of special devices into a quirk It is better to centralize the information of special devices in one single file. Instead of manually parsing the list of devices that have a special driver or those that need to be ignored, introduce HID_QUIRK_HAVE_SPECIAL_DRIVER and set the correct quirks while fetching those quirks. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 537 +------------------------------------------- drivers/hid/hid-quirks.c | 555 +++++++++++++++++++++++++++++++++++++++++++++- include/linux/hid.h | 1 + net/bluetooth/hidp/core.c | 2 +- 4 files changed, 549 insertions(+), 546 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e11caea05f8d..1c8d10724203 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1862,541 +1862,6 @@ void hid_hw_close(struct hid_device *hdev) } EXPORT_SYMBOL_GPL(hid_hw_close); -/* - * A list of devices for which there is a specialized driver on HID bus. - * - * Please note that for multitouch devices (driven by hid-multitouch driver), - * there is a proper autodetection and autoloading in place (based on presence - * of HID_DG_CONTACTID), so those devices don't need to be added to this list, - * as we are doing the right thing in hid_scan_usage(). - * - * Autodetection for (USB) HID sensor hubs exists too. If a collection of type - * physical is found inside a usage page of type sensor, hid-sensor-hub will be - * used as a driver. See hid_scan_report(). - */ -static const struct hid_device_id hid_have_special_driver[] = { -#if IS_ENABLED(CONFIG_HID_A4TECH) - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, -#endif -#if IS_ENABLED(CONFIG_HID_ACCUTOUCH) - { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) }, -#endif -#if IS_ENABLED(CONFIG_HID_ACRUX) - { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) }, -#endif -#if IS_ENABLED(CONFIG_HID_ALPS) - { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) }, -#endif -#if IS_ENABLED(CONFIG_HID_APPLE) - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, -#endif -#if IS_ENABLED(CONFIG_HID_APPLEIR) - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) }, -#endif -#if IS_ENABLED(CONFIG_HID_ASUS) - { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD) }, -#endif -#if IS_ENABLED(CONFIG_HID_AUREAL) - { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, -#endif -#if IS_ENABLED(CONFIG_HID_BELKIN) - { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, -#endif -#if IS_ENABLED(CONFIG_HID_BETOP_FF) - { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185PC, 0x5506) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2PC, 0x1850) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2BFM, 0x5500) }, -#endif -#if IS_ENABLED(CONFIG_HID_CHERRY) - { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, -#endif -#if IS_ENABLED(CONFIG_HID_CHICONY) - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) }, -#endif -#if IS_ENABLED(CONFIG_HID_CMEDIA) - { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) }, -#endif -#if IS_ENABLED(CONFIG_HID_CORSAIR) - { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) }, -#endif -#if IS_ENABLED(CONFIG_HID_CP2112) - { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, -#endif -#if IS_ENABLED(CONFIG_HID_CYPRESS) - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, -#endif -#if IS_ENABLED(CONFIG_HID_DRAGONRISE) - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, -#endif -#if IS_ENABLED(CONFIG_HID_ELECOM) - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) }, -#endif -#if IS_ENABLED(CONFIG_HID_ELO) - { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) }, -#endif -#if IS_ENABLED(CONFIG_HID_EMS_FF) - { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, -#endif -#if IS_ENABLED(CONFIG_HID_EZKEY) - { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, -#endif -#if IS_ENABLED(CONFIG_HID_GEMBIRD) - { HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) }, -#endif -#if IS_ENABLED(CONFIG_HID_GFRM) - { HID_BLUETOOTH_DEVICE(0x58, 0x2000) }, - { HID_BLUETOOTH_DEVICE(0x471, 0x2210) }, -#endif -#if IS_ENABLED(CONFIG_HID_GREENASIA) - { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, -#endif -#if IS_ENABLED(CONFIG_HID_GT683R) - { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, -#endif -#if IS_ENABLED(CONFIG_HID_GYRATION) - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, -#endif -#if IS_ENABLED(CONFIG_HID_HOLTEK) - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) }, -#endif -#if IS_ENABLED(CONFIG_HID_ICADE) - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, -#endif -#if IS_ENABLED(CONFIG_HID_ITE) - { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) }, -#endif -#if IS_ENABLED(CONFIG_HID_KENSINGTON) - { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, -#endif -#if IS_ENABLED(CONFIG_HID_KEYTOUCH) - { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, -#endif -#if IS_ENABLED(CONFIG_HID_KYE) - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_MANTICORE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912) }, -#endif -#if IS_ENABLED(CONFIG_HID_LCPOWER) - { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, -#endif -#if IS_ENABLED(CONFIG_HID_LED) - { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_LUXAFOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) }, -#endif -#if IS_ENABLED(CONFIG_HID_LENOVO) - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) }, -#endif -#if IS_ENABLED(CONFIG_HID_LOGITECH) - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, -#endif -#if IS_ENABLED(CONFIG_HID_LOGITECH_HIDPP) - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) }, -#endif -#if IS_ENABLED(CONFIG_HID_LOGITECH_DJ) - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) }, -#endif -#if IS_ENABLED(CONFIG_HID_MAGICMOUSE) - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, -#endif -#if IS_ENABLED(CONFIG_HID_MAYFLASH) - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) }, -#endif -#if IS_ENABLED(CONFIG_HID_MICROSOFT) - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE7K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, -#endif -#if IS_ENABLED(CONFIG_HID_MONTEREY) - { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, -#endif -#if IS_ENABLED(CONFIG_HID_MULTITOUCH) - { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MELFAS_MT) }, -#endif -#if IS_ENABLED(CONFIG_HID_WIIMOTE) - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) }, -#endif -#if IS_ENABLED(CONFIG_HID_NTI) - { HID_USB_DEVICE(USB_VENDOR_ID_NTI, USB_DEVICE_ID_USB_SUN) }, -#endif -#if IS_ENABLED(CONFIG_HID_NTRIG) - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, -#endif -#if IS_ENABLED(CONFIG_HID_ORTEK) - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, -#endif -#if IS_ENABLED(CONFIG_HID_PANTHERLORD) - { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, - { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) }, -#endif -#if IS_ENABLED(CONFIG_HID_PENMOUNT) - { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, -#endif -#if IS_ENABLED(CONFIG_HID_PETALYNX) - { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, -#endif -#if IS_ENABLED(CONFIG_HID_PICOLCD) - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, -#endif -#if IS_ENABLED(CONFIG_HID_PLANTRONICS) - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, -#endif -#if IS_ENABLED(CONFIG_HID_PRIMAX) - { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, -#endif -#if IS_ENABLED(CONFIG_HID_PRODIKEYS) - { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, -#endif -#if IS_ENABLED(CONFIG_HID_RETRODE) - { HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, USB_DEVICE_ID_RETRODE2) }, -#endif -#if IS_ENABLED(CONFIG_HID_RMI) - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) }, -#endif -#if IS_ENABLED(CONFIG_HID_ROCCAT) - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_GLOW) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, -#endif -#if IS_ENABLED(CONFIG_HID_SAITEK) - { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT9) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) }, -#endif -#if IS_ENABLED(CONFIG_HID_SAMSUNG) - { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, -#endif -#if IS_ENABLED(CONFIG_HID_SMARTJOYPLUS) - { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, -#endif -#if IS_ENABLED(CONFIG_HID_SONY) - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, -#endif -#if IS_ENABLED(CONFIG_HID_SPEEDLINK) - { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, -#endif -#if IS_ENABLED(CONFIG_HID_STEELSERIES) - { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) }, -#endif -#if IS_ENABLED(CONFIG_HID_SUNPLUS) - { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, -#endif -#if IS_ENABLED(CONFIG_HID_THRUSTMASTER) - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb605) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) }, -#endif -#if IS_ENABLED(CONFIG_HID_TIVO) - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_PRO) }, -#endif -#if IS_ENABLED(CONFIG_HID_TOPSEED) - { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, -#endif -#if IS_ENABLED(CONFIG_HID_TWINHAN) - { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, -#endif -#if IS_ENABLED(CONFIG_HID_UCLOGIC) - { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, -#endif -#if IS_ENABLED(CONFIG_HID_UDRAW_PS3) - { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) }, -#endif -#if IS_ENABLED(CONFIG_HID_WALTOP) - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_PID_0038) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) }, -#endif -#if IS_ENABLED(CONFIG_HID_XINMO) - { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_THT_2P_ARCADE) }, -#endif -#if IS_ENABLED(CONFIG_HID_ZEROPLUS) - { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, -#endif -#if IS_ENABLED(CONFIG_HID_ZYDACRON) - { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, -#endif - { } -}; - struct hid_dynid { struct list_head list; struct hid_device_id id; @@ -2963,7 +2428,7 @@ int hid_add_device(struct hid_device *hdev) if (hid_ignore_special_drivers) { hdev->group = HID_GROUP_GENERIC; } else if (!hdev->group && - !hid_match_id(hdev, hid_have_special_driver)) { + !(hdev->quirks & HID_QUIRK_HAVE_SPECIAL_DRIVER)) { ret = hid_scan_report(hdev); if (ret) hid_warn(hdev, "bad device descriptor (%d)\n", ret); diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index ffb513a82581..a8c93d62f1b6 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -166,6 +166,538 @@ const struct hid_device_id hid_quirks[] = { { 0 } }; +/* + * A list of devices for which there is a specialized driver on HID bus. + * + * Please note that for multitouch devices (driven by hid-multitouch driver), + * there is a proper autodetection and autoloading in place (based on presence + * of HID_DG_CONTACTID), so those devices don't need to be added to this list, + * as we are doing the right thing in hid_scan_usage(). + * + * Autodetection for (USB) HID sensor hubs exists too. If a collection of type + * physical is found inside a usage page of type sensor, hid-sensor-hub will be + * used as a driver. See hid_scan_report(). + */ +static const struct hid_device_id hid_have_special_driver[] = { +#if IS_ENABLED(CONFIG_HID_A4TECH) + { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, + { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, +#endif +#if IS_ENABLED(CONFIG_HID_ACCUTOUCH) + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) }, +#endif +#if IS_ENABLED(CONFIG_HID_ACRUX) + { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) }, +#endif +#if IS_ENABLED(CONFIG_HID_ALPS) + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) }, +#endif +#if IS_ENABLED(CONFIG_HID_APPLE) + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, +#endif +#if IS_ENABLED(CONFIG_HID_APPLEIR) + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) }, +#endif +#if IS_ENABLED(CONFIG_HID_ASUS) + { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD) }, +#endif +#if IS_ENABLED(CONFIG_HID_AUREAL) + { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, +#endif +#if IS_ENABLED(CONFIG_HID_BELKIN) + { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, +#endif +#if IS_ENABLED(CONFIG_HID_BETOP_FF) + { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185PC, 0x5506) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2PC, 0x1850) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2BFM, 0x5500) }, +#endif +#if IS_ENABLED(CONFIG_HID_CHERRY) + { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, +#endif +#if IS_ENABLED(CONFIG_HID_CHICONY) + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) }, +#endif +#if IS_ENABLED(CONFIG_HID_CMEDIA) + { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) }, +#endif +#if IS_ENABLED(CONFIG_HID_CORSAIR) + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) }, +#endif +#if IS_ENABLED(CONFIG_HID_CP2112) + { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, +#endif +#if IS_ENABLED(CONFIG_HID_CYPRESS) + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, +#endif +#if IS_ENABLED(CONFIG_HID_DRAGONRISE) + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, +#endif +#if IS_ENABLED(CONFIG_HID_ELECOM) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) }, +#endif +#if IS_ENABLED(CONFIG_HID_ELO) + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) }, +#endif +#if IS_ENABLED(CONFIG_HID_EMS_FF) + { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, +#endif +#if IS_ENABLED(CONFIG_HID_EZKEY) + { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, +#endif +#if IS_ENABLED(CONFIG_HID_GEMBIRD) + { HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) }, +#endif +#if IS_ENABLED(CONFIG_HID_GFRM) + { HID_BLUETOOTH_DEVICE(0x58, 0x2000) }, + { HID_BLUETOOTH_DEVICE(0x471, 0x2210) }, +#endif +#if IS_ENABLED(CONFIG_HID_GREENASIA) + { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, +#endif +#if IS_ENABLED(CONFIG_HID_GT683R) + { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, +#endif +#if IS_ENABLED(CONFIG_HID_GYRATION) + { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, +#endif +#if IS_ENABLED(CONFIG_HID_HOLTEK) + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) }, +#endif +#if IS_ENABLED(CONFIG_HID_ITE) + { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) }, +#endif +#if IS_ENABLED(CONFIG_HID_ICADE) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, +#endif +#if IS_ENABLED(CONFIG_HID_KENSINGTON) + { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, +#endif +#if IS_ENABLED(CONFIG_HID_KEYTOUCH) + { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, +#endif +#if IS_ENABLED(CONFIG_HID_KYE) + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_MANTICORE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912) }, +#endif +#if IS_ENABLED(CONFIG_HID_LCPOWER) + { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000) }, +#endif +#if IS_ENABLED(CONFIG_HID_LED) + { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_LUXAFOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) }, +#endif +#if IS_ENABLED(CONFIG_HID_LENOVO) + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) }, +#endif +#if IS_ENABLED(CONFIG_HID_LOGITECH) + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, +#endif +#if IS_ENABLED(CONFIG_HID_LOGITECH_HIDPP) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) }, +#endif +#if IS_ENABLED(CONFIG_HID_LOGITECH_DJ) + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) }, +#endif +#if IS_ENABLED(CONFIG_HID_MAGICMOUSE) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, +#endif +#if IS_ENABLED(CONFIG_HID_MAYFLASH) + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) }, +#endif +#if IS_ENABLED(CONFIG_HID_MICROSOFT) + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE7K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, +#endif +#if IS_ENABLED(CONFIG_HID_MONTEREY) + { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, +#endif +#if IS_ENABLED(CONFIG_HID_MULTITOUCH) + { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MELFAS_MT) }, +#endif +#if IS_ENABLED(CONFIG_HID_WIIMOTE) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) }, +#endif +#if IS_ENABLED(CONFIG_HID_NTI) + { HID_USB_DEVICE(USB_VENDOR_ID_NTI, USB_DEVICE_ID_USB_SUN) }, +#endif +#if IS_ENABLED(CONFIG_HID_NTRIG) + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, +#endif +#if IS_ENABLED(CONFIG_HID_ORTEK) + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, +#endif +#if IS_ENABLED(CONFIG_HID_PANTHERLORD) + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, + { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) }, +#endif +#if IS_ENABLED(CONFIG_HID_PENMOUNT) + { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, +#endif +#if IS_ENABLED(CONFIG_HID_PETALYNX) + { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, +#endif +#if IS_ENABLED(CONFIG_HID_PICOLCD) + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, +#endif +#if IS_ENABLED(CONFIG_HID_PLANTRONICS) + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, +#endif +#if IS_ENABLED(CONFIG_HID_PRIMAX) + { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, +#endif +#if IS_ENABLED(CONFIG_HID_PRODIKEYS) + { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, +#endif +#if IS_ENABLED(CONFIG_HID_RETRODE) + { HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, USB_DEVICE_ID_RETRODE2) }, +#endif +#if IS_ENABLED(CONFIG_HID_RMI) + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) }, +#endif +#if IS_ENABLED(CONFIG_HID_ROCCAT) + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_GLOW) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, +#endif +#if IS_ENABLED(CONFIG_HID_SAITEK) + { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT9) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) }, +#endif +#if IS_ENABLED(CONFIG_HID_SAMSUNG) + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, +#endif +#if IS_ENABLED(CONFIG_HID_SMARTJOYPLUS) + { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, +#endif +#if IS_ENABLED(CONFIG_HID_SONY) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, +#endif +#if IS_ENABLED(CONFIG_HID_SPEEDLINK) + { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, +#endif +#if IS_ENABLED(CONFIG_HID_STEELSERIES) + { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) }, +#endif +#if IS_ENABLED(CONFIG_HID_SUNPLUS) + { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, +#endif +#if IS_ENABLED(CONFIG_HID_THRUSTMASTER) + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb605) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) }, +#endif +#if IS_ENABLED(CONFIG_HID_TIVO) + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_PRO) }, +#endif +#if IS_ENABLED(CONFIG_HID_TOPSEED) + { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, +#endif +#if IS_ENABLED(CONFIG_HID_TWINHAN) + { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, +#endif +#if IS_ENABLED(CONFIG_HID_UCLOGIC) + { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, +#endif +#if IS_ENABLED(CONFIG_HID_UDRAW_PS3) + { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) }, +#endif +#if IS_ENABLED(CONFIG_HID_WALTOP) + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_PID_0038) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) }, +#endif +#if IS_ENABLED(CONFIG_HID_XINMO) + { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_THT_2P_ARCADE) }, +#endif +#if IS_ENABLED(CONFIG_HID_ZEROPLUS) + { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, +#endif +#if IS_ENABLED(CONFIG_HID_ZYDACRON) + { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, +#endif + { } +}; + /* Dynamic HID quirks list - specified at runtime */ struct quirks_list_struct { struct hid_device_id hid_bl_item; @@ -343,26 +875,31 @@ void hid_quirks_exit(__u16 bus) EXPORT_SYMBOL_GPL(hid_quirks_exit); /** - * hid_exists_squirk: return any static quirks for a HID device + * hid_gets_squirk: return any static quirks for a HID device * @hdev: the HID device to match * * Description: * Given a HID device, return a pointer to the quirked hid_device_id entry * associated with that device. * - * Returns: pointer if quirk found, or NULL if no quirks found. + * Returns: the quirks. */ -static const struct hid_device_id *hid_exists_squirk(const struct hid_device *hdev) +static unsigned long hid_gets_squirk(const struct hid_device *hdev) { const struct hid_device_id *bl_entry; + unsigned long quirks = 0; - bl_entry = hid_match_id(hdev, hid_quirks); + if (hid_match_id(hdev, hid_have_special_driver)) + quirks |= HID_QUIRK_HAVE_SPECIAL_DRIVER; + bl_entry = hid_match_id(hdev, hid_quirks); if (bl_entry != NULL) + quirks |= bl_entry->driver_data; + + if (quirks) dbg_hid("Found squirk 0x%lx for HID device 0x%hx:0x%hx\n", - bl_entry->driver_data, bl_entry->vendor, - bl_entry->product); - return bl_entry; + quirks, hdev->vendor, hdev->product); + return quirks; } /** @@ -388,10 +925,10 @@ unsigned long hid_lookup_quirk(const struct hid_device *hdev) mutex_lock(&dquirks_lock); quirk_entry = hid_exists_dquirk(hdev); - if (!quirk_entry) - quirk_entry = hid_exists_squirk(hdev); if (quirk_entry) quirks = quirk_entry->driver_data; + else + quirks = hid_gets_squirk(hdev); mutex_unlock(&dquirks_lock); return quirks; diff --git a/include/linux/hid.h b/include/linux/hid.h index 129a0d71e06a..83df331576a5 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -342,6 +342,7 @@ struct hid_item { #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID 0x00020000 #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP 0x00040000 +#define HID_QUIRK_HAVE_SPECIAL_DRIVER 0x00080000 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 #define HID_QUIRK_NO_IGNORE 0x40000000 diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 8112893037bd..83d3b8c5e790 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -789,7 +789,7 @@ static int hidp_setup_hid(struct hidp_session *session, hid->dev.parent = &session->conn->hcon->dev; hid->ll_driver = &hidp_hid_driver; - /* True if device is blacklisted in drivers/hid/hid-core.c */ + /* True if device is blacklisted in drivers/hid/hid-quirks.c */ if (hid_ignore(hid)) { hid_destroy_device(session->hid); session->hid = NULL; -- cgit v1.2.3 From f745d162f469a4b1e805779a8b0d9157100c813c Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 20 Nov 2017 11:48:43 +0100 Subject: HID: core: move the list of ignored devices in hid-quirks.c Better having all the devices quirks in one place. Note that this change introduces an initial lookup for the device in hid_gets_squirk(), which should not theoretically be required, but which actually allows to not have to reparse the list of ignored devices if we call hid_lookup_quirks twice. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 309 ---------------------------------------------- drivers/hid/hid-quirks.c | 312 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 312 insertions(+), 309 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1c8d10724203..e6d586a22bbd 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2080,315 +2080,6 @@ static struct bus_type hid_bus_type = { }; EXPORT_SYMBOL(hid_bus_type); -/* a list of devices that shouldn't be handled by HID core at all */ -static const struct hid_device_id hid_ignore_list[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, - { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AXENTIA, USB_DEVICE_ID_AXENTIA_FM_RADIO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI4713) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_RADIOSHARK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, - { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_410) }, - { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_510) }, - { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_GN9350E) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_KYE, 0x0058) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYVOLTAGE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYCURRENT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIC) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOTOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_ABSESP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_AUTODATABUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454_V2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0001) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, -#if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB) - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_INT_TP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_CPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_STICK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_COMP_TP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WTP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) }, -#endif - { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) }, - { } -}; - -/** - * hid_mouse_ignore_list - mouse devices which should not be handled by the hid layer - * - * There are composite devices for which we want to ignore only a certain - * interface. This is a list of devices for which only the mouse interface will - * be ignored. This allows a dedicated driver to take care of the interface. - */ -static const struct hid_device_id hid_mouse_ignore_list[] = { - /* appletouch driver */ - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, - { } -}; - -bool hid_ignore(struct hid_device *hdev) -{ - if (hdev->quirks & HID_QUIRK_NO_IGNORE) - return false; - if (hdev->quirks & HID_QUIRK_IGNORE) - return true; - - switch (hdev->vendor) { - case USB_VENDOR_ID_CODEMERCS: - /* ignore all Code Mercenaries IOWarrior devices */ - if (hdev->product >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST && - hdev->product <= USB_DEVICE_ID_CODEMERCS_IOW_LAST) - return true; - break; - case USB_VENDOR_ID_LOGITECH: - if (hdev->product >= USB_DEVICE_ID_LOGITECH_HARMONY_FIRST && - hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST) - return true; - /* - * The Keene FM transmitter USB device has the same USB ID as - * the Logitech AudioHub Speaker, but it should ignore the hid. - * Check if the name is that of the Keene device. - * For reference: the name of the AudioHub is - * "HOLTEK AudioHub Speaker". - */ - if (hdev->product == USB_DEVICE_ID_LOGITECH_AUDIOHUB && - !strcmp(hdev->name, "HOLTEK B-LINK USB Audio ")) - return true; - break; - case USB_VENDOR_ID_SOUNDGRAPH: - if (hdev->product >= USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST && - hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST) - return true; - break; - case USB_VENDOR_ID_HANWANG: - if (hdev->product >= USB_DEVICE_ID_HANWANG_TABLET_FIRST && - hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST) - return true; - break; - case USB_VENDOR_ID_JESS: - if (hdev->product == USB_DEVICE_ID_JESS_YUREX && - hdev->type == HID_TYPE_USBNONE) - return true; - break; - case USB_VENDOR_ID_VELLEMAN: - /* These are not HID devices. They are handled by comedi. */ - if ((hdev->product >= USB_DEVICE_ID_VELLEMAN_K8055_FIRST && - hdev->product <= USB_DEVICE_ID_VELLEMAN_K8055_LAST) || - (hdev->product >= USB_DEVICE_ID_VELLEMAN_K8061_FIRST && - hdev->product <= USB_DEVICE_ID_VELLEMAN_K8061_LAST)) - return true; - break; - case USB_VENDOR_ID_ATMEL_V_USB: - /* Masterkit MA901 usb radio based on Atmel tiny85 chip and - * it has the same USB ID as many Atmel V-USB devices. This - * usb radio is handled by radio-ma901.c driver so we want - * ignore the hid. Check the name, bus, product and ignore - * if we have MA901 usb radio. - */ - if (hdev->product == USB_DEVICE_ID_ATMEL_V_USB && - hdev->bus == BUS_USB && - strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0) - return true; - break; - } - - if (hdev->type == HID_TYPE_USBMOUSE && - hid_match_id(hdev, hid_mouse_ignore_list)) - return true; - - return !!hid_match_id(hdev, hid_ignore_list); -} -EXPORT_SYMBOL_GPL(hid_ignore); - int hid_add_device(struct hid_device *hdev) { static atomic_t id = ATOMIC_INIT(0); diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index a8c93d62f1b6..aa6a7f877ced 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -698,6 +698,315 @@ static const struct hid_device_id hid_have_special_driver[] = { { } }; +/* a list of devices that shouldn't be handled by HID core at all */ +static const struct hid_device_id hid_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, + { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AXENTIA, USB_DEVICE_ID_AXENTIA_FM_RADIO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI4713) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_RADIOSHARK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, + { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, + { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_410) }, + { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_510) }, + { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_GN9350E) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_KYE, 0x0058) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYVOLTAGE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYCURRENT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIC) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOTOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_ABSESP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_AUTODATABUS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454_V2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0001) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, +#if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB) + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_INT_TP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_CPAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_STICK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_COMP_TP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WTP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) }, +#endif + { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) }, + { } +}; + +/** + * hid_mouse_ignore_list - mouse devices which should not be handled by the hid layer + * + * There are composite devices for which we want to ignore only a certain + * interface. This is a list of devices for which only the mouse interface will + * be ignored. This allows a dedicated driver to take care of the interface. + */ +static const struct hid_device_id hid_mouse_ignore_list[] = { + /* appletouch driver */ + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +}; + +bool hid_ignore(struct hid_device *hdev) +{ + if (hdev->quirks & HID_QUIRK_NO_IGNORE) + return false; + if (hdev->quirks & HID_QUIRK_IGNORE) + return true; + + switch (hdev->vendor) { + case USB_VENDOR_ID_CODEMERCS: + /* ignore all Code Mercenaries IOWarrior devices */ + if (hdev->product >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST && + hdev->product <= USB_DEVICE_ID_CODEMERCS_IOW_LAST) + return true; + break; + case USB_VENDOR_ID_LOGITECH: + if (hdev->product >= USB_DEVICE_ID_LOGITECH_HARMONY_FIRST && + hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST) + return true; + /* + * The Keene FM transmitter USB device has the same USB ID as + * the Logitech AudioHub Speaker, but it should ignore the hid. + * Check if the name is that of the Keene device. + * For reference: the name of the AudioHub is + * "HOLTEK AudioHub Speaker". + */ + if (hdev->product == USB_DEVICE_ID_LOGITECH_AUDIOHUB && + !strcmp(hdev->name, "HOLTEK B-LINK USB Audio ")) + return true; + break; + case USB_VENDOR_ID_SOUNDGRAPH: + if (hdev->product >= USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST && + hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST) + return true; + break; + case USB_VENDOR_ID_HANWANG: + if (hdev->product >= USB_DEVICE_ID_HANWANG_TABLET_FIRST && + hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST) + return true; + break; + case USB_VENDOR_ID_JESS: + if (hdev->product == USB_DEVICE_ID_JESS_YUREX && + hdev->type == HID_TYPE_USBNONE) + return true; + break; + case USB_VENDOR_ID_VELLEMAN: + /* These are not HID devices. They are handled by comedi. */ + if ((hdev->product >= USB_DEVICE_ID_VELLEMAN_K8055_FIRST && + hdev->product <= USB_DEVICE_ID_VELLEMAN_K8055_LAST) || + (hdev->product >= USB_DEVICE_ID_VELLEMAN_K8061_FIRST && + hdev->product <= USB_DEVICE_ID_VELLEMAN_K8061_LAST)) + return true; + break; + case USB_VENDOR_ID_ATMEL_V_USB: + /* Masterkit MA901 usb radio based on Atmel tiny85 chip and + * it has the same USB ID as many Atmel V-USB devices. This + * usb radio is handled by radio-ma901.c driver so we want + * ignore the hid. Check the name, bus, product and ignore + * if we have MA901 usb radio. + */ + if (hdev->product == USB_DEVICE_ID_ATMEL_V_USB && + hdev->bus == BUS_USB && + strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0) + return true; + break; + } + + if (hdev->type == HID_TYPE_USBMOUSE && + hid_match_id(hdev, hid_mouse_ignore_list)) + return true; + + return !!hid_match_id(hdev, hid_ignore_list); +} +EXPORT_SYMBOL_GPL(hid_ignore); + /* Dynamic HID quirks list - specified at runtime */ struct quirks_list_struct { struct hid_device_id hid_bl_item; @@ -889,6 +1198,9 @@ static unsigned long hid_gets_squirk(const struct hid_device *hdev) const struct hid_device_id *bl_entry; unsigned long quirks = 0; + if (hid_match_id(hdev, hid_ignore_list)) + quirks |= HID_QUIRK_IGNORE; + if (hid_match_id(hdev, hid_have_special_driver)) quirks |= HID_QUIRK_HAVE_SPECIAL_DRIVER; -- cgit v1.2.3 From e04a0442d33b8cf183bba38646447b891bb02123 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 20 Nov 2017 11:48:44 +0100 Subject: HID: core: remove the absolute need of hid_have_special_driver[] Most HID devices behave properly when they are used with hid-generic. Since kernel v4.12, we do not poll for input reports at plug in, so hid-generic should behave properly with all HID devices. There has been a long standing list of HID devices that have a special driver. It used to be just a few, but with time, this list went too big, and we can not ask users to know which HID special driver will pick up their device. We can teach hid-generic to be nice with others. If a device is not explicitly marked with HID_QUIRK_HAVE_SPECIAL_DRIVER, we can allow hid-generic to pick up the device as long as no other loaded HID driver will match the device. When the special driver appears, hid-generic can step back and let the special driver handling the device. In case this special driver is removed, this good old pal of hid-generic will rebind to the device. This basically makes the list hid_have_special_driver[] useless. It still allows to not see a hid-generic driver bound and removed during boot, so we can keep it around. This will also help other people to have a special HID driver without the need of recompiling hid-core. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 76 ++++++++++++++++++++++++++++++----------------- drivers/hid/hid-generic.c | 68 +++++++++++++++++++++++++++++++++++++++++- include/linux/hid.h | 10 +++++++ 3 files changed, 125 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e6d586a22bbd..7297b1d1300c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -830,31 +830,6 @@ static int hid_scan_report(struct hid_device *hid) break; } - /* fall back to generic driver in case specific driver doesn't exist */ - switch (hid->group) { - case HID_GROUP_MULTITOUCH_WIN_8: - /* fall-through */ - case HID_GROUP_MULTITOUCH: - if (!IS_ENABLED(CONFIG_HID_MULTITOUCH)) - hid->group = HID_GROUP_GENERIC; - break; - case HID_GROUP_SENSOR_HUB: - if (!IS_ENABLED(CONFIG_HID_SENSOR_HUB)) - hid->group = HID_GROUP_GENERIC; - break; - case HID_GROUP_RMI: - if (!IS_ENABLED(CONFIG_HID_RMI)) - hid->group = HID_GROUP_GENERIC; - break; - case HID_GROUP_WACOM: - if (!IS_ENABLED(CONFIG_HID_WACOM)) - hid->group = HID_GROUP_GENERIC; - break; - case HID_GROUP_LOGITECH_DJ_DEVICE: - if (!IS_ENABLED(CONFIG_HID_LOGITECH_DJ)) - hid->group = HID_GROUP_GENERIC; - break; - } vfree(parser); return 0; } @@ -1928,8 +1903,8 @@ static void hid_free_dynids(struct hid_driver *hdrv) spin_unlock(&hdrv->dyn_lock); } -static const struct hid_device_id *hid_match_device(struct hid_device *hdev, - struct hid_driver *hdrv) +const struct hid_device_id *hid_match_device(struct hid_device *hdev, + struct hid_driver *hdrv) { struct hid_dynid *dynid; @@ -1944,6 +1919,7 @@ static const struct hid_device_id *hid_match_device(struct hid_device *hdev, return hid_match_id(hdev, hdrv->id_table); } +EXPORT_SYMBOL_GPL(hid_match_device); static int hid_bus_match(struct device *dev, struct device_driver *drv) { @@ -1973,6 +1949,23 @@ static int hid_device_probe(struct device *dev) goto unlock; } + if (hdrv->match) { + if (!hdrv->match(hdev, hid_ignore_special_drivers)) { + ret = -ENODEV; + goto unlock; + } + } else { + /* + * hid-generic implements .match(), so if + * hid_ignore_special_drivers is set, we can safely + * return. + */ + if (hid_ignore_special_drivers) { + ret = -ENODEV; + goto unlock; + } + } + hdev->driver = hdrv; if (hdrv->probe) { ret = hdrv->probe(hdev, id); @@ -2069,7 +2062,7 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -static struct bus_type hid_bus_type = { +struct bus_type hid_bus_type = { .name = "hid", .dev_groups = hid_dev_groups, .drv_groups = hid_drv_groups, @@ -2203,6 +2196,29 @@ void hid_destroy_device(struct hid_device *hdev) } EXPORT_SYMBOL_GPL(hid_destroy_device); + +static int __bus_add_driver(struct device_driver *drv, void *data) +{ + struct hid_driver *added_hdrv = data; + struct hid_driver *hdrv = to_hid_driver(drv); + + if (hdrv->bus_add_driver) + hdrv->bus_add_driver(added_hdrv); + + return 0; +} + +static int __bus_removed_driver(struct device_driver *drv, void *data) +{ + struct hid_driver *removed_hdrv = data; + struct hid_driver *hdrv = to_hid_driver(drv); + + if (hdrv->bus_removed_driver) + hdrv->bus_removed_driver(removed_hdrv); + + return 0; +} + int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, const char *mod_name) { @@ -2214,6 +2230,8 @@ int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, INIT_LIST_HEAD(&hdrv->dyn_list); spin_lock_init(&hdrv->dyn_lock); + bus_for_each_drv(&hid_bus_type, NULL, hdrv, __bus_add_driver); + return driver_register(&hdrv->driver); } EXPORT_SYMBOL_GPL(__hid_register_driver); @@ -2222,6 +2240,8 @@ void hid_unregister_driver(struct hid_driver *hdrv) { driver_unregister(&hdrv->driver); hid_free_dynids(hdrv); + + bus_for_each_drv(&hid_bus_type, NULL, hdrv, __bus_removed_driver); } EXPORT_SYMBOL_GPL(hid_unregister_driver); diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c index e288a4a06fe8..3c0a1bf433d7 100644 --- a/drivers/hid/hid-generic.c +++ b/drivers/hid/hid-generic.c @@ -24,8 +24,71 @@ #include +static struct hid_driver hid_generic; + +static int __unmap_hid_generic(struct device *dev, void *data) +{ + struct hid_driver *hdrv = data; + struct hid_device *hdev = to_hid_device(dev); + + /* only unbind matching devices already bound to hid-generic */ + if (hdev->driver != &hid_generic || + hid_match_device(hdev, hdrv) == NULL) + return 0; + + if (dev->parent) /* Needed for USB */ + device_lock(dev->parent); + device_release_driver(dev); + if (dev->parent) + device_unlock(dev->parent); + + return 0; +} + +static void hid_generic_add_driver(struct hid_driver *hdrv) +{ + bus_for_each_dev(&hid_bus_type, NULL, hdrv, __unmap_hid_generic); +} + +static void hid_generic_removed_driver(struct hid_driver *hdrv) +{ + int ret; + + ret = driver_attach(&hid_generic.driver); +} + +static int __check_hid_generic(struct device_driver *drv, void *data) +{ + struct hid_driver *hdrv = to_hid_driver(drv); + struct hid_device *hdev = data; + + if (hdrv == &hid_generic) + return 0; + + return hid_match_device(hdev, hdrv) != NULL; +} + +static bool hid_generic_match(struct hid_device *hdev, + bool ignore_special_driver) +{ + if (ignore_special_driver) + return true; + + if (hdev->quirks & HID_QUIRK_HAVE_SPECIAL_DRIVER) + return false; + + /* + * If any other driver wants the device, leave the device to this other + * driver. + */ + if (bus_for_each_drv(&hid_bus_type, NULL, hdev, __check_hid_generic)) + return false; + + return true; +} + static const struct hid_device_id hid_table[] = { - { HID_DEVICE(HID_BUS_ANY, HID_GROUP_GENERIC, HID_ANY_ID, HID_ANY_ID) }, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) }, { } }; MODULE_DEVICE_TABLE(hid, hid_table); @@ -33,6 +96,9 @@ MODULE_DEVICE_TABLE(hid, hid_table); static struct hid_driver hid_generic = { .name = "hid-generic", .id_table = hid_table, + .match = hid_generic_match, + .bus_add_driver = hid_generic_add_driver, + .bus_removed_driver = hid_generic_removed_driver, }; module_hid_driver(hid_generic); diff --git a/include/linux/hid.h b/include/linux/hid.h index 83df331576a5..39cdeb205caa 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -672,6 +672,7 @@ struct hid_usage_id { * to be called) * @dyn_list: list of dynamically added device ids * @dyn_lock: lock protecting @dyn_list + * @match: check if the given device is handled by this driver * @probe: new device inserted * @remove: device removed (NULL if not a hot-plug capable driver) * @report_table: on which reports to call raw_event (NULL means all) @@ -684,6 +685,8 @@ struct hid_usage_id { * @input_mapped: invoked on input registering after mapping an usage * @input_configured: invoked just before the device is registered * @feature_mapping: invoked on feature registering + * @bus_add_driver: invoked when a HID driver is about to be added + * @bus_removed_driver: invoked when a HID driver has been removed * @suspend: invoked on suspend (NULL means nop) * @resume: invoked on resume if device was not reset (NULL means nop) * @reset_resume: invoked on resume if device was reset (NULL means nop) @@ -712,6 +715,7 @@ struct hid_driver { struct list_head dyn_list; spinlock_t dyn_lock; + bool (*match)(struct hid_device *dev, bool ignore_special_driver); int (*probe)(struct hid_device *dev, const struct hid_device_id *id); void (*remove)(struct hid_device *dev); @@ -737,6 +741,8 @@ struct hid_driver { void (*feature_mapping)(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage); + void (*bus_add_driver)(struct hid_driver *driver); + void (*bus_removed_driver)(struct hid_driver *driver); #ifdef CONFIG_PM int (*suspend)(struct hid_device *hdev, pm_message_t message); int (*resume)(struct hid_device *hdev); @@ -815,6 +821,8 @@ extern bool hid_ignore(struct hid_device *); extern int hid_add_device(struct hid_device *); extern void hid_destroy_device(struct hid_device *); +extern struct bus_type hid_bus_type; + extern int __must_check __hid_register_driver(struct hid_driver *, struct module *, const char *mod_name); @@ -865,6 +873,8 @@ bool hid_match_one_id(const struct hid_device *hdev, const struct hid_device_id *id); const struct hid_device_id *hid_match_id(const struct hid_device *hdev, const struct hid_device_id *id); +const struct hid_device_id *hid_match_device(struct hid_device *hdev, + struct hid_driver *hdrv); s32 hid_snto32(__u32 value, unsigned n); __u32 hid_field_extract(const struct hid_device *hid, __u8 *report, unsigned offset, unsigned n); -- cgit v1.2.3 From d5158e020c45936d0ea5a1ce1e49a45da6e76f44 Mon Sep 17 00:00:00 2001 From: Niels Skou Olsen Date: Wed, 4 Oct 2017 12:29:57 +0200 Subject: HID: Ignore Jabra HID interface based on firmware version Two Jabra speakerphone devices were added to the ignore list in 2013, because the device HID interfaces didn't work well with kernel usbhid driver, and could cause volume key event storm. See the original commit: Commit 31b9779cb292 ("HID: ignore Jabra speakerphones HID interface") Modify hid_lookup_quirk() to consider the firmware version of these two devices, so that only versions older than a known good version are ignored. Signed-off-by: Niels Skou Olsen Signed-off-by: Jiri Kosina --- drivers/hid/hid-quirks.c | 16 ++++++++++++++-- drivers/hid/usbhid/hid-core.c | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index aa6a7f877ced..d57a22432957 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -788,8 +788,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_410) }, - { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_510) }, { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_GN9350E) }, { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, @@ -1235,6 +1233,20 @@ unsigned long hid_lookup_quirk(const struct hid_device *hdev) hdev->product <= USB_DEVICE_ID_NCR_LAST) return HID_QUIRK_NO_INIT_REPORTS; + /* These devices must be ignored if version (bcdDevice) is too old */ + if (hdev->bus == BUS_USB && hdev->vendor == USB_VENDOR_ID_JABRA) { + switch (hdev->product) { + case USB_DEVICE_ID_JABRA_SPEAK_410: + if (hdev->version < 0x0111) + return HID_QUIRK_IGNORE; + break; + case USB_DEVICE_ID_JABRA_SPEAK_510: + if (hdev->version < 0x0214) + return HID_QUIRK_IGNORE; + break; + } + } + mutex_lock(&dquirks_lock); quirk_entry = hid_exists_dquirk(hdev); if (quirk_entry) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index cd1ccb6b90c9..77c50cdfff97 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1327,6 +1327,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * hid->bus = BUS_USB; hid->vendor = le16_to_cpu(dev->descriptor.idVendor); hid->product = le16_to_cpu(dev->descriptor.idProduct); + hid->version = le16_to_cpu(dev->descriptor.bcdDevice); hid->name[0] = 0; if (intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) -- cgit v1.2.3 From 19ca28271c9a361629eb06382a43f355249de7ea Mon Sep 17 00:00:00 2001 From: Niels Skou Olsen Date: Wed, 4 Oct 2017 12:31:22 +0200 Subject: HID: Add special driver for Jabra devices Add a hid-jabra driver to the list of special drivers in hid-core. The driver prevents vendor defined HID usages (FF00-FFFF) in Jabra devices from being mapped to input events, that become unintended mouse events in the X11 server. Signed-off-by: Niels Skou Olsen Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 11 +++++++++ drivers/hid/Makefile | 1 + drivers/hid/hid-jabra.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-quirks.c | 3 +++ 4 files changed, 73 insertions(+) create mode 100644 drivers/hid/hid-jabra.c (limited to 'drivers') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 779c5ae47f36..9058dbc4dd6e 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -396,6 +396,17 @@ config HID_ITE ---help--- Support for ITE devices not fully compliant with HID standard. +config HID_JABRA + tristate "Jabra USB HID Driver" + depends on HID + ---help--- + Support for Jabra USB HID devices. + + Prevents mapping of vendor defined HID usages to input events. Without + this driver HID reports from Jabra devices may incorrectly be seen as + mouse button events. + Say M here if you may ever plug in a Jabra USB device. + config HID_TWINHAN tristate "Twinhan IR remote control" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 2be460d44c69..eb13b9e92d85 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o obj-$(CONFIG_HID_ICADE) += hid-icade.o obj-$(CONFIG_HID_ITE) += hid-ite.o +obj-$(CONFIG_HID_JABRA) += hid-jabra.o obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o obj-$(CONFIG_HID_KYE) += hid-kye.o diff --git a/drivers/hid/hid-jabra.c b/drivers/hid/hid-jabra.c new file mode 100644 index 000000000000..1f52daf14426 --- /dev/null +++ b/drivers/hid/hid-jabra.c @@ -0,0 +1,58 @@ +/* + * Jabra USB HID Driver + * + * Copyright (c) 2017 Niels Skou Olsen + */ + +/* + * 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. + */ + +#include +#include + +#include "hid-ids.h" + +#define HID_UP_VENDOR_DEFINED_MIN 0xff000000 +#define HID_UP_VENDOR_DEFINED_MAX 0xffff0000 + +static int jabra_input_mapping(struct hid_device *hdev, + struct hid_input *hi, + struct hid_field *field, + struct hid_usage *usage, + unsigned long **bit, int *max) +{ + int is_vendor_defined = + ((usage->hid & HID_USAGE_PAGE) >= HID_UP_VENDOR_DEFINED_MIN && + (usage->hid & HID_USAGE_PAGE) <= HID_UP_VENDOR_DEFINED_MAX); + + dbg_hid("hid=0x%08x appl=0x%08x coll_idx=0x%02x usage_idx=0x%02x: %s\n", + usage->hid, + field->application, + usage->collection_index, + usage->usage_index, + is_vendor_defined ? "ignored" : "defaulted"); + + /* Ignore vendor defined usages, default map standard usages */ + return is_vendor_defined ? -1 : 0; +} + +static const struct hid_device_id jabra_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, HID_ANY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(hid, jabra_devices); + +static struct hid_driver jabra_driver = { + .name = "jabra", + .id_table = jabra_devices, + .input_mapping = jabra_input_mapping, +}; +module_hid_driver(jabra_driver); + +MODULE_AUTHOR("Niels Skou Olsen "); +MODULE_DESCRIPTION("Jabra USB HID Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index d57a22432957..015e0c10248b 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -384,6 +384,9 @@ static const struct hid_device_id hid_have_special_driver[] = { #if IS_ENABLED(CONFIG_HID_ICADE) { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, #endif +#if IS_ENABLED(CONFIG_HID_JABRA) + { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, HID_ANY_ID) }, +#endif #if IS_ENABLED(CONFIG_HID_KENSINGTON) { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, #endif -- cgit v1.2.3 From 99acedadde157a02b21761fd406ef7adc7615533 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Fri, 10 Nov 2017 11:50:00 -0800 Subject: HID: wacom: Properly handle AES serial number and tool type Current AES sensors relay tool type and serial number information with a different set of usages than those prescribed by the modern (i.e. MobileStudio Pro and newer) EMR tablet standard. To ensure the driver properly understands these usages, we modify them to be compatible. The identifying information is split across three consecutive fields: a 16-bit WACOM_HID_WT_SERIALNUMBER (which is more accurately described as WACOM_HID_WD_TOOLTYPE), a 32-bit HID_DG_TOOLSERIALNUMBER, and an 8-bit 0xFF000000 (which should be WACOM_HID_WD_SERIALHI). While we're at it, we also define proper min/max values since may may be undefined on some devices. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 42 +++++++++++++++++++++++++++++++++--------- drivers/hid/wacom_wac.h | 3 +++ 2 files changed, 36 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 16af6886e828..ff679ee3b358 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2086,6 +2086,27 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, break; case HID_DG_TOOLSERIALNUMBER: wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0); + + /* Adjust AES usages to match modern convention */ + if (usage->hid == WACOM_HID_WT_SERIALNUMBER && field->report_size == 16) { + if (field->index + 2 < field->report->maxfield) { + struct hid_field *a = field->report->field[field->index + 1]; + struct hid_field *b = field->report->field[field->index + 2]; + + if (a->maxusage > 0 && a->usage[0].hid == HID_DG_TOOLSERIALNUMBER && a->report_size == 32 && + b->maxusage > 0 && b->usage[0].hid == 0xFF000000 && b->report_size == 8) { + features->quirks |= WACOM_QUIRK_AESPEN; + usage->hid = WACOM_HID_WD_TOOLTYPE; + field->logical_minimum = S16_MIN; + field->logical_maximum = S16_MAX; + a->logical_minimum = S32_MIN; + a->logical_maximum = S32_MAX; + b->usage[0].hid = WACOM_HID_WD_SERIALHI; + b->logical_minimum = 0; + b->logical_maximum = U8_MAX; + } + } + } break; case WACOM_HID_WD_SENSE: features->quirks |= WACOM_QUIRK_SENSE; @@ -2093,15 +2114,18 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, break; case WACOM_HID_WD_SERIALHI: wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0); - set_bit(EV_KEY, input->evbit); - input_set_capability(input, EV_KEY, BTN_TOOL_PEN); - input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER); - input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH); - input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL); - input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH); - if (!(features->device_type & WACOM_DEVICETYPE_DIRECT)) { - input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE); - input_set_capability(input, EV_KEY, BTN_TOOL_LENS); + + if (!(features->quirks & WACOM_QUIRK_AESPEN)) { + set_bit(EV_KEY, input->evbit); + input_set_capability(input, EV_KEY, BTN_TOOL_PEN); + input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER); + input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH); + input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL); + input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH); + if (!(features->device_type & WACOM_DEVICETYPE_DIRECT)) { + input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE); + input_set_capability(input, EV_KEY, BTN_TOOL_LENS); + } } break; case WACOM_HID_WD_FINGERWHEEL: diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 64d8f014602e..6fe6d60f9ab5 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -86,6 +86,7 @@ /* device quirks */ #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001 #define WACOM_QUIRK_SENSE 0x0002 +#define WACOM_QUIRK_AESPEN 0x0004 #define WACOM_QUIRK_BATTERY 0x0008 /* device types */ @@ -107,6 +108,7 @@ #define WACOM_HID_WD_PEN (WACOM_HID_UP_WACOMDIGITIZER | 0x02) #define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36) #define WACOM_HID_WD_DIGITIZERFNKEYS (WACOM_HID_UP_WACOMDIGITIZER | 0x39) +#define WACOM_HID_WD_SERIALNUMBER (WACOM_HID_UP_WACOMDIGITIZER | 0x5b) #define WACOM_HID_WD_SERIALHI (WACOM_HID_UP_WACOMDIGITIZER | 0x5c) #define WACOM_HID_WD_TOOLTYPE (WACOM_HID_UP_WACOMDIGITIZER | 0x77) #define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132) @@ -150,6 +152,7 @@ #define WACOM_HID_WT_TOUCHSCREEN (WACOM_HID_UP_WACOMTOUCH | 0x04) #define WACOM_HID_WT_TOUCHPAD (WACOM_HID_UP_WACOMTOUCH | 0x05) #define WACOM_HID_WT_CONTACTMAX (WACOM_HID_UP_WACOMTOUCH | 0x55) +#define WACOM_HID_WT_SERIALNUMBER (WACOM_HID_UP_WACOMTOUCH | 0x5b) #define WACOM_HID_WT_X (WACOM_HID_UP_WACOMTOUCH | 0x130) #define WACOM_HID_WT_Y (WACOM_HID_UP_WACOMTOUCH | 0x131) -- cgit v1.2.3 From 83417206427bdf0fef9fa69957807194f25923c3 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Fri, 10 Nov 2017 11:50:01 -0800 Subject: HID: wacom: Queue events with missing type/serial data for later processing Userspace expects to receive tool type and serial number information for the active pen in the very first kernel report, if such data is supported by the hardware. While this expectation is not an issue for EMR devices, AES sensors will often send several packets worth of in- range data before relaying type/serial data to the kernel. Sending this data "late" can result in proximity-tracking issues by xf86-input-wacom, or an inability to distinguish different pens by input-wacom. Options for dealing with this situation include ignoring reports from the tablet until we get the necessary data, or using the information from the last-seen pen instead of the (eventual) real data. Neither option is particularly attractive: the former results in truncated strokes and the latter causes issues with switching between pens. This commit instead opts to queue up events with missing information until we receive a report which contains it. At that point, we can update the driver's state variables (id[0] and serial[0]) and replay the queued events. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/hid/wacom_wac.c | 1 + drivers/hid/wacom_wac.h | 3 ++ 3 files changed, 114 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index ee71ad9b6cc1..c9eadf632564 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -56,6 +56,107 @@ static int wacom_set_report(struct hid_device *hdev, u8 type, u8 *buf, return retval; } +static void wacom_wac_queue_insert(struct hid_device *hdev, + struct kfifo_rec_ptr_2 *fifo, + u8 *raw_data, int size) +{ + bool warned = false; + + while (kfifo_avail(fifo) < size) { + if (!warned) + hid_warn(hdev, "%s: kfifo has filled, starting to drop events\n", __func__); + warned = true; + + kfifo_skip(fifo); + } + + kfifo_in(fifo, raw_data, size); +} + +static void wacom_wac_queue_flush(struct hid_device *hdev, + struct kfifo_rec_ptr_2 *fifo) +{ + while (!kfifo_is_empty(fifo)) { + u8 buf[WACOM_PKGLEN_MAX]; + int size; + int err; + + size = kfifo_out(fifo, buf, sizeof(buf)); + err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false); + if (err) { + hid_warn(hdev, "%s: unable to flush event due to error %d\n", + __func__, err); + } + } +} + +static int wacom_wac_pen_serial_enforce(struct hid_device *hdev, + struct hid_report *report, u8 *raw_data, int size) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_features *features = &wacom_wac->features; + bool flush = false; + bool insert = false; + int i, j; + + if (wacom_wac->serial[0] || !(features->quirks & WACOM_QUIRK_TOOLSERIAL)) + return 0; + + /* Queue events which have invalid tool type or serial number */ + for (i = 0; i < report->maxfield; i++) { + for (j = 0; j < report->field[i]->maxusage; j++) { + struct hid_field *field = report->field[i]; + struct hid_usage *usage = &field->usage[j]; + unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); + unsigned int offset; + unsigned int size; + unsigned int value; + + if (equivalent_usage != HID_DG_INRANGE && + equivalent_usage != HID_DG_TOOLSERIALNUMBER && + equivalent_usage != WACOM_HID_WD_SERIALHI && + equivalent_usage != WACOM_HID_WD_TOOLTYPE) + continue; + + offset = field->report_offset; + size = field->report_size; + value = hid_field_extract(hdev, raw_data+1, offset + j * size, size); + + /* If we go out of range, we need to flush the queue ASAP */ + if (equivalent_usage == HID_DG_INRANGE) + value = !value; + + if (value) { + flush = true; + switch (equivalent_usage) { + case HID_DG_TOOLSERIALNUMBER: + wacom_wac->serial[0] = value; + break; + + case WACOM_HID_WD_SERIALHI: + wacom_wac->serial[0] |= ((__u64)value) << 32; + break; + + case WACOM_HID_WD_TOOLTYPE: + wacom_wac->id[0] = value; + break; + } + } + else { + insert = true; + } + } + } + + if (flush) + wacom_wac_queue_flush(hdev, &wacom_wac->pen_fifo); + else if (insert) + wacom_wac_queue_insert(hdev, &wacom_wac->pen_fifo, raw_data, size); + + return insert && !flush; +} + static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { @@ -64,6 +165,9 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, if (size > WACOM_PKGLEN_MAX) return 1; + if (wacom_wac_pen_serial_enforce(hdev, report, raw_data, size)) + return -1; + memcpy(wacom->wacom_wac.data, raw_data, size); wacom_wac_irq(&wacom->wacom_wac, size); @@ -2580,6 +2684,10 @@ static int wacom_probe(struct hid_device *hdev, goto fail; } + error = kfifo_alloc(&wacom_wac->pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL); + if (error) + goto fail; + wacom_wac->hid_data.inputmode = -1; wacom_wac->mode_report = -1; @@ -2643,6 +2751,8 @@ static void wacom_remove(struct hid_device *hdev) if (wacom->wacom_wac.features.type != REMOTE) wacom_release_resources(wacom); + kfifo_free(&wacom_wac->pen_fifo); + hid_set_drvdata(hdev, NULL); } diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index ff679ee3b358..7fa373225d8a 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2085,6 +2085,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS2, 0); break; case HID_DG_TOOLSERIALNUMBER: + features->quirks |= WACOM_QUIRK_TOOLSERIAL; wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0); /* Adjust AES usages to match modern convention */ diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 6fe6d60f9ab5..15d9c14fbdf7 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -11,6 +11,7 @@ #include #include +#include /* maximum packet length for USB/BT devices */ #define WACOM_PKGLEN_MAX 361 @@ -88,6 +89,7 @@ #define WACOM_QUIRK_SENSE 0x0002 #define WACOM_QUIRK_AESPEN 0x0004 #define WACOM_QUIRK_BATTERY 0x0008 +#define WACOM_QUIRK_TOOLSERIAL 0x0010 /* device types */ #define WACOM_DEVICETYPE_NONE 0x0000 @@ -339,6 +341,7 @@ struct wacom_wac { struct input_dev *pen_input; struct input_dev *touch_input; struct input_dev *pad_input; + struct kfifo_rec_ptr_2 pen_fifo; int pid; int num_contacts_left; u8 bt_features; -- cgit v1.2.3 From 847989e548ee76f06fd51b61c1fb887d1e86a239 Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Tue, 3 Oct 2017 11:19:21 -0700 Subject: HID: i2c-hid: Allow ACPI systems to specify "post-power-on-delay-ms" The property "post-power-on-delay-ms" allows a platform to specify the delay needed after power-on, but only via device trees currently. Use device_property_* instead of of_* reads to allow ACPI systems to also provide the same information. This is useful for Wacom hardware on ACPI systems. Signed-off-by: Rajat Jain Signed-off-by: Jiri Kosina --- .../devicetree/bindings/input/hid-over-i2c.txt | 2 +- drivers/hid/i2c-hid/i2c-hid.c | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.txt b/Documentation/devicetree/bindings/input/hid-over-i2c.txt index 28e8bd8b7d64..4d3da9d91de4 100644 --- a/Documentation/devicetree/bindings/input/hid-over-i2c.txt +++ b/Documentation/devicetree/bindings/input/hid-over-i2c.txt @@ -31,7 +31,7 @@ device-specific compatible properties, which should be used in addition to the - vdd-supply: phandle of the regulator that provides the supply voltage. - post-power-on-delay-ms: time required by the device after enabling its regulators - before it is ready for communication. Must be used with 'vdd-supply'. + or powering it on, before it is ready for communication. Example: diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index e054ee43c1e2..7230243b94d3 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -934,11 +934,6 @@ static int i2c_hid_of_probe(struct i2c_client *client, } pdata->hid_descriptor_address = val; - ret = of_property_read_u32(dev->of_node, "post-power-on-delay-ms", - &val); - if (!ret) - pdata->post_power_delay_ms = val; - return 0; } @@ -955,6 +950,16 @@ static inline int i2c_hid_of_probe(struct i2c_client *client, } #endif +static void i2c_hid_fwnode_probe(struct i2c_client *client, + struct i2c_hid_platform_data *pdata) +{ + u32 val; + + if (!device_property_read_u32(&client->dev, "post-power-on-delay-ms", + &val)) + pdata->post_power_delay_ms = val; +} + static int i2c_hid_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { @@ -998,6 +1003,9 @@ static int i2c_hid_probe(struct i2c_client *client, ihid->pdata = *platform_data; } + /* Parse platform agnostic common properties from ACPI / device tree */ + i2c_hid_fwnode_probe(client, &ihid->pdata); + ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd"); if (IS_ERR(ihid->pdata.supply)) { ret = PTR_ERR(ihid->pdata.supply); -- cgit v1.2.3 From fb55b4026d88a2bdc351f5485461d9314c885b60 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Nov 2017 12:57:07 +0100 Subject: HID: multitouch: Fix alphabetic sorting of mt_devices table. Fix alphabetic sorting of mt_devices hid_device_id table. Signed-off-by: Hans de Goede Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 65ea23be9677..9ef24b518f12 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1649,14 +1649,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, - /* Panasonic panels */ - { .driver_data = MT_CLS_PANASONIC, - MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, - USB_DEVICE_ID_PANABOARD_UBT780) }, - { .driver_data = MT_CLS_PANASONIC, - MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, - USB_DEVICE_ID_PANABOARD_UBT880) }, - /* Novatek Panel */ { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK, @@ -1667,6 +1659,14 @@ static const struct hid_device_id mt_devices[] = { HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_NTRIG, 0x1b05) }, + /* Panasonic panels */ + { .driver_data = MT_CLS_PANASONIC, + MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, + USB_DEVICE_ID_PANABOARD_UBT780) }, + { .driver_data = MT_CLS_PANASONIC, + MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, + USB_DEVICE_ID_PANABOARD_UBT880) }, + /* PixArt optical touch screen */ { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_PIXART, -- cgit v1.2.3 From af8dc4d0949092c4fba17ebb9e54448697c3d4e0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Nov 2017 12:57:08 +0100 Subject: HID: multitouch: Properly deal with Win8 PTP reports with 0 touches The Windows Precision Touchpad spec "Figure 4 Button Only Down and Up" and "Table 9 Report Sequence for Button Only Down and Up" indicate that the first packet of a (possibly hybrid mode multi-packet) frame may contain a contact-count of 0 if only a button is pressed and no fingers are detected. This means that a value of 0 for contact-count is a valid value and should be used as expected contact count when it is the first packet (num_received == 0), as extra check to make sure that this is the first packet of a buttons only frame, we also check that the timestamp is different. Signed-off-by: Hans de Goede Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 9ef24b518f12..d8b1cad74faf 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -119,6 +119,9 @@ struct mt_device { unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */ int cc_index; /* contact count field index in the report */ int cc_value_index; /* contact count value index in the field */ + int scantime_index; /* scantime field index in the report */ + int scantime_val_index; /* scantime value index in the field */ + int prev_scantime; /* scantime reported in the previous packet */ unsigned last_slot_field; /* the last field of a slot */ unsigned mt_report_id; /* the report ID of the multitouch device */ unsigned long initial_quirks; /* initial quirks state */ @@ -599,6 +602,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, EV_MSC, MSC_TIMESTAMP); input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP); mt_store_field(usage, td, hi); + /* Ignore if indexes are out of bounds. */ + if (field->index >= field->report->maxfield || + usage->usage_index >= field->report_count) + return 1; + td->scantime_index = field->index; + td->scantime_val_index = usage->usage_index; return 1; case HID_DG_CONTACTCOUNT: /* Ignore if indexes are out of bounds. */ @@ -855,9 +864,10 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, static void mt_touch_report(struct hid_device *hid, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hid); + __s32 cls = td->mtclass.name; struct hid_field *field; unsigned count; - int r, n; + int r, n, scantime = 0; /* sticky fingers release in progress, abort */ if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) @@ -867,12 +877,29 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) * Includes multi-packet support where subsequent * packets are sent with zero contactcount. */ + if (td->scantime_index >= 0) { + field = report->field[td->scantime_index]; + scantime = field->value[td->scantime_val_index]; + } if (td->cc_index >= 0) { struct hid_field *field = report->field[td->cc_index]; int value = field->value[td->cc_value_index]; - if (value) + + /* + * For Win8 PTPs the first packet (td->num_received == 0) may + * have a contactcount of 0 if there only is a button event. + * We double check that this is not a continuation packet + * of a possible multi-packet frame be checking that the + * timestamp has changed. + */ + if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) && + td->num_received == 0 && td->prev_scantime != scantime) + td->num_expected = value; + /* A non 0 contact count always indicates a first packet */ + else if (value) td->num_expected = value; } + td->prev_scantime = scantime; for (r = 0; r < report->maxfield; r++) { field = report->field[r]; @@ -1329,6 +1356,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) td->maxcontact_report_id = -1; td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; td->cc_index = -1; + td->scantime_index = -1; td->mt_report_id = -1; hid_set_drvdata(hdev, td); -- cgit v1.2.3 From 55746d28d66860bccaae20a67b55b9d5db7c14af Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Nov 2017 12:57:09 +0100 Subject: HID: multitouch: Only look at non touch fields in first packet of a frame Devices in "single finger hybrid mode" will send one report per finger, on some devices only the first report of such a multi-packet frame will contain a value for BTN_LEFT, in subsequent reports (if multiple fingers are down) the value is always 0, causing hid-mt to report BTN_LEFT going 1 - 0 - 1 - 0 when pressing a clickpad and putting down a second finger. This happens for example on USB 0603:0002 mt touchpads. This commit fixes this by only reporting non touch fields for the first packet of a (possibly) multi-packet frame. Signed-off-by: Hans de Goede Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index d8b1cad74faf..760c4a042e6a 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -787,9 +787,11 @@ static int mt_touch_event(struct hid_device *hid, struct hid_field *field, } static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) + struct hid_usage *usage, __s32 value, + bool first_packet) { struct mt_device *td = hid_get_drvdata(hid); + __s32 cls = td->mtclass.name; __s32 quirks = td->mtclass.quirks; struct input_dev *input = field->hidinput->input; @@ -846,6 +848,15 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, break; default: + /* + * For Win8 PTP touchpads we should only look at + * non finger/touch events in the first_packet of + * a (possible) multi-packet frame. + */ + if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) && + !first_packet) + return; + if (usage->type) input_event(input, usage->type, usage->code, value); @@ -866,6 +877,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) struct mt_device *td = hid_get_drvdata(hid); __s32 cls = td->mtclass.name; struct hid_field *field; + bool first_packet; unsigned count; int r, n, scantime = 0; @@ -901,6 +913,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) } td->prev_scantime = scantime; + first_packet = td->num_received == 0; for (r = 0; r < report->maxfield; r++) { field = report->field[r]; count = field->report_count; @@ -910,7 +923,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) for (n = 0; n < count; n++) mt_process_mt_event(hid, field, &field->usage[n], - field->value[n]); + field->value[n], first_packet); } if (td->num_received >= td->num_expected) -- cgit v1.2.3 From 127e71bd462b87301f5ff1d1fd686515b4a4af9c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Nov 2017 12:57:10 +0100 Subject: HID: multitouch: Combine all left-button events in a frame According to the Win8 Precision Touchpad spec, inside the HID_UP_BUTTON usage-page usage 1 is for a clickpad getting clicked, 2 for an external left button and 3 for an external right button. Since Linux uses BTN_LEFT for a clickpad being clicked we end up mapping both usage 1 and 2 to BTN_LEFT and if a single report contains both then we ended up always reporting the value of both in a single SYN, e.g. : BTN_LEFT 1, BTN_LEFT 0, SYN. This happens for example with Hantick HTT5288 i2c mt touchpads. This commit fixes this by not immediately reporting left button when we parse the report, but instead storing or-ing together the values and reporting the result from mt_sync_frame() when we've a complete frame. Signed-off-by: Hans de Goede Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 760c4a042e6a..76088f2cf598 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -122,6 +122,7 @@ struct mt_device { int scantime_index; /* scantime field index in the report */ int scantime_val_index; /* scantime value index in the field */ int prev_scantime; /* scantime reported in the previous packet */ + int left_button_state; /* left button state */ unsigned last_slot_field; /* the last field of a slot */ unsigned mt_report_id; /* the report ID of the multitouch device */ unsigned long initial_quirks; /* initial quirks state */ @@ -743,10 +744,16 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) */ static void mt_sync_frame(struct mt_device *td, struct input_dev *input) { + __s32 cls = td->mtclass.name; + + if (cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) + input_event(input, EV_KEY, BTN_LEFT, td->left_button_state); + input_mt_sync_frame(input); input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp); input_sync(input); td->num_received = 0; + td->left_button_state = 0; if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags)) set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags); else @@ -857,6 +864,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, !first_packet) return; + /* + * For Win8 PTP touchpads we map both the clickpad click + * and any "external" left buttons to BTN_LEFT if a + * device claims to have both we need to report 1 for + * BTN_LEFT if either is pressed, so we or all values + * together and report the result in mt_sync_frame(). + */ + if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) && + usage->type == EV_KEY && usage->code == BTN_LEFT) { + td->left_button_state |= value; + return; + } + if (usage->type) input_event(input, usage->type, usage->code, value); -- cgit v1.2.3 From 9abd04af951e5734c9d5cfee9b49790844b734cf Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 22 Nov 2017 11:19:51 +0100 Subject: HID: elo: clear BTN_LEFT mapping ELO devices have one Button usage in GenDesk field, which makes hid-input map it to BTN_LEFT; that confuses userspace, which then considers the device to be a mouse/touchpad instead of touchscreen. Fix that by unmapping BTN_LEFT and keeping only BTN_TOUCH in place. Signed-off-by: Jiri Kosina --- drivers/hid/hid-elo.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c index 0cd4f7216239..5eea6fe0d7bd 100644 --- a/drivers/hid/hid-elo.c +++ b/drivers/hid/hid-elo.c @@ -42,6 +42,12 @@ static int elo_input_configured(struct hid_device *hdev, { struct input_dev *input = hidinput->input; + /* + * ELO devices have one Button usage in GenDesk field, which makes + * hid-input map it to BTN_LEFT; that confuses userspace, which then + * considers the device to be a mouse/touchpad instead of touchscreen. + */ + clear_bit(BTN_LEFT, input->keybit); set_bit(BTN_TOUCH, input->keybit); set_bit(ABS_PRESSURE, input->absbit); input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0); -- cgit v1.2.3 From 4c59ff5a9a9c54cc26c807dc2fa6933f7e9fa4ef Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Sun, 29 Oct 2017 10:46:39 +0200 Subject: iwlwifi: mvm: check for short GI only for OFDM This bit will be used in CCK to indicate short preamble. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 3 ++- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index d1a40688d5e1..7cbea7890b0c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -439,7 +439,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->bw = RATE_INFO_BW_160; break; } - if (rate_n_flags & RATE_MCS_SGI_MSK) + if (!(rate_n_flags & RATE_MCS_CCK_MSK) && + rate_n_flags & RATE_MCS_SGI_MSK) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; if (rate_n_flags & RATE_HT_MCS_GF_MSK) rx_status->enc_flags |= RX_ENC_FLAG_HT_GF; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 76dc58381e1c..f444ff3a3396 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1010,7 +1010,9 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->bw = RATE_INFO_BW_160; break; } - if (rate_n_flags & RATE_MCS_SGI_MSK) + + if (!(rate_n_flags & RATE_MCS_CCK_MSK) && + rate_n_flags & RATE_MCS_SGI_MSK) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; if (rate_n_flags & RATE_HT_MCS_GF_MSK) rx_status->enc_flags |= RX_ENC_FLAG_HT_GF; -- cgit v1.2.3 From 087428d39721c7a721559977444dc7150132ce68 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Mon, 23 Oct 2017 15:02:42 +0300 Subject: iwlwifi: mvm: support MGMT frames in compressed BA In A000 family, compressed BA notifs can include MGMT frames, so don't fail RXs in such a case. While at it, since in A000 the TID for MGMT frames is 15, treat it in the RX flow as if received TID 8. This way we won't require special handling of this TID. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index d88c3685a6dd..0407ea30bb82 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1623,7 +1623,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, int freed; if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT || - tid >= IWL_MAX_TID_COUNT, + tid > IWL_MAX_TID_COUNT, "sta_id %d tid %d", sta_id, tid)) return; @@ -1678,7 +1678,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, if (ieee80211_is_data_qos(hdr->frame_control)) freed++; else - WARN_ON_ONCE(1); + WARN_ON_ONCE(tid != IWL_MAX_TID_COUNT); iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); @@ -1770,8 +1770,12 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) struct iwl_mvm_compressed_ba_tfd *ba_tfd = &ba_res->tfd[i]; + tid = ba_tfd->tid; + if (tid == IWL_MGMT_TID) + tid = IWL_MAX_TID_COUNT; + mvmsta->tid_data[i].lq_color = lq_color; - iwl_mvm_tx_reclaim(mvm, sta_id, ba_tfd->tid, + iwl_mvm_tx_reclaim(mvm, sta_id, tid, (int)(le16_to_cpu(ba_tfd->q_num)), le16_to_cpu(ba_tfd->tfd_index), &ba_info, -- cgit v1.2.3 From 992172e3aec19e5b0ea5b757ba40a146b9282d1e Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 19 Oct 2017 21:36:04 +0300 Subject: iwlwifi: mvm: rs: don't override the rate history in the search cycle When we are in a search cycle, we try different combinations of parameters. Those combinations are called 'columns'. When we switch to a new column, we first need to check if this column has a suitable rate, if not, we can't try it. This means we must not erase the statistics we gathered for the previous column until we are sure that we are indeed switching column. The code that tries to switch to a new column first sets a whole bunch of things for the new column, and only then checks that we can find suitable rates in that column. While doing that, the code mistakenly erased the rate statistics. This code was right until struct iwl_scale_tbl_info grew up for TPC. Fix this to make sure we don't erase the rate statistics until we are sure that we can indeed switch to the new column. Note that this bug is really harmless since it causes a change in the behavior only when we can't find any rate in the new column which should really not happen. In the case we do find a suitable we reset the rate statistics a few lines later anyway. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index c69515ed72df..fbfa5eafcc93 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -1877,12 +1877,10 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, struct rs_rate *rate = &search_tbl->rate; const struct rs_tx_column *column = &rs_tx_columns[col_id]; const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column]; - u32 sz = (sizeof(struct iwl_scale_tbl_info) - - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); unsigned long rate_mask = 0; u32 rate_idx = 0; - memcpy(search_tbl, tbl, sz); + memcpy(search_tbl, tbl, offsetof(struct iwl_scale_tbl_info, win)); rate->sgi = column->sgi; rate->ant = column->ant; -- cgit v1.2.3 From 357969c6b5460ce2b01fc249fb734a6f7063efeb Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 1 Nov 2017 13:27:49 +0200 Subject: iwlwifi: mvm: revert support new Coex firmware API This new API will not be used, remove the code that supports it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/coex.h | 30 --------------------- drivers/net/wireless/intel/iwlwifi/fw/file.h | 3 --- drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 33 +++++------------------- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 12 +++------ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 ----- 5 files changed, 9 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/coex.h b/drivers/net/wireless/intel/iwlwifi/fw/api/coex.h index d09555afe2c5..87c1ddea75ae 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/coex.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/coex.h @@ -188,11 +188,6 @@ enum iwl_bt_mxbox_dw3 { BT_MBOX(3, UPDATE_REQUEST, 21, 1), }; -enum iwl_bt_mxbox_dw4 { - BT_MBOX(4, ATS_BT_INTERVAL, 0, 7), - BT_MBOX(4, ATS_BT_ACTIVE_MAX_TH, 7, 7), -}; - #define BT_MBOX_MSG(_notif, _num, _field) \ ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ >> BT_MBOX##_num##_##_field##_POS) @@ -232,31 +227,6 @@ enum iwl_bt_ci_compliance { * @reserved: reserved */ struct iwl_bt_coex_profile_notif { - __le32 mbox_msg[8]; - __le32 msg_idx; - __le32 bt_ci_compliance; - - __le32 primary_ch_lut; - __le32 secondary_ch_lut; - __le32 bt_activity_grading; - u8 ttc_status; - u8 rrc_status; - __le16 reserved; -} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_5 */ - -/** - * struct iwl_bt_coex_profile_notif - notification about BT coex - * @mbox_msg: message from BT to WiFi - * @msg_idx: the index of the message - * @bt_ci_compliance: enum %iwl_bt_ci_compliance - * @primary_ch_lut: LUT used for primary channel &enum iwl_bt_coex_lut_type - * @secondary_ch_lut: LUT used for secondary channel &enum iwl_bt_coex_lut_type - * @bt_activity_grading: the activity of BT &enum iwl_bt_activity_grading - * @ttc_status: is TTC enabled - one bit per PHY - * @rrc_status: is RRC enabled - one bit per PHY - * @reserved: reserved - */ -struct iwl_bt_coex_profile_notif_v4 { __le32 mbox_msg[4]; __le32 msg_idx; __le32 bt_ci_compliance; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 740d97093d1c..e52678c8f899 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -246,8 +246,6 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; * @IWL_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement. * @IWL_UCODE_TLV_API_NAN2_VER2: This ucode supports NAN API version 2 * @IWL_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used - * @IWL_UCODE_TLV_API_ATS_COEX_EXTERNAL: the coex notification is enlared to - * include information about ACL time sharing. * @IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY: Quota command includes a field * indicating low latency direction. * @@ -266,7 +264,6 @@ enum iwl_ucode_tlv_api { /* API Set 1 */ IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE = (__force iwl_ucode_tlv_api_t)34, IWL_UCODE_TLV_API_NEW_RX_STATS = (__force iwl_ucode_tlv_api_t)35, - IWL_UCODE_TLV_API_COEX_ATS_EXTERNAL = (__force iwl_ucode_tlv_api_t)37, IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY = (__force iwl_ucode_tlv_api_t)38, NUM_IWL_UCODE_TLV_API diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c index 79c80f181f7d..890dbfff3a06 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c @@ -7,7 +7,6 @@ * * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2017 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -34,7 +33,6 @@ * * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2017 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -514,36 +512,17 @@ void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data; - if (!iwl_mvm_has_new_ats_coex_api(mvm)) { - struct iwl_bt_coex_profile_notif_v4 *v4 = (void *)pkt->data; - - mvm->last_bt_notif.mbox_msg[0] = v4->mbox_msg[0]; - mvm->last_bt_notif.mbox_msg[1] = v4->mbox_msg[1]; - mvm->last_bt_notif.mbox_msg[2] = v4->mbox_msg[2]; - mvm->last_bt_notif.mbox_msg[3] = v4->mbox_msg[3]; - mvm->last_bt_notif.msg_idx = v4->msg_idx; - mvm->last_bt_notif.bt_ci_compliance = v4->bt_ci_compliance; - mvm->last_bt_notif.primary_ch_lut = v4->primary_ch_lut; - mvm->last_bt_notif.secondary_ch_lut = v4->secondary_ch_lut; - mvm->last_bt_notif.bt_activity_grading = - v4->bt_activity_grading; - mvm->last_bt_notif.ttc_status = v4->ttc_status; - mvm->last_bt_notif.rrc_status = v4->rrc_status; - } else { - /* save this notification for future use: rssi fluctuations */ - memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); - } - IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); - IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", - mvm->last_bt_notif.bt_ci_compliance); + IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n", - le32_to_cpu(mvm->last_bt_notif.primary_ch_lut)); + le32_to_cpu(notif->primary_ch_lut)); IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n", - le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut)); + le32_to_cpu(notif->secondary_ch_lut)); IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n", - le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)); + le32_to_cpu(notif->bt_activity_grading)); + /* remember this notification for future use: rssi fluctuations */ + memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); iwl_mvm_bt_coex_notif_handle(mvm); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 2ff594f11259..dad18a609d9a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -470,8 +470,7 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf, } static -int iwl_mvm_coex_dump_mbox(struct iwl_mvm *mvm, - struct iwl_bt_coex_profile_notif *notif, char *buf, +int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf, int pos, int bufsz) { pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n"); @@ -525,12 +524,7 @@ int iwl_mvm_coex_dump_mbox(struct iwl_mvm *mvm, BT_MBOX_PRINT(3, INBAND_P, false); BT_MBOX_PRINT(3, MSG_TYPE_2, false); BT_MBOX_PRINT(3, SSN_2, false); - BT_MBOX_PRINT(3, UPDATE_REQUEST, !iwl_mvm_has_new_ats_coex_api(mvm)); - - if (iwl_mvm_has_new_ats_coex_api(mvm)) { - BT_MBOX_PRINT(4, ATS_BT_INTERVAL, false); - BT_MBOX_PRINT(4, ATS_BT_ACTIVE_MAX_TH, true); - } + BT_MBOX_PRINT(3, UPDATE_REQUEST, true); return pos; } @@ -549,7 +543,7 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, mutex_lock(&mvm->mutex); - pos += iwl_mvm_coex_dump_mbox(mvm, notif, buf, pos, bufsz); + pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n", notif->bt_ci_compliance); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 0e18c5066f04..bd6ba550c809 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1263,12 +1263,6 @@ static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm) IWL_UCODE_TLV_API_NEW_RX_STATS); } -static inline bool iwl_mvm_has_new_ats_coex_api(struct iwl_mvm *mvm) -{ - return fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_COEX_ATS_EXTERNAL); -} - static inline bool iwl_mvm_has_quota_low_latency(struct iwl_mvm *mvm) { return fw_has_api(&mvm->fw->ucode_capa, -- cgit v1.2.3 From debdc23b17cb2b363b6f970d9d9c773df6cc7532 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 26 Oct 2017 22:57:57 +0200 Subject: iwlwifi: mvm: remove TCP wakeup support This feature was actually removed from firmware, but without ever telling the driver. Since nobody is actually using it, just remove it entirely without bothering with a capability check. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 232 +--------------------- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 24 --- 2 files changed, 1 insertion(+), 255 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index b1f73dcabd31..0e6cf39285f4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -429,231 +429,6 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, return err; } -enum iwl_mvm_tcp_packet_type { - MVM_TCP_TX_SYN, - MVM_TCP_RX_SYNACK, - MVM_TCP_TX_DATA, - MVM_TCP_RX_ACK, - MVM_TCP_RX_WAKE, - MVM_TCP_TX_FIN, -}; - -static __le16 pseudo_hdr_check(int len, __be32 saddr, __be32 daddr) -{ - __sum16 check = tcp_v4_check(len, saddr, daddr, 0); - return cpu_to_le16(be16_to_cpu((__force __be16)check)); -} - -static void iwl_mvm_build_tcp_packet(struct ieee80211_vif *vif, - struct cfg80211_wowlan_tcp *tcp, - void *_pkt, u8 *mask, - __le16 *pseudo_hdr_csum, - enum iwl_mvm_tcp_packet_type ptype) -{ - struct { - struct ethhdr eth; - struct iphdr ip; - struct tcphdr tcp; - u8 data[]; - } __packed *pkt = _pkt; - u16 ip_tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr); - int i; - - pkt->eth.h_proto = cpu_to_be16(ETH_P_IP), - pkt->ip.version = 4; - pkt->ip.ihl = 5; - pkt->ip.protocol = IPPROTO_TCP; - - switch (ptype) { - case MVM_TCP_TX_SYN: - case MVM_TCP_TX_DATA: - case MVM_TCP_TX_FIN: - memcpy(pkt->eth.h_dest, tcp->dst_mac, ETH_ALEN); - memcpy(pkt->eth.h_source, vif->addr, ETH_ALEN); - pkt->ip.ttl = 128; - pkt->ip.saddr = tcp->src; - pkt->ip.daddr = tcp->dst; - pkt->tcp.source = cpu_to_be16(tcp->src_port); - pkt->tcp.dest = cpu_to_be16(tcp->dst_port); - /* overwritten for TX SYN later */ - pkt->tcp.doff = sizeof(struct tcphdr) / 4; - pkt->tcp.window = cpu_to_be16(65000); - break; - case MVM_TCP_RX_SYNACK: - case MVM_TCP_RX_ACK: - case MVM_TCP_RX_WAKE: - memcpy(pkt->eth.h_dest, vif->addr, ETH_ALEN); - memcpy(pkt->eth.h_source, tcp->dst_mac, ETH_ALEN); - pkt->ip.saddr = tcp->dst; - pkt->ip.daddr = tcp->src; - pkt->tcp.source = cpu_to_be16(tcp->dst_port); - pkt->tcp.dest = cpu_to_be16(tcp->src_port); - break; - default: - WARN_ON(1); - return; - } - - switch (ptype) { - case MVM_TCP_TX_SYN: - /* firmware assumes 8 option bytes - 8 NOPs for now */ - memset(pkt->data, 0x01, 8); - ip_tot_len += 8; - pkt->tcp.doff = (sizeof(struct tcphdr) + 8) / 4; - pkt->tcp.syn = 1; - break; - case MVM_TCP_TX_DATA: - ip_tot_len += tcp->payload_len; - memcpy(pkt->data, tcp->payload, tcp->payload_len); - pkt->tcp.psh = 1; - pkt->tcp.ack = 1; - break; - case MVM_TCP_TX_FIN: - pkt->tcp.fin = 1; - pkt->tcp.ack = 1; - break; - case MVM_TCP_RX_SYNACK: - pkt->tcp.syn = 1; - pkt->tcp.ack = 1; - break; - case MVM_TCP_RX_ACK: - pkt->tcp.ack = 1; - break; - case MVM_TCP_RX_WAKE: - ip_tot_len += tcp->wake_len; - pkt->tcp.psh = 1; - pkt->tcp.ack = 1; - memcpy(pkt->data, tcp->wake_data, tcp->wake_len); - break; - } - - switch (ptype) { - case MVM_TCP_TX_SYN: - case MVM_TCP_TX_DATA: - case MVM_TCP_TX_FIN: - pkt->ip.tot_len = cpu_to_be16(ip_tot_len); - pkt->ip.check = ip_fast_csum(&pkt->ip, pkt->ip.ihl); - break; - case MVM_TCP_RX_WAKE: - for (i = 0; i < DIV_ROUND_UP(tcp->wake_len, 8); i++) { - u8 tmp = tcp->wake_mask[i]; - mask[i + 6] |= tmp << 6; - if (i + 1 < DIV_ROUND_UP(tcp->wake_len, 8)) - mask[i + 7] = tmp >> 2; - } - /* fall through for ethernet/IP/TCP headers mask */ - case MVM_TCP_RX_SYNACK: - case MVM_TCP_RX_ACK: - mask[0] = 0xff; /* match ethernet */ - /* - * match ethernet, ip.version, ip.ihl - * the ip.ihl half byte is really masked out by firmware - */ - mask[1] = 0x7f; - mask[2] = 0x80; /* match ip.protocol */ - mask[3] = 0xfc; /* match ip.saddr, ip.daddr */ - mask[4] = 0x3f; /* match ip.daddr, tcp.source, tcp.dest */ - mask[5] = 0x80; /* match tcp flags */ - /* leave rest (0 or set for MVM_TCP_RX_WAKE) */ - break; - }; - - *pseudo_hdr_csum = pseudo_hdr_check(ip_tot_len - sizeof(struct iphdr), - pkt->ip.saddr, pkt->ip.daddr); -} - -static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct cfg80211_wowlan_tcp *tcp) -{ - struct iwl_wowlan_remote_wake_config *cfg; - struct iwl_host_cmd cmd = { - .id = REMOTE_WAKE_CONFIG_CMD, - .len = { sizeof(*cfg), }, - .dataflags = { IWL_HCMD_DFL_NOCOPY, }, - }; - int ret; - - if (!tcp) - return 0; - - cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); - if (!cfg) - return -ENOMEM; - cmd.data[0] = cfg; - - cfg->max_syn_retries = 10; - cfg->max_data_retries = 10; - cfg->tcp_syn_ack_timeout = 1; /* seconds */ - cfg->tcp_ack_timeout = 1; /* seconds */ - - /* SYN (TX) */ - iwl_mvm_build_tcp_packet( - vif, tcp, cfg->syn_tx.data, NULL, - &cfg->syn_tx.info.tcp_pseudo_header_checksum, - MVM_TCP_TX_SYN); - cfg->syn_tx.info.tcp_payload_length = 0; - - /* SYN/ACK (RX) */ - iwl_mvm_build_tcp_packet( - vif, tcp, cfg->synack_rx.data, cfg->synack_rx.rx_mask, - &cfg->synack_rx.info.tcp_pseudo_header_checksum, - MVM_TCP_RX_SYNACK); - cfg->synack_rx.info.tcp_payload_length = 0; - - /* KEEPALIVE/ACK (TX) */ - iwl_mvm_build_tcp_packet( - vif, tcp, cfg->keepalive_tx.data, NULL, - &cfg->keepalive_tx.info.tcp_pseudo_header_checksum, - MVM_TCP_TX_DATA); - cfg->keepalive_tx.info.tcp_payload_length = - cpu_to_le16(tcp->payload_len); - cfg->sequence_number_offset = tcp->payload_seq.offset; - /* length must be 0..4, the field is little endian */ - cfg->sequence_number_length = tcp->payload_seq.len; - cfg->initial_sequence_number = cpu_to_le32(tcp->payload_seq.start); - cfg->keepalive_interval = cpu_to_le16(tcp->data_interval); - if (tcp->payload_tok.len) { - cfg->token_offset = tcp->payload_tok.offset; - cfg->token_length = tcp->payload_tok.len; - cfg->num_tokens = - cpu_to_le16(tcp->tokens_size % tcp->payload_tok.len); - memcpy(cfg->tokens, tcp->payload_tok.token_stream, - tcp->tokens_size); - } else { - /* set tokens to max value to almost never run out */ - cfg->num_tokens = cpu_to_le16(65535); - } - - /* ACK (RX) */ - iwl_mvm_build_tcp_packet( - vif, tcp, cfg->keepalive_ack_rx.data, - cfg->keepalive_ack_rx.rx_mask, - &cfg->keepalive_ack_rx.info.tcp_pseudo_header_checksum, - MVM_TCP_RX_ACK); - cfg->keepalive_ack_rx.info.tcp_payload_length = 0; - - /* WAKEUP (RX) */ - iwl_mvm_build_tcp_packet( - vif, tcp, cfg->wake_rx.data, cfg->wake_rx.rx_mask, - &cfg->wake_rx.info.tcp_pseudo_header_checksum, - MVM_TCP_RX_WAKE); - cfg->wake_rx.info.tcp_payload_length = - cpu_to_le16(tcp->wake_len); - - /* FIN */ - iwl_mvm_build_tcp_packet( - vif, tcp, cfg->fin_tx.data, NULL, - &cfg->fin_tx.info.tcp_pseudo_header_checksum, - MVM_TCP_TX_FIN); - cfg->fin_tx.info.tcp_payload_length = 0; - - ret = iwl_mvm_send_cmd(mvm, &cmd); - kfree(cfg); - - return ret; -} - static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *ap_sta) { @@ -1082,12 +857,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm, if (ret) return ret; - ret = iwl_mvm_send_proto_offload(mvm, vif, false, true, 0); - if (ret) - return ret; - - ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp); - return ret; + return iwl_mvm_send_proto_offload(mvm, vif, false, true, 0); } static int diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 3e92a117c0b8..149d301e5e98 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -114,29 +114,6 @@ static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { }, }; -#ifdef CONFIG_PM_SLEEP -static const struct nl80211_wowlan_tcp_data_token_feature -iwl_mvm_wowlan_tcp_token_feature = { - .min_len = 0, - .max_len = 255, - .bufsize = IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS, -}; - -static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = { - .tok = &iwl_mvm_wowlan_tcp_token_feature, - .data_payload_max = IWL_WOWLAN_TCP_MAX_PACKET_LEN - - sizeof(struct ethhdr) - - sizeof(struct iphdr) - - sizeof(struct tcphdr), - .data_interval_max = 65535, /* __le16 in API */ - .wake_payload_max = IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN - - sizeof(struct ethhdr) - - sizeof(struct iphdr) - - sizeof(struct tcphdr), - .seq = true, -}; -#endif - #ifdef CONFIG_IWLWIFI_BCAST_FILTERING /* * Use the reserved field to indicate magic values. @@ -702,7 +679,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) mvm->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN; mvm->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN; mvm->wowlan.max_nd_match_sets = IWL_SCAN_MAX_PROFILES; - mvm->wowlan.tcp = &iwl_mvm_wowlan_tcp_support; hw->wiphy->wowlan = &mvm->wowlan; } #endif -- cgit v1.2.3 From 76c5bcb3941d5b35248c1f4bc05c50e0af2a03e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 2 Nov 2017 10:02:04 +0200 Subject: iwlwifi: print the version number of the firmware in hex Starting from a version 35, the minor version should be printed in hexa. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 4b224d7d967c..de8f6ae2f51b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -919,9 +919,14 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, minor = le32_to_cpup(ptr++); local_comp = le32_to_cpup(ptr); - snprintf(drv->fw.fw_version, - sizeof(drv->fw.fw_version), "%u.%u.%u", - major, minor, local_comp); + if (major >= 35) + snprintf(drv->fw.fw_version, + sizeof(drv->fw.fw_version), + "%u.%08x.%u", major, minor, local_comp); + else + snprintf(drv->fw.fw_version, + sizeof(drv->fw.fw_version), + "%u.%u.%u", major, minor, local_comp); break; } case IWL_UCODE_TLV_FW_DBG_DEST: { -- cgit v1.2.3 From dfd4b08cf44f27587e2053e006e43a1603328006 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 31 Oct 2017 15:54:50 +0200 Subject: iwlwifi: dbg: allow wrt collection before ALIVE Even if no ALIVE was received, the WRT data can still be collected. Add this. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 8106fd4be996..67aefc8fc9ac 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -964,7 +964,20 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, if (trigger) delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay)); - if (WARN(fwrt->trans->state == IWL_TRANS_NO_FW, + /* + * If the loading of the FW completed successfully, the next step is to + * get the SMEM config data. Thus, if fwrt->smem_cfg.num_lmacs is non + * zero, the FW was already loaded successully. If the state is "NO_FW" + * in such a case - WARN and exit, since FW may be dead. Otherwise, we + * can try to collect the data, since FW might just not be fully + * loaded (no "ALIVE" yet), and the debug data is accessible. + * + * Corner case: got the FW alive but crashed before getting the SMEM + * config. In such a case, due to HW access problems, we might + * collect garbage. + */ + if (WARN((fwrt->trans->state == IWL_TRANS_NO_FW) && + fwrt->smem_cfg.num_lmacs, "Can't collect dbg data when FW isn't alive\n")) return -EIO; -- cgit v1.2.3 From fd3e454366603c8e35b31c52195b1ea8798a8fff Mon Sep 17 00:00:00 2001 From: Ganapatrao Kulkarni Date: Wed, 15 Nov 2017 22:59:02 +0530 Subject: ACPI / NUMA: ia64: Parse all entries of SRAT memory affinity table In current implementation, SRAT Memory Affinity Structure table parsing is restricted to number of maximum memblocks allowed (NR_NODE_MEMBLKS). However NR_NODE_MEMBLKS is defined individually as per architecture requirements. Hence removing the restriction of SRAT Memory Affinity Structure parsing in ACPI driver code and let architecture code check for allowed memblocks count. This check is already there in the x86 code, so do the same on ia64. Signed-off-by: Ganapatrao Kulkarni Acked-by: Tony Luck Signed-off-by: Rafael J. Wysocki --- arch/ia64/kernel/acpi.c | 5 +++++ drivers/acpi/numa.c | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 1d29b2f8726b..1dacbf5e9e09 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -504,6 +504,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) return -1; + if (num_node_memblks >= NR_NODE_MEMBLKS) { + pr_err("NUMA: too many memblk ranges\n"); + return -EINVAL; + } + /* record this node in proximity bitmap */ pxm_bit_set(pxm); diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 917f1cc0fda4..8ccaae3550d2 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -460,8 +460,7 @@ int __init acpi_numa_init(void) srat_proc, ARRAY_SIZE(srat_proc), 0); cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, - acpi_parse_memory_affinity, - NR_NODE_MEMBLKS); + acpi_parse_memory_affinity, 0); } /* SLIT: System Locality Information Table */ -- cgit v1.2.3 From 8f275615a623183584b1604789cdcb240342ffbc Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Fri, 17 Nov 2017 15:40:14 -0800 Subject: ACPICA: Fix an off-by-one error in acpi_get_timer_duration(). ACPICA commit b4fd33f3c2af014aeec978d46392d286fd7f52b3 Delta calculation has an off-by-one error when there is a rollover. For example, when start_ticks is 0x00FFFFFF and end_ticks is 0x00000000 (for 24-bit timer), delta_ticks should be 1 (one) but it was 0 (zero). Link: https://github.com/acpica/acpica/commit/b4fd33f3 Signed-off-by: Jung-uk Kim Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/hwtimer.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index a2f4e25d45b1..5b4282902a83 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -150,10 +150,10 @@ ACPI_EXPORT_SYMBOL(acpi_get_timer) * ******************************************************************************/ acpi_status -acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) +acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 *time_elapsed) { acpi_status status; - u32 delta_ticks; + u64 delta_ticks; u64 quotient; ACPI_FUNCTION_TRACE(acpi_get_timer_duration); @@ -168,30 +168,29 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) return_ACPI_STATUS(AE_SUPPORT); } + if (start_ticks == end_ticks) { + *time_elapsed = 0; + return_ACPI_STATUS(AE_OK); + } + /* * Compute Tick Delta: * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. */ - if (start_ticks < end_ticks) { - delta_ticks = end_ticks - start_ticks; - } else if (start_ticks > end_ticks) { + delta_ticks = end_ticks; + if (start_ticks > end_ticks) { if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { /* 24-bit Timer */ - delta_ticks = - (((0x00FFFFFF - start_ticks) + - end_ticks) & 0x00FFFFFF); + delta_ticks |= (u64)1 << 24; } else { /* 32-bit Timer */ - delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks; + delta_ticks |= (u64)1 << 32; } - } else { /* start_ticks == end_ticks */ - - *time_elapsed = 0; - return_ACPI_STATUS(AE_OK); } + delta_ticks -= start_ticks; /* * Compute Duration (Requires a 64-bit multiply and divide): @@ -199,10 +198,10 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) * time_elapsed (microseconds) = * (delta_ticks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; */ - status = acpi_ut_short_divide(((u64)delta_ticks) * ACPI_USEC_PER_SEC, + status = acpi_ut_short_divide(delta_ticks * ACPI_USEC_PER_SEC, ACPI_PM_TIMER_FREQUENCY, "ient, NULL); - *time_elapsed = (u32) quotient; + *time_elapsed = (u32)quotient; return_ACPI_STATUS(status); } -- cgit v1.2.3 From 5c74663e20bca25fa37d4d488265367b8d6b975f Mon Sep 17 00:00:00 2001 From: Erik Schmauss Date: Fri, 17 Nov 2017 15:40:15 -0800 Subject: ACPICA: Disassembler: reset parser_state's Aml pointer when parsing bad externals ACPICA commit e7e25137471d7f75960fdb8caf757db0426245ca Link: https://github.com/acpica/acpica/commit/e7e25137 Signed-off-by: Erik Schmauss Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/psobject.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c index 0bef6df71bba..8cbe36159376 100644 --- a/drivers/acpi/acpica/psobject.c +++ b/drivers/acpi/acpica/psobject.c @@ -382,6 +382,7 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, walk_state->aml - walk_state->parser_state.aml_start); walk_state->aml = walk_state->parser_state.aml + 2; + walk_state->parser_state.aml = walk_state->aml; return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); } #endif -- cgit v1.2.3 From ee470f08b07d6c3a07a8d9dd7d1817e68cdf3b86 Mon Sep 17 00:00:00 2001 From: Erik Schmauss Date: Fri, 17 Nov 2017 15:40:16 -0800 Subject: ACPICA: disassembler: getting rid of error message ACPICA commit 7d542c6f97e27f7d0e90be1afd98097c3840e007 This error message tends to clutter up the disassembled ASL file with information that is unnecessary. Link: https://github.com/acpica/acpica/commit/7d542c6f Signed-off-by: Erik Schmauss Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/psobject.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c index 8cbe36159376..c0b179883ff2 100644 --- a/drivers/acpi/acpica/psobject.c +++ b/drivers/acpi/acpica/psobject.c @@ -372,15 +372,8 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, * external declaration opcode. Setting walk_state->Aml to * walk_state->parser_state.Aml + 2 moves increments the * walk_state->Aml past the object type and the paramcount of the - * external opcode. For the error message, only print the AML - * offset. We could attempt to print the name but this may cause - * a segmentation fault when printing the namepath because the - * AML may be incorrect. + * external opcode. */ - acpi_os_printf - ("// Invalid external declaration at AML offset 0x%x.\n", - walk_state->aml - - walk_state->parser_state.aml_start); walk_state->aml = walk_state->parser_state.aml + 2; walk_state->parser_state.aml = walk_state->aml; return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); -- cgit v1.2.3 From 29ad1f88ab7dd6c220ff9f5b9faed718b443f4a4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 17 Nov 2017 15:40:17 -0800 Subject: ACPICA: Avoid null pointer dereference on Op. ACPICA commit 08a00639b0d6756e8ba1421419fc3728904651d9 The calls to acpi_os_acquire_object can result in a null being assigned to Op (for example if a mutex acquire fails) which can lead to a null pointer dereference on Op on the call to ASL_CV_TRANSFER_COMMENTS (via function cv_transfer_comments). Move the block into the previous block that checks for a null Op so that we never can call cv_transfer_comments with a null Op. Detected by: coverity_scan CID#1371660 ("Dereference after null check") Link: https://github.com/acpica/acpica/commit/08a00639 Signed-off-by: Colin Ian King Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/psutils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c index 02642760cb93..e15b636b1d4b 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c @@ -158,10 +158,10 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml) if (opcode == AML_SCOPE_OP) { acpi_gbl_current_scope = op; } - } - if (gbl_capture_comments) { - ASL_CV_TRANSFER_COMMENTS(op); + if (gbl_capture_comments) { + ASL_CV_TRANSFER_COMMENTS(op); + } } return (op); -- cgit v1.2.3 From 164a08cee1358e360c47fcb26a7720461d5853a5 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 17 Nov 2017 15:40:18 -0800 Subject: ACPICA: Dispatcher: Introduce timeout mechanism for infinite loop detection ACPICA commit 9605023e7e6d1f05581502766c8cf2905bcc03d9 This patch implements a new infinite loop detection mechanism to replace the old one, it uses acpi_os_get_timer() to limit loop execution into a determined time slice. This is useful in case some hardware/firmware operations really require the AML interpreter to wait while the old mechanism could expire too fast on recent machines. The new mechanism converts old acpi_gbl_max_loop_iterations to store the user configurable value for the new mechanism in order to allow users to be still able to configure this value for acpiexec via command line. This patch also removes wrong initilization code of acpi_gbl_max_loop_iterations accordingly (it should have been initialized by ACPI_INIT_GLOBAL, and the default value is also properly tuned for acpiexec). Reported by M. Foronda, fixed by Lv Zheng. Link: https://github.com/acpica/acpica/commit/9605023e Link: https://bugzilla.kernel.org/show_bug.cgi?id=156501 Reported-by: M. Foronda Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 2 +- drivers/acpi/acpica/dscontrol.c | 16 +++++++++------- drivers/acpi/acpica/utinit.c | 1 - include/acpi/acconfig.h | 4 ++-- include/acpi/acpixf.h | 4 ++-- include/acpi/actypes.h | 2 ++ 6 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 0d45b8bb1678..bed041d41596 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -622,7 +622,7 @@ struct acpi_control_state { union acpi_parse_object *predicate_op; u8 *aml_predicate_start; /* Start of if/while predicate */ u8 *package_end; /* End of if/while block */ - u32 loop_count; /* While() loop counter */ + u64 loop_timeout; /* While() loop timeout */ }; /* diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index f470e81b0499..244075dbc03a 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -118,6 +118,8 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, control_state->control.package_end = walk_state->parser_state.pkg_end; control_state->control.opcode = op->common.aml_opcode; + control_state->control.loop_timeout = acpi_os_get_timer() + + (u64)(acpi_gbl_max_loop_iterations * ACPI_100NSEC_PER_SEC); /* Push the control state on this walk's control stack */ @@ -206,14 +208,14 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state, /* Predicate was true, the body of the loop was just executed */ /* - * This loop counter mechanism allows the interpreter to escape - * possibly infinite loops. This can occur in poorly written AML - * when the hardware does not respond within a while loop and the - * loop does not implement a timeout. + * This infinite loop detection mechanism allows the interpreter + * to escape possibly infinite loops. This can occur in poorly + * written AML when the hardware does not respond within a while + * loop and the loop does not implement a timeout. */ - control_state->control.loop_count++; - if (control_state->control.loop_count > - acpi_gbl_max_loop_iterations) { + if (ACPI_TIME_AFTER(acpi_os_get_timer(), + control_state->control. + loop_timeout)) { status = AE_AML_INFINITE_LOOP; break; } diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index 23e766d1691d..45eeb0dcf283 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -206,7 +206,6 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_next_owner_id_offset = 0; acpi_gbl_debugger_configuration = DEBUGGER_THREADING; acpi_gbl_osi_mutex = NULL; - acpi_gbl_max_loop_iterations = ACPI_MAX_LOOP_COUNT; /* Hardware oriented */ diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 6db3b4668b1a..ffe364fa4040 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -145,9 +145,9 @@ #define ACPI_ADDRESS_RANGE_MAX 2 -/* Maximum number of While() loops before abort */ +/* Maximum time (default 30s) of While() loops before abort */ -#define ACPI_MAX_LOOP_COUNT 0x000FFFFF +#define ACPI_MAX_LOOP_TIMEOUT 30 /****************************************************************************** * diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index e1dd1a8d42b6..1a4322db0274 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -260,11 +260,11 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_osi_data, 0); ACPI_INIT_GLOBAL(u8, acpi_gbl_reduced_hardware, FALSE); /* - * Maximum number of While() loop iterations before forced method abort. + * Maximum timeout for While() loop iterations before forced method abort. * This mechanism is intended to prevent infinite loops during interpreter * execution within a host kernel. */ -ACPI_INIT_GLOBAL(u32, acpi_gbl_max_loop_iterations, ACPI_MAX_LOOP_COUNT); +ACPI_INIT_GLOBAL(u32, acpi_gbl_max_loop_iterations, ACPI_MAX_LOOP_TIMEOUT); /* * This mechanism is used to trace a specified AML method. The method is diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 4f077edb9b81..ddde2790a54a 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -468,6 +468,8 @@ typedef void *acpi_handle; /* Actually a ptr to a NS Node */ #define ACPI_NSEC_PER_MSEC 1000000L #define ACPI_NSEC_PER_SEC 1000000000L +#define ACPI_TIME_AFTER(a, b) ((s64)((b) - (a)) < 0) + /* Owner IDs are used to track namespace nodes for selective deletion */ typedef u8 acpi_owner_id; -- cgit v1.2.3 From a26f4df913140a43cf7e3cb89b12ac27d87df984 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:40:19 -0800 Subject: ACPICA: Rename AE_AML_INFINITE_LOOP exception ACPICA commit e017213698374e01225f641ba0917516d8e91427 More appropriately renamed to AE_AML_LOOP_TIMEOUT, now that a real timer is used for the implementation. Link: https://github.com/acpica/acpica/commit/e0172136 Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/dscontrol.c | 2 +- include/acpi/acexcep.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index 244075dbc03a..4b6ebc2a2851 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -216,7 +216,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state, if (ACPI_TIME_AFTER(acpi_os_get_timer(), control_state->control. loop_timeout)) { - status = AE_AML_INFINITE_LOOP; + status = AE_AML_LOOP_TIMEOUT; break; } diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 17d61b1f2511..e1f9fe47f69e 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -195,7 +195,7 @@ struct acpi_exception_info { #define AE_AML_CIRCULAR_REFERENCE EXCEP_AML (0x001E) #define AE_AML_BAD_RESOURCE_LENGTH EXCEP_AML (0x001F) #define AE_AML_ILLEGAL_ADDRESS EXCEP_AML (0x0020) -#define AE_AML_INFINITE_LOOP EXCEP_AML (0x0021) +#define AE_AML_LOOP_TIMEOUT EXCEP_AML (0x0021) #define AE_AML_UNINITIALIZED_NODE EXCEP_AML (0x0022) #define AE_AML_TARGET_TYPE EXCEP_AML (0x0023) @@ -368,8 +368,8 @@ static const struct acpi_exception_info acpi_gbl_exception_names_aml[] = { "The length of a Resource Descriptor in the AML is incorrect"), EXCEP_TXT("AE_AML_ILLEGAL_ADDRESS", "A memory, I/O, or PCI configuration address is invalid"), - EXCEP_TXT("AE_AML_INFINITE_LOOP", - "An apparent infinite AML While loop, method was aborted"), + EXCEP_TXT("AE_AML_LOOP_TIMEOUT", + "An AML While loop exceeded the maximum execution time"), EXCEP_TXT("AE_AML_UNINITIALIZED_NODE", "A namespace node is uninitialized or unresolved"), EXCEP_TXT("AE_AML_TARGET_TYPE", -- cgit v1.2.3 From 90adf776a9b01faa08f29d712de5ff0bf5ba1441 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:40:20 -0800 Subject: ACPICA: Tools: Deploy -vd option (build date/time) across all tools ACPICA commit 336131640a1574b86240b32eca3150195f9270d6 Common option for all tools. Link: https://github.com/acpica/acpica/commit/33613164 Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acapps.h | 3 +++ tools/power/acpi/tools/acpidump/apmain.c | 28 ++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h index 7a1a68b5ac5c..2243c8164b34 100644 --- a/drivers/acpi/acpica/acapps.h +++ b/drivers/acpi/acpica/acapps.h @@ -80,6 +80,9 @@ prefix, ACPICA_COPYRIGHT, \ prefix +#define ACPI_COMMON_BUILD_TIME \ + "Build date/time: %s %s\n", __DATE__, __TIME__ + /* Macros for usage messages */ #define ACPI_USAGE_HEADER(usage) \ diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c index 22c3b4ee1617..be418fba9441 100644 --- a/tools/power/acpi/tools/acpidump/apmain.c +++ b/tools/power/acpi/tools/acpidump/apmain.c @@ -79,7 +79,7 @@ struct ap_dump_action action_table[AP_MAX_ACTIONS]; u32 current_action = 0; #define AP_UTILITY_NAME "ACPI Binary Table Dump Utility" -#define AP_SUPPORTED_OPTIONS "?a:bc:f:hn:o:r:svxz" +#define AP_SUPPORTED_OPTIONS "?a:bc:f:hn:o:r:sv^xz" /****************************************************************************** * @@ -100,6 +100,7 @@ static void ap_display_usage(void) ACPI_OPTION("-r
", "Dump tables from specified RSDP"); ACPI_OPTION("-s", "Print table summaries only"); ACPI_OPTION("-v", "Display version information"); + ACPI_OPTION("-vd", "Display build date and time"); ACPI_OPTION("-z", "Verbose mode"); ACPI_USAGE_TEXT("\nTable Options:\n"); @@ -231,10 +232,29 @@ static int ap_do_options(int argc, char **argv) } continue; - case 'v': /* Revision/version */ + case 'v': /* -v: (Version): signon already emitted, just exit */ - acpi_os_printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); - return (1); + switch (acpi_gbl_optarg[0]) { + case '^': /* -v: (Version) */ + + fprintf(stderr, + ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); + return (1); + + case 'd': + + fprintf(stderr, + ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); + printf(ACPI_COMMON_BUILD_TIME); + return (1); + + default: + + printf("Unknown option: -v%s\n", + acpi_gbl_optarg); + return (-1); + } + break; case 'z': /* Verbose mode */ -- cgit v1.2.3 From b43eac6f3384b033259bd973d4067d11260b68b3 Mon Sep 17 00:00:00 2001 From: Erik Schmauss Date: Fri, 17 Nov 2017 15:40:21 -0800 Subject: ACPICA: iASL: change processing of external op namespace nodes for correctness ACPICA commit aa866a9b4f24bbec9f158d10325b486d7d12d90f The declaration External (ABCD.EFGH) creates two nodes in the namespace: ABCD and EFGH where ABCD is marked as an implicit external node. ABCD is labeled as implicit because there does not exist a specific External (ABCD) declaration. Before this change, the declaration External (ABCD.EFGH) and External (ABCD.EFGH.IJKL) creates the namespace nodes ABCD, EFGH, and IJKL where ABCD and EFGH are labeled as implicit external nodes. This is incorrect. The only implicit node should be ABCD because EFGH and IJKL are explicit nodes. This change fixes the labeling procecess of external op namespace nodes so that nodes are properly labeled as implicit external. Due to this commit, the below ASL code results in a compilation error. definition_block ("DSDT.aml", "DSDT", 0x02, "INTEL", "BDW ", 0x0) { External(\_SB.PCI0.GFX0, device_obj) External(\_SB.PCI0.GFX0.ALSI) Scope(\_SB) { Device(PCI0) { Device(GFX0) { Name(_ADR, 0x00020000) } } } } Link: https://github.com/acpica/acpica/commit/aa866a9b Signed-off-by: Erik Schmauss Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsaccess.c | 13 +++++++------ drivers/acpi/acpica/nssearch.c | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index f2733f51ca8d..33e652a12fca 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -644,17 +644,18 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, this_node->object; } } -#ifdef ACPI_ASL_COMPILER - if (!acpi_gbl_disasm_flag && - (this_node->flags & ANOBJ_IS_EXTERNAL)) { - this_node->flags |= IMPLICIT_EXTERNAL; - } -#endif } /* Special handling for the last segment (num_segments == 0) */ else { +#ifdef ACPI_ASL_COMPILER + if (!acpi_gbl_disasm_flag + && (this_node->flags & ANOBJ_IS_EXTERNAL)) { + this_node->flags &= ~IMPLICIT_EXTERNAL; + } +#endif + /* * Sanity typecheck of the target object: * diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 5de8957f5ef0..e91dbee9235f 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -417,6 +417,7 @@ acpi_ns_search_and_enter(u32 target_name, if (flags & ACPI_NS_EXTERNAL || (walk_state && walk_state->opcode == AML_SCOPE_OP)) { new_node->flags |= ANOBJ_IS_EXTERNAL; + new_node->flags |= IMPLICIT_EXTERNAL; } #endif -- cgit v1.2.3 From 19654f9f24a47d374e5b413c67d05ecb5a1df580 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 17 Nov 2017 15:40:23 -0800 Subject: ACPICA: Utilities: Cleanup style issue for bit clearing ACPICA commit b49a0e1e26f3c61df7113f18f441c83739eb5514 It's reported in Linux community that change to utmath.c contains a style problem: [.../utmath.c:137]: (style) Same expression on both sides of '^='. [.../utmath.c:174]: (style) Same expression on both sides of '^='. This patch fixes this problem. ACPICA BZ 1422, reported by David Binderman, fixed by Lv Zheng. Link: https://github.com/acpica/acpica/commit/b49a0e1e Link: https://bugs.acpica.org/show_bug.cgi?id=1422 Reported-by: David Binderman Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utmath.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index 5f9c680076c4..2055a858e5f5 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -134,7 +134,7 @@ acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result) if ((count & 63) >= 32) { operand_ovl.part.hi = operand_ovl.part.lo; - operand_ovl.part.lo ^= operand_ovl.part.lo; + operand_ovl.part.lo = 0; count = (count & 63) - 32; } ACPI_SHIFT_LEFT_64_BY_32(operand_ovl.part.hi, @@ -171,7 +171,7 @@ acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result) if ((count & 63) >= 32) { operand_ovl.part.lo = operand_ovl.part.hi; - operand_ovl.part.hi ^= operand_ovl.part.hi; + operand_ovl.part.hi = 0; count = (count & 63) - 32; } ACPI_SHIFT_RIGHT_64_BY_32(operand_ovl.part.hi, -- cgit v1.2.3 From db53f7f0eba56a7d8e45d6b26042899fccc43755 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:42:16 -0800 Subject: ACPICA: Use local 64-bit divide support for string conversions ACPICA commit f230f4df26d07b97ef00be39156ecee64250447d On 32-bit platforms, 64-bit divide often requires a library function which may not be present in the build. Link: https://github.com/acpica/acpica/commit/f230f4df Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utstrsuppt.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/utstrsuppt.c b/drivers/acpi/acpica/utstrsuppt.c index 965fb5cec94f..b2fc371c402e 100644 --- a/drivers/acpi/acpica/utstrsuppt.c +++ b/drivers/acpi/acpica/utstrsuppt.c @@ -52,10 +52,9 @@ static acpi_status acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit); static acpi_status -acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product); +acpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product); -static acpi_status -acpi_ut_strtoul_add64(u64 addend1, u64 addend2, u64 *out_sum); +static acpi_status acpi_ut_strtoul_add64(u64 addend1, u32 digit, u64 *out_sum); /******************************************************************************* * @@ -357,7 +356,7 @@ acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit) * FUNCTION: acpi_ut_strtoul_multiply64 * * PARAMETERS: multiplicand - Current accumulated converted integer - * multiplier - Base/Radix + * base - Base/Radix * out_product - Where the product is returned * * RETURN: Status and 64-bit product @@ -369,25 +368,32 @@ acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit) ******************************************************************************/ static acpi_status -acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product) +acpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product) { u64 val; + u64 quotient; /* Exit if either operand is zero */ *out_product = 0; - if (!multiplicand || !multiplier) { + if (!multiplicand || !base) { return (AE_OK); } - /* Check for 64-bit overflow before the actual multiplication */ - - acpi_ut_short_divide(ACPI_UINT64_MAX, (u32)multiplier, &val, NULL); - if (multiplicand > val) { + /* + * Check for 64-bit overflow before the actual multiplication. + * + * Notes: 64-bit division is often not supported on 32-bit platforms + * (it requires a library function), Therefore ACPICA has a local + * 64-bit divide function. Also, Multiplier is currently only used + * as the radix (8/10/16), to the 64/32 divide will always work. + */ + acpi_ut_short_divide(ACPI_UINT64_MAX, base, "ient, NULL); + if (multiplicand > quotient) { return (AE_NUMERIC_OVERFLOW); } - val = multiplicand * multiplier; + val = multiplicand * base; /* Check for 32-bit overflow if necessary */ @@ -404,7 +410,7 @@ acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product) * FUNCTION: acpi_ut_strtoul_add64 * * PARAMETERS: addend1 - Current accumulated converted integer - * addend2 - New hex value/char + * digit - New hex value/char * out_sum - Where sum is returned (Accumulator) * * RETURN: Status and 64-bit sum @@ -415,17 +421,17 @@ acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product) * ******************************************************************************/ -static acpi_status acpi_ut_strtoul_add64(u64 addend1, u64 addend2, u64 *out_sum) +static acpi_status acpi_ut_strtoul_add64(u64 addend1, u32 digit, u64 *out_sum) { u64 sum; /* Check for 64-bit overflow before the actual addition */ - if ((addend1 > 0) && (addend2 > (ACPI_UINT64_MAX - addend1))) { + if ((addend1 > 0) && (digit > (ACPI_UINT64_MAX - addend1))) { return (AE_NUMERIC_OVERFLOW); } - sum = addend1 + addend2; + sum = addend1 + digit; /* Check for 32-bit overflow if necessary */ -- cgit v1.2.3 From e814109bee1aba30c650418e7412adb89654057b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:42:17 -0800 Subject: ACPICA: Update output from ACPI_EXCEPTION macro ACPICA commit b2858b2cc83e1481950a2c976f62d4e1d758bc85 Changes line prefix from "ACPI Exception" to simply "ACPI Error" to match the ACPI_ERROR macro. ACPI_EXCEPTION takes the ACPI status as an argument, decodes and displays it along with the error message. Link: https://github.com/acpica/acpica/commit/b2858b2c Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acutils.h | 3 --- drivers/acpi/acpica/utxferror.c | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 83b75e9db7ef..bb97a18158ec 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -118,9 +118,6 @@ extern const char *acpi_gbl_ptyp_decode[]; #ifndef ACPI_MSG_ERROR #define ACPI_MSG_ERROR "ACPI Error: " #endif -#ifndef ACPI_MSG_EXCEPTION -#define ACPI_MSG_EXCEPTION "ACPI Exception: " -#endif #ifndef ACPI_MSG_WARNING #define ACPI_MSG_WARNING "ACPI Warning: " #endif diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index 950a1e500bfa..9da4f8ef2e77 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -96,8 +96,8 @@ ACPI_EXPORT_SYMBOL(acpi_error) * * RETURN: None * - * DESCRIPTION: Print "ACPI Exception" message with module/line/version info - * and decoded acpi_status. + * DESCRIPTION: Print an "ACPI Error" message with module/line/version + * info as well as decoded acpi_status. * ******************************************************************************/ void ACPI_INTERNAL_VAR_XFACE @@ -111,10 +111,10 @@ acpi_exception(const char *module_name, /* For AE_OK, just print the message */ if (ACPI_SUCCESS(status)) { - acpi_os_printf(ACPI_MSG_EXCEPTION); + acpi_os_printf(ACPI_MSG_ERROR); } else { - acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ", + acpi_os_printf(ACPI_MSG_ERROR "%s, ", acpi_format_exception(status)); } -- cgit v1.2.3 From 53ae81e1896e8beb52c6d94fa2380f864e9bb4e7 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:42:18 -0800 Subject: ACPICA: Add an additional error message for EC timeouts ACPICA commit 24dd370b14711b7b3f31d7ca6326f9e0bd177c4e AE_TIME is seen to be returned from the EC driver/handler so often that an additional error message is added to help clarify the problem. Link: https://github.com/acpica/acpica/commit/24dd370b Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evregion.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 28b447ff92df..bb58419f0d61 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -298,6 +298,16 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", acpi_ut_get_region_name(region_obj->region. space_id))); + + /* + * Special case for an EC timeout. These are seen so frequently + * that an additional error message is helpful + */ + if ((region_obj->region.space_id == ACPI_ADR_SPACE_EC) && + (status == AE_TIME)) { + ACPI_ERROR((AE_INFO, + "Timeout from EC hardware or EC device driver")); + } } if (!(handler_desc->address_space.handler_flags & -- cgit v1.2.3 From b12ebe59353c76e08d4a956a2c8a6a13b3b98839 Mon Sep 17 00:00:00 2001 From: Erik Schmauss Date: Fri, 17 Nov 2017 15:42:20 -0800 Subject: ACPICA: ACPICA: style edits to utility function output, no functional change ACPICA commit 8070a23749f1c2eedec313f42f564b5375054137 Link: https://github.com/acpica/acpica/commit/8070a237 Signed-off-by: Erik Schmauss Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/uttrack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 3c8de88ecbd5..28a302eb2015 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -717,7 +717,7 @@ exit: if (!num_outstanding) { ACPI_INFO(("No outstanding allocations")); } else { - ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations", + ACPI_ERROR((AE_INFO, "%u (0x%X) Outstanding cache allocations", num_outstanding, num_outstanding)); } -- cgit v1.2.3 From 16ccf829201cef23edaa5524f3f91e05861c4455 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:42:22 -0800 Subject: ACPICA: Enhance error messages from namespace create/lookup operations ACPICA commit b09c8d7bdc8c5a3db0a8d38bfd6182c023885e12 1) Emit the full pathname (scope+name) instead of just the name 2) For AE_ALREADY_EXISTS and AE_NOT_FOUND, use the "firmware error" string to point to the true problem. Link: https://github.com/acpica/acpica/commit/b09c8d7b Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acmacros.h | 2 +- drivers/acpi/acpica/acnamesp.h | 3 + drivers/acpi/acpica/acutils.h | 12 ++-- drivers/acpi/acpica/dsfield.c | 28 +++++--- drivers/acpi/acpica/dsobject.c | 4 +- drivers/acpi/acpica/dsutils.c | 3 +- drivers/acpi/acpica/dswload.c | 6 +- drivers/acpi/acpica/dswload2.c | 13 ++-- drivers/acpi/acpica/nsconvert.c | 3 +- drivers/acpi/acpica/nsnames.c | 146 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/psargs.c | 2 +- drivers/acpi/acpica/uterror.c | 73 ++++++++++++++++++++ 12 files changed, 270 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index c7f0c96cc00f..128a3d71b598 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -455,7 +455,7 @@ * the plist contains a set of parens to allow variable-length lists. * These macros are used for both the debug and non-debug versions of the code. */ -#define ACPI_ERROR_NAMESPACE(s, e) acpi_ut_namespace_error (AE_INFO, s, e); +#define ACPI_ERROR_NAMESPACE(s, p, e) acpi_ut_prefixed_namespace_error (AE_INFO, s, p, e); #define ACPI_ERROR_METHOD(s, n, p, e) acpi_ut_method_error (AE_INFO, s, n, p, e); #define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist #define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 54a0c51b3e37..2fb1bb78d85c 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -289,6 +289,9 @@ acpi_ns_build_normalized_path(struct acpi_namespace_node *node, char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node, u8 no_trailing); +char *acpi_ns_build_prefixed_pathname(union acpi_generic_state *prefix_scope, + const char *internal_path); + char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state); acpi_status diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index bb97a18158ec..d38187ee11c8 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -126,10 +126,10 @@ extern const char *acpi_gbl_ptyp_decode[]; #endif #ifndef ACPI_MSG_BIOS_ERROR -#define ACPI_MSG_BIOS_ERROR "ACPI BIOS Error (bug): " +#define ACPI_MSG_BIOS_ERROR "Firmware Error (ACPI): " #endif #ifndef ACPI_MSG_BIOS_WARNING -#define ACPI_MSG_BIOS_WARNING "ACPI BIOS Warning (bug): " +#define ACPI_MSG_BIOS_WARNING "Firmware Warning (ACPI): " #endif /* @@ -734,9 +734,11 @@ acpi_ut_predefined_bios_error(const char *module_name, u8 node_flags, const char *format, ...); void -acpi_ut_namespace_error(const char *module_name, - u32 line_number, - const char *internal_name, acpi_status lookup_status); +acpi_ut_prefixed_namespace_error(const char *module_name, + u32 line_number, + union acpi_generic_state *prefix_scope, + const char *internal_name, + acpi_status lookup_status); void acpi_ut_method_error(const char *module_name, diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 7bcf5f5ea029..0cab34a593d5 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -209,7 +209,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, ACPI_IMODE_LOAD_PASS1, flags, walk_state, &node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + arg->common.value.string, status); return_ACPI_STATUS(status); } } @@ -383,7 +384,9 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, walk_state, &info->connection_node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(child->common. + ACPI_ERROR_NAMESPACE(walk_state-> + scope_info, + child->common. value.name, status); return_ACPI_STATUS(status); @@ -402,7 +405,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, ACPI_NS_DONT_OPEN_SCOPE, walk_state, &info->field_node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE((char *)&arg->named.name, + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + (char *)&arg->named.name, status); return_ACPI_STATUS(status); } else { @@ -498,7 +502,8 @@ acpi_ds_create_field(union acpi_parse_object *op, ®ion_node); #endif if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.name, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + arg->common.value.name, status); return_ACPI_STATUS(status); } } @@ -618,7 +623,8 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, ACPI_IMODE_LOAD_PASS1, flags, walk_state, &node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE((char *)&arg->named.name, + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + (char *)&arg->named.name, status); if (status != AE_ALREADY_EXISTS) { return_ACPI_STATUS(status); @@ -681,7 +687,8 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, ®ion_node); #endif if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.name, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + arg->common.value.name, status); return_ACPI_STATUS(status); } } @@ -695,7 +702,8 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + arg->common.value.string, status); return_ACPI_STATUS(status); } @@ -765,7 +773,8 @@ acpi_ds_create_index_field(union acpi_parse_object *op, ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + arg->common.value.string, status); return_ACPI_STATUS(status); } @@ -778,7 +787,8 @@ acpi_ds_create_index_field(union acpi_parse_object *op, ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + arg->common.value.string, status); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 82448551781b..b21fe084ffc8 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -112,7 +112,9 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, acpi_namespace_node, &(op->common.node))); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(op->common.value. + ACPI_ERROR_NAMESPACE(walk_state-> + scope_info, + op->common.value. string, status); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index 0dabd9b95684..4c5faf629a83 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -583,7 +583,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, } if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(name_string, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + name_string, status); } } diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index eaa859a89702..5771e4e4a99a 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -207,7 +207,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, } #endif if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, path, + status); return_ACPI_STATUS(status); } @@ -375,7 +376,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, } if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + path, status); return_ACPI_STATUS(status); } } diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index aad83ef5a4ec..b3d0aaec8203 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -184,11 +184,14 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, if (status == AE_NOT_FOUND) { status = AE_OK; } else { - ACPI_ERROR_NAMESPACE(buffer_ptr, + ACPI_ERROR_NAMESPACE(walk_state-> + scope_info, + buffer_ptr, status); } #else - ACPI_ERROR_NAMESPACE(buffer_ptr, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + buffer_ptr, status); #endif return_ACPI_STATUS(status); } @@ -343,7 +346,8 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, } if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(buffer_ptr, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + buffer_ptr, status); return_ACPI_STATUS(status); } @@ -719,7 +723,8 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) */ op->common.node = new_node; } else { - ACPI_ERROR_NAMESPACE(arg->common.value.string, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + arg->common.value.string, status); } break; diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c index 539d775bbc92..d55dcc82f434 100644 --- a/drivers/acpi/acpica/nsconvert.c +++ b/drivers/acpi/acpica/nsconvert.c @@ -495,7 +495,8 @@ acpi_ns_convert_to_reference(struct acpi_namespace_node *scope, /* Check if we are resolving a named reference within a package */ - ACPI_ERROR_NAMESPACE(original_object->string.pointer, status); + ACPI_ERROR_NAMESPACE(&scope_info, + original_object->string.pointer, status); goto error_exit; } diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index a410760a0308..4203d4589b6d 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -49,6 +49,9 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsnames") +/* Local Prototypes */ +static void acpi_ns_normalize_pathname(char *original_path); + /******************************************************************************* * * FUNCTION: acpi_ns_get_external_pathname @@ -63,6 +66,7 @@ ACPI_MODULE_NAME("nsnames") * for error and debug statements. * ******************************************************************************/ + char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) { char *name_buffer; @@ -352,3 +356,145 @@ char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node, return_PTR(name_buffer); } + +/******************************************************************************* + * + * FUNCTION: acpi_ns_build_prefixed_pathname + * + * PARAMETERS: prefix_scope - Scope/Path that prefixes the internal path + * internal_path - Name or path of the namespace node + * + * RETURN: None + * + * DESCRIPTION: Construct a fully qualified pathname from a concatenation of: + * 1) Path associated with the prefix_scope namespace node + * 2) External path representation of the Internal path + * + ******************************************************************************/ + +char *acpi_ns_build_prefixed_pathname(union acpi_generic_state *prefix_scope, + const char *internal_path) +{ + acpi_status status; + char *full_path = NULL; + char *external_path; + char *prefix_path = NULL; + u32 prefix_path_length = 0; + + /* If there is a prefix, get the pathname to it */ + + if (prefix_scope && prefix_scope->scope.node) { + prefix_path = + acpi_ns_get_normalized_pathname(prefix_scope->scope.node, + TRUE); + if (prefix_path) { + prefix_path_length = strlen(prefix_path); + } + } + + status = acpi_ns_externalize_name(ACPI_UINT32_MAX, internal_path, + NULL, &external_path); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Merge the prefix path and the path. 2 is for one dot and trailing null */ + + full_path = + ACPI_ALLOCATE_ZEROED(prefix_path_length + strlen(external_path) + + 2); + if (!full_path) { + goto cleanup; + } + + /* Don't merge if the External path is already fully qualified */ + + if (prefix_path && (*external_path != '\\') && (*external_path != '^')) { + strcat(full_path, prefix_path); + if (prefix_path[1]) { + strcat(full_path, "."); + } + } + + acpi_ns_normalize_pathname(external_path); + strcat(full_path, external_path); + +cleanup: + if (prefix_path) { + ACPI_FREE(prefix_path); + } + + return (full_path); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_normalize_pathname + * + * PARAMETERS: original_path - Path to be normalized, in External format + * + * RETURN: The original path is processed in-place + * + * DESCRIPTION: Remove trailing underscores from each element of a path. + * + * For example: \A___.B___.C___ becomes \A.B.C + * + ******************************************************************************/ + +static void acpi_ns_normalize_pathname(char *original_path) +{ + char *input_path = original_path; + char *new_path_buffer; + char *new_path; + u32 i; + + /* Allocate a temp buffer in which to construct the new path */ + + new_path_buffer = ACPI_ALLOCATE_ZEROED(strlen(input_path) + 1); + new_path = new_path_buffer; + if (!new_path_buffer) { + return; + } + + /* Special characters may appear at the beginning of the path */ + + if (*input_path == '\\') { + *new_path = *input_path; + new_path++; + input_path++; + } + + while (*input_path == '^') { + *new_path = *input_path; + new_path++; + input_path++; + } + + /* Remainder of the path */ + + while (*input_path) { + + /* Do one nameseg at a time */ + + for (i = 0; (i < ACPI_NAME_SIZE) && *input_path; i++) { + if ((i == 0) || (*input_path != '_')) { /* First char is allowed to be underscore */ + *new_path = *input_path; + new_path++; + } + + input_path++; + } + + /* Dot means that there are more namesegs to come */ + + if (*input_path == '.') { + *new_path = *input_path; + new_path++; + input_path++; + } + } + + *new_path = 0; + strcpy(original_path, new_path_buffer); + ACPI_FREE(new_path_buffer); +} diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index eb9dfaca555f..171e2faa7c50 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -361,7 +361,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, /* Final exception check (may have been changed from code above) */ if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, path, status); if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) { diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c index e3368186e1c1..42388dcb5ccc 100644 --- a/drivers/acpi/acpica/uterror.c +++ b/drivers/acpi/acpica/uterror.c @@ -180,6 +180,78 @@ acpi_ut_predefined_bios_error(const char *module_name, va_end(arg_list); } +/******************************************************************************* + * + * FUNCTION: acpi_ut_prefixed_namespace_error + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * prefix_scope - Scope/Path that prefixes the internal path + * internal_path - Name or path of the namespace node + * lookup_status - Exception code from NS lookup + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname constructed this way: + * + * prefix_scope_node_full_path.externalized_internal_path + * + * NOTE: 10/2017: Treat the major ns_lookup errors as firmware errors + * + ******************************************************************************/ + +void +acpi_ut_prefixed_namespace_error(const char *module_name, + u32 line_number, + union acpi_generic_state *prefix_scope, + const char *internal_path, + acpi_status lookup_status) +{ + char *full_path; + const char *message; + + /* + * Main cases: + * 1) Object creation, object must not already exist + * 2) Object lookup, object must exist + */ + switch (lookup_status) { + case AE_ALREADY_EXISTS: + + acpi_os_printf(ACPI_MSG_BIOS_ERROR); + message = "Failure creating"; + break; + + case AE_NOT_FOUND: + + acpi_os_printf(ACPI_MSG_BIOS_ERROR); + message = "Failure looking up"; + break; + + default: + + acpi_os_printf(ACPI_MSG_ERROR); + message = "Failure looking up"; + break; + } + + /* Concatenate the prefix path and the internal path */ + + full_path = + acpi_ns_build_prefixed_pathname(prefix_scope, internal_path); + + acpi_os_printf("%s [%s], %s", message, + full_path ? full_path : "Could not get pathname", + acpi_format_exception(lookup_status)); + + if (full_path) { + ACPI_FREE(full_path); + } + + ACPI_MSG_SUFFIX; +} + +#ifdef __OBSOLETE_FUNCTION /******************************************************************************* * * FUNCTION: acpi_ut_namespace_error @@ -240,6 +312,7 @@ acpi_ut_namespace_error(const char *module_name, ACPI_MSG_SUFFIX; ACPI_MSG_REDIRECT_END; } +#endif /******************************************************************************* * -- cgit v1.2.3 From dea4e83358f23bcb178e9cb23e9278ff5a8cea76 Mon Sep 17 00:00:00 2001 From: Erik Schmauss Date: Fri, 17 Nov 2017 15:42:23 -0800 Subject: ACPICA: Namespace: fix memory leak from building prefixed pathname ACPICA commit f8ca5db30605467b851f86d152079631c27eeca8 Link: https://github.com/acpica/acpica/commit/f8ca5db3 Signed-off-by: Erik Schmauss Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsnames.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index 4203d4589b6d..22c92d1a24d8 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -377,7 +377,7 @@ char *acpi_ns_build_prefixed_pathname(union acpi_generic_state *prefix_scope, { acpi_status status; char *full_path = NULL; - char *external_path; + char *external_path = NULL; char *prefix_path = NULL; u32 prefix_path_length = 0; @@ -423,6 +423,9 @@ cleanup: if (prefix_path) { ACPI_FREE(prefix_path); } + if (external_path) { + ACPI_FREE(external_path); + } return (full_path); } -- cgit v1.2.3 From 060c859d79ed8ead423a076e581af08d6496bf02 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:42:26 -0800 Subject: ACPICA: Debugger: add "background" command for method execution ACPICA commit d7b44738a48caa9f669b8dbf0024d456711aec31 Allows a single task to execute in the background, while control returns to the debugger prompt. Also, cleanup the debugger help screen. Link: https://github.com/acpica/acpica/commit/d7b44738 Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 4 ++ drivers/acpi/acpica/aclocal.h | 13 ++-- drivers/acpi/acpica/dbexec.c | 110 +++++++++++++++++++++++++++++++- drivers/acpi/acpica/dbinput.c | 145 +++++++++++++++++++++++++----------------- 4 files changed, 206 insertions(+), 66 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 71743e5252f5..54b8d9df9423 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -222,6 +222,10 @@ ACPI_DBR_DEPENDENT_RETURN_VOID(void void acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags); +void +acpi_db_create_execution_thread(char *method_name_arg, + char **arguments, acpi_object_type *types); + void acpi_db_create_execution_threads(char *num_threads_arg, char *num_loops_arg, char *method_name_arg); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index bed041d41596..a56675f0661e 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -1218,16 +1218,17 @@ struct acpi_db_method_info { acpi_object_type *types; /* - * Arguments to be passed to method for the command - * Threads - - * the Number of threads, ID of current thread and - * Index of current thread inside all them created. + * Arguments to be passed to method for the commands Threads and + * Background. Note, ACPI specifies a maximum of 7 arguments (0 - 6). + * + * For the Threads command, the Number of threads, ID of current + * thread and Index of current thread inside all them created. */ char init_args; #ifdef ACPI_DEBUGGER - acpi_object_type arg_types[4]; + acpi_object_type arg_types[ACPI_METHOD_NUM_ARGS]; #endif - char *arguments[4]; + char *arguments[ACPI_METHOD_NUM_ARGS]; char num_threads_str[11]; char id_of_thread_str[11]; char index_of_thread_str[11]; diff --git a/drivers/acpi/acpica/dbexec.c b/drivers/acpi/acpica/dbexec.c index 3b30319752f0..ed088fceb18d 100644 --- a/drivers/acpi/acpica/dbexec.c +++ b/drivers/acpi/acpica/dbexec.c @@ -67,6 +67,8 @@ static acpi_status acpi_db_execution_walk(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value); +static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context); + /******************************************************************************* * * FUNCTION: acpi_db_delete_objects @@ -229,7 +231,7 @@ static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info) ACPI_FUNCTION_NAME(db_execute_setup); - /* Catenate the current scope to the supplied name */ + /* Concatenate the current scope to the supplied name */ info->pathname[0] = 0; if ((info->name[0] != '\\') && (info->name[0] != '/')) { @@ -609,6 +611,112 @@ static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context) } } +/******************************************************************************* + * + * FUNCTION: acpi_db_single_execution_thread + * + * PARAMETERS: context - Method info struct + * + * RETURN: None + * + * DESCRIPTION: Create one thread and execute a method + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context) +{ + struct acpi_db_method_info *info = context; + acpi_status status; + struct acpi_buffer return_obj; + + acpi_os_printf("\n"); + + status = acpi_db_execute_method(info, &return_obj); + if (ACPI_FAILURE(status)) { + acpi_os_printf("%s During evaluation of %s\n", + acpi_format_exception(status), info->pathname); + return; + } + + /* Display a return object, if any */ + + if (return_obj.length) { + acpi_os_printf("Evaluation of %s returned object %p, " + "external buffer length %X\n", + acpi_gbl_db_method_info.pathname, + return_obj.pointer, (u32)return_obj.length); + + acpi_db_dump_external_object(return_obj.pointer, 1); + } + + acpi_os_printf("\nBackground thread completed\n%c ", + ACPI_DEBUGGER_COMMAND_PROMPT); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_create_execution_thread + * + * PARAMETERS: method_name_arg - Control method to execute + * arguments - Array of arguments to the method + * types - Corresponding array of object types + * + * RETURN: None + * + * DESCRIPTION: Create a single thread to evaluate a namespace object. Handles + * arguments passed on command line for control methods. + * + ******************************************************************************/ + +void +acpi_db_create_execution_thread(char *method_name_arg, + char **arguments, acpi_object_type *types) +{ + acpi_status status; + u32 i; + + memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info)); + acpi_gbl_db_method_info.name = method_name_arg; + acpi_gbl_db_method_info.init_args = 1; + acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments; + acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types; + + /* Setup method arguments, up to 7 (0-6) */ + + for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *arguments; i++) { + acpi_gbl_db_method_info.arguments[i] = *arguments; + arguments++; + + acpi_gbl_db_method_info.arg_types[i] = *types; + types++; + } + + status = acpi_db_execute_setup(&acpi_gbl_db_method_info); + if (ACPI_FAILURE(status)) { + return; + } + + /* Get the NS node, determines existence also */ + + status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname, + &acpi_gbl_db_method_info.method); + if (ACPI_FAILURE(status)) { + acpi_os_printf("%s Could not get handle for %s\n", + acpi_format_exception(status), + acpi_gbl_db_method_info.pathname); + return; + } + + status = acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD, + acpi_db_single_execution_thread, + &acpi_gbl_db_method_info); + if (ACPI_FAILURE(status)) { + return; + } + + acpi_os_printf("\nBackground thread started\n"); +} + /******************************************************************************* * * FUNCTION: acpi_db_create_execution_threads diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c index 2626d79db064..954ca3b981a7 100644 --- a/drivers/acpi/acpica/dbinput.c +++ b/drivers/acpi/acpica/dbinput.c @@ -136,6 +136,7 @@ enum acpi_ex_debugger_commands { CMD_UNLOAD, CMD_TERMINATE, + CMD_BACKGROUND, CMD_THREADS, CMD_TEST, @@ -212,6 +213,7 @@ static const struct acpi_db_command_info acpi_gbl_db_commands[] = { {"UNLOAD", 1}, {"TERMINATE", 0}, + {"BACKGROUND", 1}, {"THREADS", 3}, {"TEST", 1}, @@ -222,9 +224,56 @@ static const struct acpi_db_command_info acpi_gbl_db_commands[] = { /* * Help for all debugger commands. First argument is the number of lines * of help to output for the command. + * + * Note: Some commands are not supported by the kernel-level version of + * the debugger. */ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { - {0, "\nGeneral-Purpose Commands:", "\n"}, + {0, "\nNamespace Access:", "\n"}, + {1, " Businfo", "Display system bus info\n"}, + {1, " Disassemble ", "Disassemble a control method\n"}, + {1, " Find (? is wildcard)", + "Find ACPI name(s) with wildcards\n"}, + {1, " Integrity", "Validate namespace integrity\n"}, + {1, " Methods", "Display list of loaded control methods\n"}, + {1, " Namespace [Object] [Depth]", + "Display loaded namespace tree/subtree\n"}, + {1, " Notify ", "Send a notification on Object\n"}, + {1, " Objects [ObjectType]", + "Display summary of all objects or just given type\n"}, + {1, " Owner [Depth]", + "Display loaded namespace by object owner\n"}, + {1, " Paths", "Display full pathnames of namespace objects\n"}, + {1, " Predefined", "Check all predefined names\n"}, + {1, " Prefix []", "Set or Get current execution prefix\n"}, + {1, " References ", "Find all references to object at addr\n"}, + {1, " Resources [DeviceName]", + "Display Device resources (no arg = all devices)\n"}, + {1, " Set N ", "Set value for named integer\n"}, + {1, " Template ", "Format/dump a Buffer/ResourceTemplate\n"}, + {1, " Type ", "Display object type\n"}, + + {0, "\nControl Method Execution:", "\n"}, + {1, " Evaluate [Arguments]", + "Evaluate object or control method\n"}, + {1, " Execute [Arguments]", "Synonym for Evaluate\n"}, +#ifdef ACPI_APPLICATION + {1, " Background [Arguments]", + "Evaluate object/method in a separate thread\n"}, + {1, " Thread ", + "Spawn threads to execute method(s)\n"}, +#endif + {1, " Debug [Arguments]", "Single-Step a control method\n"}, + {7, " [Arguments] formats:", "Control method argument formats\n"}, + {1, " Hex Integer", "Integer\n"}, + {1, " \"Ascii String\"", "String\n"}, + {1, " (Hex Byte List)", "Buffer\n"}, + {1, " (01 42 7A BF)", "Buffer example (4 bytes)\n"}, + {1, " [Package Element List]", "Package\n"}, + {1, " [0x01 0x1234 \"string\"]", + "Package example (3 elements)\n"}, + + {0, "\nMiscellaneous:", "\n"}, {1, " Allocations", "Display list of current memory allocations\n"}, {2, " Dump
|", "\n"}, {0, " [Byte|Word|Dword|Qword]", @@ -248,46 +297,30 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { {1, " Stack", "Display CPU stack usage\n"}, {1, " Tables", "Info about current ACPI table(s)\n"}, {1, " Tables", "Display info about loaded ACPI tables\n"}, +#ifdef ACPI_APPLICATION + {1, " Terminate", "Delete namespace and all internal objects\n"}, +#endif {1, " ! ", "Execute command from history buffer\n"}, {1, " !!", "Execute last command again\n"}, - {0, "\nNamespace Access Commands:", "\n"}, - {1, " Businfo", "Display system bus info\n"}, - {1, " Disassemble ", "Disassemble a control method\n"}, - {1, " Find (? is wildcard)", - "Find ACPI name(s) with wildcards\n"}, - {1, " Integrity", "Validate namespace integrity\n"}, - {1, " Methods", "Display list of loaded control methods\n"}, - {1, " Namespace [Object] [Depth]", - "Display loaded namespace tree/subtree\n"}, - {1, " Notify ", "Send a notification on Object\n"}, - {1, " Objects [ObjectType]", - "Display summary of all objects or just given type\n"}, - {1, " Owner [Depth]", - "Display loaded namespace by object owner\n"}, - {1, " Paths", "Display full pathnames of namespace objects\n"}, - {1, " Predefined", "Check all predefined names\n"}, - {1, " Prefix []", "Set or Get current execution prefix\n"}, - {1, " References ", "Find all references to object at addr\n"}, - {1, " Resources [DeviceName]", - "Display Device resources (no arg = all devices)\n"}, - {1, " Set N ", "Set value for named integer\n"}, - {1, " Template ", "Format/dump a Buffer/ResourceTemplate\n"}, - {1, " Type ", "Display object type\n"}, + {0, "\nMethod and Namespace Debugging:", "\n"}, + {5, " Trace [] [Once]", + "Trace control method execution\n"}, + {1, " Enable", "Enable all messages\n"}, + {1, " Disable", "Disable tracing\n"}, + {1, " Method", "Enable method execution messages\n"}, + {1, " Opcode", "Enable opcode execution messages\n"}, + {3, " Test ", "Invoke a debug test\n"}, + {1, " Objects", "Read/write/compare all namespace data objects\n"}, + {1, " Predefined", + "Validate all ACPI predefined names (_STA, etc.)\n"}, + {1, " Execute predefined", + "Execute all predefined (public) methods\n"}, - {0, "\nControl Method Execution Commands:", "\n"}, + {0, "\nControl Method Single-Step Execution:", "\n"}, {1, " Arguments (or Args)", "Display method arguments\n"}, {1, " Breakpoint ", "Set an AML execution breakpoint\n"}, {1, " Call", "Run to next control method invocation\n"}, - {1, " Debug [Arguments]", "Single Step a control method\n"}, - {6, " Evaluate", "Synonym for Execute\n"}, - {5, " Execute [Arguments]", "Execute control method\n"}, - {1, " Hex Integer", "Integer method argument\n"}, - {1, " \"Ascii String\"", "String method argument\n"}, - {1, " (Hex Byte List)", "Buffer method argument\n"}, - {1, " [Package Element List]", "Package method argument\n"}, - {5, " Execute predefined", - "Execute all predefined (public) methods\n"}, {1, " Go", "Allow method to run to completion\n"}, {1, " Information", "Display info about the current method\n"}, {1, " Into", "Step into (not over) a method call\n"}, @@ -296,41 +329,24 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { {1, " Results", "Display method result stack\n"}, {1, " Set <#> ", "Set method data (Arguments/Locals)\n"}, {1, " Stop", "Terminate control method\n"}, - {5, " Trace [] [Once]", - "Trace control method execution\n"}, - {1, " Enable", "Enable all messages\n"}, - {1, " Disable", "Disable tracing\n"}, - {1, " Method", "Enable method execution messages\n"}, - {1, " Opcode", "Enable opcode execution messages\n"}, {1, " Tree", "Display control method calling tree\n"}, {1, " ", "Single step next AML opcode (over calls)\n"}, #ifdef ACPI_APPLICATION - {0, "\nHardware Simulation Commands:", "\n"}, - {1, " EnableAcpi", "Enable ACPI (hardware) mode\n"}, - {1, " Event ", "Generate AcpiEvent (Fixed/GPE)\n"}, - {1, " Gpe [GpeBlockDevice]", "Simulate a GPE\n"}, - {1, " Gpes", "Display info on all GPE devices\n"}, - {1, " Sci", "Generate an SCI\n"}, - {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"}, - - {0, "\nFile I/O Commands:", "\n"}, + {0, "\nFile Operations:", "\n"}, {1, " Close", "Close debug output file\n"}, {1, " Load ", "Load ACPI table from a file\n"}, {1, " Open ", "Open a file for debug output\n"}, {1, " Unload ", "Unload an ACPI table via namespace object\n"}, - {0, "\nUser Space Commands:", "\n"}, - {1, " Terminate", "Delete namespace and all internal objects\n"}, - {1, " Thread ", - "Spawn threads to execute method(s)\n"}, - - {0, "\nDebug Test Commands:", "\n"}, - {3, " Test ", "Invoke a debug test\n"}, - {1, " Objects", "Read/write/compare all namespace data objects\n"}, - {1, " Predefined", - "Execute all ACPI predefined names (_STA, etc.)\n"}, + {0, "\nHardware Simulation:", "\n"}, + {1, " EnableAcpi", "Enable ACPI (hardware) mode\n"}, + {1, " Event ", "Generate AcpiEvent (Fixed/GPE)\n"}, + {1, " Gpe [GpeBlockDevice]", "Simulate a GPE\n"}, + {1, " Gpes", "Display info on all GPE devices\n"}, + {1, " Sci", "Generate an SCI\n"}, + {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"}, #endif {0, NULL, NULL} }; @@ -442,11 +458,15 @@ static void acpi_db_display_help(char *command) /* No argument to help, display help for all commands */ + acpi_os_printf("\nSummary of AML Debugger Commands\n\n"); + while (next->invocation) { acpi_os_printf("%-38s%s", next->invocation, next->description); next++; } + acpi_os_printf("\n"); + } else { /* Display help for all commands that match the subtring */ @@ -1087,6 +1107,13 @@ acpi_db_command_dispatch(char *input_buffer, /* acpi_initialize (NULL); */ break; + case CMD_BACKGROUND: + + acpi_db_create_execution_thread(acpi_gbl_db_args[1], + &acpi_gbl_db_args[2], + &acpi_gbl_db_arg_types[2]); + break; + case CMD_THREADS: acpi_db_create_execution_threads(acpi_gbl_db_args[1], -- cgit v1.2.3 From 692aa0cf5d459dfb747d8bbf8bee20afbf1fa746 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:42:27 -0800 Subject: ACPICA: Update mutex error messages, no functional change ACPICA commit 22f2b0beb45d277841ed02bc613df1009e5b20cf Add mutex name on certain acquire/release errors. Link: https://github.com/acpica/acpica/commit/22f2b0be Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utmutex.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 586354788018..524ba931d5e8 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -286,8 +286,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; } else { ACPI_EXCEPTION((AE_INFO, status, - "Thread %u could not acquire Mutex [0x%X]", - (u32)this_thread_id, mutex_id)); + "Thread %u could not acquire Mutex [%s] (0x%X)", + (u32)this_thread_id, + acpi_ut_get_mutex_name(mutex_id), mutex_id)); } return (status); @@ -322,8 +323,8 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) */ if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) { ACPI_ERROR((AE_INFO, - "Mutex [0x%X] is not acquired, cannot release", - mutex_id)); + "Mutex [%s] (0x%X) is not acquired, cannot release", + acpi_ut_get_mutex_name(mutex_id), mutex_id)); return (AE_NOT_ACQUIRED); } -- cgit v1.2.3 From 3e1dc644aa2fe816e6d91459dfd2e383e66be8c7 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:42:28 -0800 Subject: ACPICA: Update linkage for get mutex name interface ACPICA commit cb9a3906ec35da7a6e0b8972f8e6e7895e59c208 Always enable the function. Link: https://github.com/acpica/acpica/commit/cb9a3906 Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acutils.h | 4 ++-- drivers/acpi/acpica/utdecode.c | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index d38187ee11c8..8bb46d8623ca 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -230,10 +230,10 @@ u64 acpi_ut_implicit_strtoul64(char *string); */ acpi_status acpi_ut_init_globals(void); -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) - const char *acpi_ut_get_mutex_name(u32 mutex_id); +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type); #endif diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 02cd2c2d961a..55debbad487d 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -395,11 +395,6 @@ const char *acpi_ut_get_reference_name(union acpi_operand_object *object) return (acpi_gbl_ref_class_names[object->reference.class]); } -#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -/* - * Strings and procedures used for debug only - */ - /******************************************************************************* * * FUNCTION: acpi_ut_get_mutex_name @@ -433,6 +428,12 @@ const char *acpi_ut_get_mutex_name(u32 mutex_id) return (acpi_gbl_mutex_names[mutex_id]); } +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* + * Strings and procedures used for debug only + */ + /******************************************************************************* * * FUNCTION: acpi_ut_get_notify_name -- cgit v1.2.3 From 0d4b54c6fee87ff60b0bc1007ca487449698468d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 18 Nov 2017 15:31:49 +0100 Subject: PM / core: Add LEAVE_SUSPENDED driver flag Define and document a new driver flag, DPM_FLAG_LEAVE_SUSPENDED, to instruct the PM core and middle-layer (bus type, PM domain, etc.) code that it is desirable to leave the device in runtime suspend after system-wide transitions to the working state (for example, the device may be slow to resume and it may be better to avoid resuming it right away). Generally, the middle-layer code involved in the handling of the device is expected to indicate to the PM core whether or not the device may be left in suspend with the help of the device's power.may_skip_resume status bit. That has to happen in the "noirq" phase of the preceding system suspend (or analogous) transition. The middle layer is then responsible for handling the device as appropriate in its "noirq" resume callback which is executed regardless of whether or not the device may be left suspended, but the other resume callbacks (except for ->complete) will be skipped automatically by the core if the device really can be left in suspend. The additional power.must_resume status bit introduced for the implementation of this mechanisn is used internally by the PM core to track the requirement to resume the device (which may depend on its children etc). Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Reviewed-by: Ulf Hansson --- Documentation/driver-api/pm/devices.rst | 27 +++++++++++- drivers/base/power/main.c | 73 ++++++++++++++++++++++++++++++--- include/linux/pm.h | 16 ++++++-- 3 files changed, 105 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/Documentation/driver-api/pm/devices.rst b/Documentation/driver-api/pm/devices.rst index 53c1b0b06da5..b0fe63c91f8d 100644 --- a/Documentation/driver-api/pm/devices.rst +++ b/Documentation/driver-api/pm/devices.rst @@ -788,6 +788,29 @@ must reflect the "active" status for runtime PM in that case. During system-wide resume from a sleep state it's easiest to put devices into the full-power state, as explained in :file:`Documentation/power/runtime_pm.txt`. -Refer to that document for more information regarding this particular issue as +[Refer to that document for more information regarding this particular issue as well as for information on the device runtime power management framework in -general. +general.] + +However, it often is desirable to leave devices in suspend after system +transitions to the working state, especially if those devices had been in +runtime suspend before the preceding system-wide suspend (or analogous) +transition. Device drivers can use the ``DPM_FLAG_LEAVE_SUSPENDED`` flag to +indicate to the PM core (and middle-layer code) that they prefer the specific +devices handled by them to be left suspended and they have no problems with +skipping their system-wide resume callbacks for this reason. Whether or not the +devices will actually be left in suspend may depend on their state before the +given system suspend-resume cycle and on the type of the system transition under +way. In particular, devices are not left suspended if that transition is a +restore from hibernation, as device states are not guaranteed to be reflected +by the information stored in the hibernation image in that case. + +The middle-layer code involved in the handling of the device is expected to +indicate to the PM core if the device may be left in suspend by setting its +:c:member:`power.may_skip_resume` status bit which is checked by the PM core +during the "noirq" phase of the preceding system-wide suspend (or analogous) +transition. The middle layer is then responsible for handling the device as +appropriate in its "noirq" resume callback, which is executed regardless of +whether or not the device is left suspended, but the other resume callbacks +(except for ``->complete``) will be skipped automatically by the PM core if the +device really can be left in suspend. diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index db2f04415927..73ec6796d9e1 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -525,6 +525,18 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd) /*------------------------- Resume routines -------------------------*/ +/** + * dev_pm_may_skip_resume - System-wide device resume optimization check. + * @dev: Target device. + * + * Checks whether or not the device may be left in suspend after a system-wide + * transition to the working state. + */ +bool dev_pm_may_skip_resume(struct device *dev) +{ + return !dev->power.must_resume && pm_transition.event != PM_EVENT_RESTORE; +} + /** * device_resume_noirq - Execute a "noirq resume" callback for given device. * @dev: Device to handle. @@ -573,6 +585,19 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn error = dpm_run_callback(callback, dev, state, info); dev->power.is_noirq_suspended = false; + if (dev_pm_may_skip_resume(dev)) { + /* + * The device is going to be left in suspend, but it might not + * have been in runtime suspend before the system suspended, so + * its runtime PM status needs to be updated to avoid confusing + * the runtime PM framework when runtime PM is enabled for the + * device again. + */ + pm_runtime_set_suspended(dev); + dev->power.is_late_suspended = false; + dev->power.is_suspended = false; + } + Out: complete_all(&dev->power.completion); TRACE_RESUME(error); @@ -1074,6 +1099,22 @@ static pm_message_t resume_event(pm_message_t sleep_state) return PMSG_ON; } +static void dpm_superior_set_must_resume(struct device *dev) +{ + struct device_link *link; + int idx; + + if (dev->parent) + dev->parent->power.must_resume = true; + + idx = device_links_read_lock(); + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) + link->supplier->power.must_resume = true; + + device_links_read_unlock(idx); +} + /** * __device_suspend_noirq - Execute a "noirq suspend" callback for given device. * @dev: Device to handle. @@ -1125,10 +1166,28 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a } error = dpm_run_callback(callback, dev, state, info); - if (!error) - dev->power.is_noirq_suspended = true; - else + if (error) { async_error = error; + goto Complete; + } + + dev->power.is_noirq_suspended = true; + + if (dev_pm_test_driver_flags(dev, DPM_FLAG_LEAVE_SUSPENDED)) { + /* + * The only safe strategy here is to require that if the device + * may not be left in suspend, resume callbacks must be invoked + * for it. + */ + dev->power.must_resume = dev->power.must_resume || + !dev->power.may_skip_resume || + atomic_read(&dev->power.usage_count) > 1; + } else { + dev->power.must_resume = true; + } + + if (dev->power.must_resume) + dpm_superior_set_must_resume(dev); Complete: complete_all(&dev->power.completion); @@ -1485,6 +1544,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) dev->power.direct_complete = false; } + dev->power.may_skip_resume = false; + dev->power.must_resume = false; + dpm_watchdog_set(&wd, dev); device_lock(dev); @@ -1650,8 +1712,9 @@ static int device_prepare(struct device *dev, pm_message_t state) if (dev->power.syscore) return 0; - WARN_ON(dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) && - !pm_runtime_enabled(dev)); + WARN_ON(!pm_runtime_enabled(dev) && + dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND | + DPM_FLAG_LEAVE_SUSPENDED)); /* * If a device's parent goes into runtime suspend at the wrong time, diff --git a/include/linux/pm.h b/include/linux/pm.h index 65d39115f06d..b5a40b713e9e 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -556,9 +556,10 @@ struct pm_subsys_data { * These flags can be set by device drivers at the probe time. They need not be * cleared by the drivers as the driver core will take care of that. * - * NEVER_SKIP: Do not skip system suspend/resume callbacks for the device. + * NEVER_SKIP: Do not skip all system suspend/resume callbacks for the device. * SMART_PREPARE: Check the return value of the driver's ->prepare callback. * SMART_SUSPEND: No need to resume the device from runtime suspend. + * LEAVE_SUSPENDED: Avoid resuming the device during system resume if possible. * * Setting SMART_PREPARE instructs bus types and PM domains which may want * system suspend/resume callbacks to be skipped for the device to return 0 from @@ -572,10 +573,14 @@ struct pm_subsys_data { * necessary from the driver's perspective. It also may cause them to skip * invocations of the ->suspend_late and ->suspend_noirq callbacks provided by * the driver if they decide to leave the device in runtime suspend. + * + * Setting LEAVE_SUSPENDED informs the PM core and middle-layer code that the + * driver prefers the device to be left in suspend after system resume. */ -#define DPM_FLAG_NEVER_SKIP BIT(0) -#define DPM_FLAG_SMART_PREPARE BIT(1) -#define DPM_FLAG_SMART_SUSPEND BIT(2) +#define DPM_FLAG_NEVER_SKIP BIT(0) +#define DPM_FLAG_SMART_PREPARE BIT(1) +#define DPM_FLAG_SMART_SUSPEND BIT(2) +#define DPM_FLAG_LEAVE_SUSPENDED BIT(3) struct dev_pm_info { pm_message_t power_state; @@ -597,6 +602,8 @@ struct dev_pm_info { bool wakeup_path:1; bool syscore:1; bool no_pm_callbacks:1; /* Owned by the PM core */ + unsigned int must_resume:1; /* Owned by the PM core */ + unsigned int may_skip_resume:1; /* Set by subsystems */ #else unsigned int should_wakeup:1; #endif @@ -765,6 +772,7 @@ extern int pm_generic_poweroff_late(struct device *dev); extern int pm_generic_poweroff(struct device *dev); extern void pm_generic_complete(struct device *dev); +extern bool dev_pm_may_skip_resume(struct device *dev); extern bool dev_pm_smart_suspend_and_suspended(struct device *dev); #else /* !CONFIG_PM_SLEEP */ -- cgit v1.2.3 From bd755d770ac78e8eeda05877ba66cc66f151e10e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 18 Nov 2017 15:33:52 +0100 Subject: PCI / PM: Support for LEAVE_SUSPENDED driver flag Add support for DPM_FLAG_LEAVE_SUSPENDED to the PCI bus type by making it (a) set the power.may_skip_resume status bit for devices that, from its perspective, may be left in suspend after system wakeup from sleep and (b) return early from pci_pm_resume_noirq() for devices whose remaining resume callbacks during the transition under way are going to be skipped by the PM core. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Acked-by: Bjorn Helgaas --- Documentation/power/pci.txt | 11 +++++++++++ drivers/pci/pci-driver.c | 19 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt index 704cd36079b8..8eaf9ee24d43 100644 --- a/Documentation/power/pci.txt +++ b/Documentation/power/pci.txt @@ -994,6 +994,17 @@ into D0 going forward), but if it is in runtime suspend in pci_pm_thaw_noirq(), the function will set the power.direct_complete flag for it (to make the PM core skip the subsequent "thaw" callbacks for it) and return. +Setting the DPM_FLAG_LEAVE_SUSPENDED flag means that the driver prefers the +device to be left in suspend after system-wide transitions to the working state. +This flag is checked by the PM core, but the PCI bus type informs the PM core +which devices may be left in suspend from its perspective (that happens during +the "noirq" phase of system-wide suspend and analogous transitions) and next it +uses the dev_pm_may_skip_resume() helper to decide whether or not to return from +pci_pm_resume_noirq() early, as the PM core will skip the remaining resume +callbacks for the device during the transition under way and will set its +runtime PM status to "suspended" if dev_pm_may_skip_resume() returns "true" for +it. + 3.2. Device Runtime Power Management ------------------------------------ In addition to providing device power management callbacks PCI device drivers diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 7f47bb72bf30..3cf2da22acf2 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -699,7 +699,7 @@ static void pci_pm_complete(struct device *dev) pm_generic_complete(dev); /* Resume device if platform firmware has put it in reset-power-on */ - if (dev->power.direct_complete && pm_resume_via_firmware()) { + if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) { pci_power_t pre_sleep_state = pci_dev->current_state; pci_update_current_state(pci_dev, pci_dev->current_state); @@ -783,8 +783,10 @@ static int pci_pm_suspend_noirq(struct device *dev) struct pci_dev *pci_dev = to_pci_dev(dev); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (dev_pm_smart_suspend_and_suspended(dev)) + if (dev_pm_smart_suspend_and_suspended(dev)) { + dev->power.may_skip_resume = true; return 0; + } if (pci_has_legacy_pm_support(pci_dev)) return pci_legacy_suspend_late(dev, PMSG_SUSPEND); @@ -838,6 +840,16 @@ static int pci_pm_suspend_noirq(struct device *dev) Fixup: pci_fixup_device(pci_fixup_suspend_late, pci_dev); + /* + * If the target system sleep state is suspend-to-idle, it is sufficient + * to check whether or not the device's wakeup settings are good for + * runtime PM. Otherwise, the pm_resume_via_firmware() check will cause + * pci_pm_complete() to take care of fixing up the device's state + * anyway, if need be. + */ + dev->power.may_skip_resume = device_may_wakeup(dev) || + !device_can_wakeup(dev); + return 0; } @@ -847,6 +859,9 @@ static int pci_pm_resume_noirq(struct device *dev) struct device_driver *drv = dev->driver; int error = 0; + if (dev_pm_may_skip_resume(dev)) + return 0; + /* * Devices with DPM_FLAG_SMART_SUSPEND may be left in runtime suspend * during system suspend, so update their runtime PM status to "active" -- cgit v1.2.3 From db68daff90ef79761cc0bba16f775b6027ea3a83 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 18 Nov 2017 15:35:00 +0100 Subject: ACPI / PM: Support for LEAVE_SUSPENDED driver flag in ACPI PM domain Add support for DPM_FLAG_LEAVE_SUSPENDED to the ACPI PM domain by making it (a) set the power.may_skip_resume status bit for devices that, from its perspective, may be left in suspend after system wakeup from sleep and (b) return early from acpi_subsys_resume_noirq() for devices whose remaining resume callbacks during the transition under way are going to be skipped by the PM core. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman --- drivers/acpi/device_pm.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index e4ffaeec9ec2..5cfe794c36bd 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -990,7 +990,7 @@ void acpi_subsys_complete(struct device *dev) * the sleep state it is going out of and it has never been resumed till * now, resume it in case the firmware powered it up. */ - if (dev->power.direct_complete && pm_resume_via_firmware()) + if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) pm_request_resume(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_complete); @@ -1039,10 +1039,28 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late); */ int acpi_subsys_suspend_noirq(struct device *dev) { - if (dev_pm_smart_suspend_and_suspended(dev)) + int ret; + + if (dev_pm_smart_suspend_and_suspended(dev)) { + dev->power.may_skip_resume = true; return 0; + } + + ret = pm_generic_suspend_noirq(dev); + if (ret) + return ret; + + /* + * If the target system sleep state is suspend-to-idle, it is sufficient + * to check whether or not the device's wakeup settings are good for + * runtime PM. Otherwise, the pm_resume_via_firmware() check will cause + * acpi_subsys_complete() to take care of fixing up the device's state + * anyway, if need be. + */ + dev->power.may_skip_resume = device_may_wakeup(dev) || + !device_can_wakeup(dev); - return pm_generic_suspend_noirq(dev); + return 0; } EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq); @@ -1052,6 +1070,9 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq); */ int acpi_subsys_resume_noirq(struct device *dev) { + if (dev_pm_may_skip_resume(dev)) + return 0; + /* * Devices with DPM_FLAG_SMART_SUSPEND may be left in runtime suspend * during system suspend, so update their runtime PM status to "active" -- cgit v1.2.3 From 57044031b0cb11325e1034394a4721484f9dc9fe Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Nov 2017 02:16:55 +0100 Subject: ACPI / PM: Make it possible to ignore the system sleep blacklist The ACPI code supporting system transitions to sleep states uses an internal blacklist to apply special handling to some machines reported to behave incorrectly in some ways. However, some entries of that blacklist cover problematic as well as non-problematic systems, so give the users of the latter a chance to ignore the blacklist and run their systems in the default way by adding acpi_sleep=nobl to the kernel command line. For example, that allows the users of Dell XPS13 9360 systems not affected by the issue that caused the blacklist entry for this machine to be added by commit 71630b7a832f (ACPI / PM: Blacklist Low Power S0 Idle _DSM for Dell XPS13 9360) to use suspend-to-idle with the Low Power S0 Idle _DSM interface which in principle should be more energy-efficient than S3 on them. Signed-off-by: Rafael J. Wysocki --- Documentation/admin-guide/kernel-parameters.txt | 5 ++++- arch/x86/kernel/acpi/sleep.c | 2 ++ drivers/acpi/sleep.c | 10 ++++++++++ include/linux/acpi.h | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 6571fbfdb2a1..b125690d5dbc 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -223,7 +223,7 @@ acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, - old_ordering, nonvs, sci_force_enable } + old_ordering, nonvs, sci_force_enable, nobl } See Documentation/power/video.txt for information on s3_bios and s3_mode. s3_beep is for debugging; it makes the PC's speaker beep @@ -239,6 +239,9 @@ sci_force_enable causes the kernel to set SCI_EN directly on resume from S1/S3 (which is against the ACPI spec, but some broken systems don't work without it). + nobl causes the internal blacklist of systems known to + behave incorrectly in some ways with respect to system + suspend and resume to be ignored (use wisely). acpi_use_timer_override [HW,ACPI] Use timer override. For some broken Nvidia NF5 boards diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 7188aea91549..f1915b744052 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -138,6 +138,8 @@ static int __init acpi_sleep_setup(char *str) acpi_nvs_nosave_s3(); if (strncmp(str, "old_ordering", 12) == 0) acpi_old_suspend_ordering(); + if (strncmp(str, "nobl", 4) == 0) + acpi_sleep_no_blacklist(); str = strchr(str, ','); if (str != NULL) str += strspn(str, ", \t"); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 8082871b409a..15cd862a87c2 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -367,10 +367,20 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = { {}, }; +static bool ignore_blacklist; + +void __init acpi_sleep_no_blacklist(void) +{ + ignore_blacklist = true; +} + static void __init acpi_sleep_dmi_check(void) { int year; + if (ignore_blacklist) + return; + if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012) acpi_nvs_nosave_s3(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index dc1ebfeeb5ec..699655a9618b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -451,6 +451,7 @@ void __init acpi_no_s4_hw_signature(void); void __init acpi_old_suspend_ordering(void); void __init acpi_nvs_nosave(void); void __init acpi_nvs_nosave_s3(void); +void __init acpi_sleep_no_blacklist(void); #endif /* CONFIG_PM_SLEEP */ struct acpi_osc_context { -- cgit v1.2.3 From 2d18baf6ed8ecf0e6419ad34cbe0fa7c616a8825 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 9 Nov 2017 09:40:59 +0100 Subject: extcon: max77693: Delete unneeded initialization in max77693_muic_set_path() The variable "ret" will be set to an appropriate value a bit later. Thus this patch omits the explicit initialization at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-max77693.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 643411066ad9..227651ff9666 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -266,7 +266,7 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, static int max77693_muic_set_path(struct max77693_muic_info *info, u8 val, bool attached) { - int ret = 0; + int ret; unsigned int ctrl1, ctrl2 = 0; if (attached) -- cgit v1.2.3 From 00c2f524b8bb3e84b88aec0919a61ce947554c53 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 9 Nov 2017 10:00:08 +0100 Subject: extcon: max8997: Delete unneeded initialization in max8997_muic_set_path() The variable "ret" will be set to an appropriate value a bit later. Thus this patch omits the explicit initialization at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-max8997.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index 8152790d72e1..9f30f4929b72 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -204,7 +204,7 @@ static int max8997_muic_set_debounce_time(struct max8997_muic_info *info, static int max8997_muic_set_path(struct max8997_muic_info *info, u8 val, bool attached) { - int ret = 0; + int ret; u8 ctrl1, ctrl2 = 0; if (attached) -- cgit v1.2.3 From 447641eb88287fa29971b076166397e3f4cce3dd Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Thu, 23 Nov 2017 21:25:29 +0530 Subject: extcon: adc-jack: Fix platform_get_irq's error checking The platform_get_irq() function returns negative if an error occurs. zero or positive number on success. platform_get_irq() error checking for zero is not correct. Signed-off-by: Arvind Yadav Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-adc-jack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 3877d86c746a..18026354c332 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -144,7 +144,7 @@ static int adc_jack_probe(struct platform_device *pdev) return err; data->irq = platform_get_irq(pdev, 0); - if (!data->irq) { + if (data->irq < 0) { dev_err(&pdev->dev, "platform_get_irq failed\n"); return -ENODEV; } -- cgit v1.2.3 From 1554bbd4ad401b7f0f916c0891874111c10befe5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 29 Oct 2017 01:50:06 +0900 Subject: reset: make device_reset_optional() really optional Commit bb475230b8e5 ("reset: make optional functions really optional") converted *_get_optional* functions, but device_reset_optional() was left behind. Convert it in the same way. Signed-off-by: Masahiro Yamada Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 9 +++++---- include/linux/reset.h | 28 +++++++++++++--------------- 2 files changed, 18 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 1d21c6f7d56c..da4292e9de97 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -566,17 +566,18 @@ EXPORT_SYMBOL_GPL(__devm_reset_control_get); * device_reset - find reset controller associated with the device * and perform reset * @dev: device to be reset by the controller + * @optional: whether it is optional to reset the device * - * Convenience wrapper for reset_control_get() and reset_control_reset(). + * Convenience wrapper for __reset_control_get() and reset_control_reset(). * This is useful for the common case of devices with single, dedicated reset * lines. */ -int device_reset(struct device *dev) +int __device_reset(struct device *dev, bool optional) { struct reset_control *rstc; int ret; - rstc = reset_control_get(dev, NULL); + rstc = __reset_control_get(dev, NULL, 0, 0, optional); if (IS_ERR(rstc)) return PTR_ERR(rstc); @@ -586,7 +587,7 @@ int device_reset(struct device *dev) return ret; } -EXPORT_SYMBOL_GPL(device_reset); +EXPORT_SYMBOL_GPL(__device_reset); /** * APIs to manage an array of reset controls. diff --git a/include/linux/reset.h b/include/linux/reset.h index 4c7871ddf3c6..b681019fc04c 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -20,22 +20,16 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional); void reset_control_put(struct reset_control *rstc); +int __device_reset(struct device *dev, bool optional); struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional); -int __must_check device_reset(struct device *dev); - struct reset_control *devm_reset_control_array_get(struct device *dev, bool shared, bool optional); struct reset_control *of_reset_control_array_get(struct device_node *np, bool shared, bool optional); -static inline int device_reset_optional(struct device *dev) -{ - return device_reset(dev); -} - #else static inline int reset_control_reset(struct reset_control *rstc) @@ -62,15 +56,9 @@ static inline void reset_control_put(struct reset_control *rstc) { } -static inline int __must_check device_reset(struct device *dev) +static inline int __device_reset(struct device *dev, bool optional) { - WARN_ON(1); - return -ENOTSUPP; -} - -static inline int device_reset_optional(struct device *dev) -{ - return -ENOTSUPP; + return optional ? 0 : -ENOTSUPP; } static inline struct reset_control *__of_reset_control_get( @@ -109,6 +97,16 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional) #endif /* CONFIG_RESET_CONTROLLER */ +static inline int __must_check device_reset(struct device *dev) +{ + return __device_reset(dev, false); +} + +static inline int device_reset_optional(struct device *dev) +{ + return __device_reset(dev, true); +} + /** * reset_control_get_exclusive - Lookup and obtain an exclusive reference * to a reset controller. -- cgit v1.2.3 From 0e5721f76252d69d424ec87a391d5ea37414b641 Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Fri, 10 Nov 2017 16:46:50 +0800 Subject: reset: meson-axg: add compatible string for Meson-AXG SoC Try to add compatible string explictly to support new Meson-AXG SoC. Signed-off-by: Yixun Lan Reviewed-by: Neil Armstrong Signed-off-by: Philipp Zabel --- drivers/reset/reset-meson.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index c419a3753d00..93cbee1ae8ef 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -139,6 +139,8 @@ static const struct of_device_id meson_reset_dt_ids[] = { .data = &meson_reset_meson8_ops, }, { .compatible = "amlogic,meson-gxbb-reset", .data = &meson_reset_gx_ops, }, + { .compatible = "amlogic,meson-axg-reset", + .data = &meson_reset_gx_ops, }, { /* sentinel */ }, }; -- cgit v1.2.3 From 1a79f22de8102678e15ef9789c161fefd00fc802 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 14:58:50 +0100 Subject: staging: most: add SPDX identifiers to all most driver files It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the drivers/staging/most files files with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: Michael Fabry Cc: Christian Gromm Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 1 + drivers/staging/most/aim-network/networking.c | 1 + drivers/staging/most/aim-sound/sound.c | 1 + drivers/staging/most/aim-v4l2/video.c | 1 + drivers/staging/most/hdm-dim2/dim2_errors.h | 1 + drivers/staging/most/hdm-dim2/dim2_hal.c | 1 + drivers/staging/most/hdm-dim2/dim2_hal.h | 1 + drivers/staging/most/hdm-dim2/dim2_hdm.c | 1 + drivers/staging/most/hdm-dim2/dim2_hdm.h | 1 + drivers/staging/most/hdm-dim2/dim2_reg.h | 1 + drivers/staging/most/hdm-dim2/dim2_sysfs.c | 1 + drivers/staging/most/hdm-dim2/dim2_sysfs.h | 1 + drivers/staging/most/hdm-i2c/hdm_i2c.c | 1 + drivers/staging/most/hdm-usb/hdm_usb.c | 1 + drivers/staging/most/mostcore/core.c | 1 + drivers/staging/most/mostcore/mostcore.h | 1 + 16 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 1e5cbc893496..d6e7e85d9ece 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * cdev.c - Application interfacing module for character devices * diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 936f013c350e..e2dff6d5cf30 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Networking AIM - Networking Application Interface Module for MostCore * diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c index ea1366a44008..0f596ca532d8 100644 --- a/drivers/staging/most/aim-sound/sound.c +++ b/drivers/staging/most/aim-sound/sound.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * sound.c - Audio Application Interface Module for Mostcore * diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index e0748416aee5..e089d139b943 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * V4L2 AIM - V4L2 Application Interface Module for MostCore * diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h index 66343ba426c1..073d93cf4927 100644 --- a/drivers/staging/most/hdm-dim2/dim2_errors.h +++ b/drivers/staging/most/hdm-dim2/dim2_errors.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dim2_errors.h - Definitions of errors for DIM2 HAL API * (MediaLB, Device Interface Macro IP, OS62420) diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 91484643d289..f0a45863c8cb 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dim2_hal.c - DIM2 HAL implementation * (MediaLB, Device Interface Macro IP, OS62420) diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index 6df6ea5f7da4..df678124117c 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dim2_hal.h - DIM2 HAL interface * (MediaLB, Device Interface Macro IP, OS62420) diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index df7021c522b3..c59c8a526d06 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module * diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h index 4050e7c764ed..dc0293a7be1f 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.h +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dim2_hdm.h - MediaLB DIM2 HDM Header * diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h index f7d9fbcd29f2..c94220daec33 100644 --- a/drivers/staging/most/hdm-dim2/dim2_reg.h +++ b/drivers/staging/most/hdm-dim2/dim2_reg.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dim2_reg.h - Definitions for registers of DIM2 * (MediaLB, Device Interface Macro IP, OS62420) diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c index d8b22f91d2c3..144ab4281e31 100644 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.c +++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dim2_sysfs.c - MediaLB sysfs information * diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h index b71dd027ebc7..50d17176a1b8 100644 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.h +++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dim2_sysfs.h - MediaLB sysfs information * diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c index 2b4de404e46a..6272353dc8c3 100644 --- a/drivers/staging/most/hdm-i2c/hdm_i2c.c +++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * hdm_i2c.c - Hardware Dependent Module for I2C Interface * diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 667dacac81f0..368e0718bd6e 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * hdm_usb.c - Hardware dependent module for USB * diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 069269db394c..80040849160d 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * core.c - Implementation of core module of MOST Linux driver stack * diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h index 915e5159d1eb..6f15590417f5 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/mostcore/mostcore.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * mostcore.h - Interface between MostCore, * Hardware Dependent Module (HDM) and Application Interface Module (AIM). -- cgit v1.2.3 From c1dcb35bf18e8644f9487f5cd15e15fdd0bf1142 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 14:58:51 +0100 Subject: staging: most: Remove redundant license text Now that the SPDX tag is in all most driver files, that identifies the license in a specific and legally-defined manner. So the extra GPL text wording can be removed as it is no longer needed at all. This is done on a quest to remove the 700+ different ways that files in the kernel describe the GPL license text. And there's unneeded stuff like the address (sometimes incorrect) for the FSF which is never needed. No copyright headers or other non-license-description text was removed. Cc: Christian Gromm Cc: Michael Fabry Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 7 ------- drivers/staging/most/aim-network/networking.c | 7 ------- drivers/staging/most/aim-sound/sound.c | 7 ------- drivers/staging/most/aim-v4l2/video.c | 7 ------- drivers/staging/most/hdm-dim2/dim2_errors.h | 7 ------- drivers/staging/most/hdm-dim2/dim2_hal.c | 7 ------- drivers/staging/most/hdm-dim2/dim2_hal.h | 7 ------- drivers/staging/most/hdm-dim2/dim2_hdm.c | 7 ------- drivers/staging/most/hdm-dim2/dim2_hdm.h | 7 ------- drivers/staging/most/hdm-dim2/dim2_reg.h | 7 ------- drivers/staging/most/hdm-dim2/dim2_sysfs.c | 7 ------- drivers/staging/most/hdm-dim2/dim2_sysfs.h | 7 ------- drivers/staging/most/hdm-i2c/hdm_i2c.c | 7 ------- drivers/staging/most/hdm-usb/hdm_usb.c | 7 ------- drivers/staging/most/mostcore/core.c | 7 ------- drivers/staging/most/mostcore/mostcore.h | 7 ------- 16 files changed, 112 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index d6e7e85d9ece..5010c7bf8772 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -3,13 +3,6 @@ * cdev.c - Application interfacing module for character devices * * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index e2dff6d5cf30..d98eb893d44c 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -3,13 +3,6 @@ * Networking AIM - Networking Application Interface Module for MostCore * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c index 0f596ca532d8..d84a6e1b56a1 100644 --- a/drivers/staging/most/aim-sound/sound.c +++ b/drivers/staging/most/aim-sound/sound.c @@ -3,13 +3,6 @@ * sound.c - Audio Application Interface Module for Mostcore * * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index e089d139b943..72e9a9a5d8b3 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -3,13 +3,6 @@ * V4L2 AIM - V4L2 Application Interface Module for MostCore * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h index 073d93cf4927..8b90196076d5 100644 --- a/drivers/staging/most/hdm-dim2/dim2_errors.h +++ b/drivers/staging/most/hdm-dim2/dim2_errors.h @@ -4,13 +4,6 @@ * (MediaLB, Device Interface Macro IP, OS62420) * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #ifndef _MOST_DIM_ERRORS_H diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index f0a45863c8cb..f98ac935729c 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -4,13 +4,6 @@ * (MediaLB, Device Interface Macro IP, OS62420) * * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ /* Author: Andrey Shvetsov */ diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index df678124117c..fce9ae96121b 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -4,13 +4,6 @@ * (MediaLB, Device Interface Macro IP, OS62420) * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #ifndef _DIM2_HAL_H diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index c59c8a526d06..312f4f75ef06 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -3,13 +3,6 @@ * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module * * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h index dc0293a7be1f..5f380b648bd7 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.h +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.h @@ -3,13 +3,6 @@ * dim2_hdm.h - MediaLB DIM2 HDM Header * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #ifndef DIM2_HDM_H diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h index c94220daec33..2b2fca4f6451 100644 --- a/drivers/staging/most/hdm-dim2/dim2_reg.h +++ b/drivers/staging/most/hdm-dim2/dim2_reg.h @@ -4,13 +4,6 @@ * (MediaLB, Device Interface Macro IP, OS62420) * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #ifndef DIM2_OS62420_H diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c index 144ab4281e31..3a2ad355cab1 100644 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.c +++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.c @@ -3,13 +3,6 @@ * dim2_sysfs.c - MediaLB sysfs information * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ /* Author: Andrey Shvetsov */ diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h index 50d17176a1b8..e46dc4ba3946 100644 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.h +++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.h @@ -3,13 +3,6 @@ * dim2_sysfs.h - MediaLB sysfs information * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ /* Author: Andrey Shvetsov */ diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c index 6272353dc8c3..ed6793a1bc93 100644 --- a/drivers/staging/most/hdm-i2c/hdm_i2c.c +++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c @@ -3,13 +3,6 @@ * hdm_i2c.c - Hardware Dependent Module for I2C Interface * * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 368e0718bd6e..c01b93bb134f 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -3,13 +3,6 @@ * hdm_usb.c - Hardware dependent module for USB * * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 80040849160d..cb70e1029a93 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -3,13 +3,6 @@ * core.c - Implementation of core module of MOST Linux driver stack * * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h index 6f15590417f5..f6fdba0c5eaf 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/mostcore/mostcore.h @@ -4,13 +4,6 @@ * Hardware Dependent Module (HDM) and Application Interface Module (AIM). * * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. */ /* -- cgit v1.2.3 From 057301cd972e44fa97b4834d9421878fe5edc059 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:35 +0100 Subject: staging: most: move core files This patch moves the core files to the root dir of the driver. This is needed to clean up the directory layout. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Kconfig | 13 +- drivers/staging/most/Makefile | 5 +- drivers/staging/most/aim-cdev/Makefile | 2 +- drivers/staging/most/aim-cdev/cdev.c | 2 +- drivers/staging/most/aim-network/Makefile | 2 +- drivers/staging/most/aim-network/networking.c | 2 +- drivers/staging/most/aim-sound/Makefile | 2 +- drivers/staging/most/aim-sound/sound.c | 2 +- drivers/staging/most/aim-v4l2/Makefile | 2 +- drivers/staging/most/aim-v4l2/video.c | 2 +- drivers/staging/most/core.c | 1943 +++++++++++++++++++++++++ drivers/staging/most/core.h | 319 ++++ drivers/staging/most/hdm-dim2/Makefile | 2 +- drivers/staging/most/hdm-dim2/dim2_hdm.c | 2 +- drivers/staging/most/hdm-i2c/Makefile | 2 +- drivers/staging/most/hdm-i2c/hdm_i2c.c | 2 +- drivers/staging/most/hdm-usb/Makefile | 2 +- drivers/staging/most/hdm-usb/hdm_usb.c | 2 +- drivers/staging/most/mostcore/Kconfig | 14 - drivers/staging/most/mostcore/Makefile | 3 - drivers/staging/most/mostcore/core.c | 1943 ------------------------- drivers/staging/most/mostcore/mostcore.h | 319 ---- 22 files changed, 2288 insertions(+), 2299 deletions(-) create mode 100644 drivers/staging/most/core.c create mode 100644 drivers/staging/most/core.h delete mode 100644 drivers/staging/most/mostcore/Kconfig delete mode 100644 drivers/staging/most/mostcore/Makefile delete mode 100644 drivers/staging/most/mostcore/core.c delete mode 100644 drivers/staging/most/mostcore/mostcore.h (limited to 'drivers') diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 0b9b9b539f70..2045f7ac5081 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -1,10 +1,15 @@ menuconfig MOST - tristate "MOST driver" + tristate "MOST support" depends on HAS_DMA - select MOSTCORE default n ---help--- - This option allows you to enable support for MOST Network transceivers. + Say Y here if you want to enable MOST support. + This driver needs at least one additional component to enable the + desired access from userspace (e.g. character devices) and one that + matches the network controller's hardware interface (e.g. USB). + + To compile this driver as a module, choose M here: the + module will be called most_core. If in doubt, say N here. @@ -12,8 +17,6 @@ menuconfig MOST if MOST -source "drivers/staging/most/mostcore/Kconfig" - source "drivers/staging/most/aim-cdev/Kconfig" source "drivers/staging/most/aim-network/Kconfig" diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile index f5bbb9deaab5..7f6aa9c515fa 100644 --- a/drivers/staging/most/Makefile +++ b/drivers/staging/most/Makefile @@ -1,5 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_MOSTCORE) += mostcore/ +obj-$(CONFIG_MOST) += most_core.o +most_core-y := core.o +ccflags-y += -Idrivers/staging/ + obj-$(CONFIG_AIM_CDEV) += aim-cdev/ obj-$(CONFIG_AIM_NETWORK) += aim-network/ obj-$(CONFIG_AIM_SOUND) += aim-sound/ diff --git a/drivers/staging/most/aim-cdev/Makefile b/drivers/staging/most/aim-cdev/Makefile index 0bcc6c637b75..b7afcb40997d 100644 --- a/drivers/staging/most/aim-cdev/Makefile +++ b/drivers/staging/most/aim-cdev/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_AIM_CDEV) += aim_cdev.o aim_cdev-objs := cdev.o -ccflags-y += -Idrivers/staging/most/mostcore/ \ No newline at end of file +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 5010c7bf8772..3ae9246c0c5c 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -16,7 +16,7 @@ #include #include #include -#include "mostcore.h" +#include "most/core.h" static dev_t aim_devno; static struct class *aim_class; diff --git a/drivers/staging/most/aim-network/Makefile b/drivers/staging/most/aim-network/Makefile index 840c1dd94873..a874aac8d285 100644 --- a/drivers/staging/most/aim-network/Makefile +++ b/drivers/staging/most/aim-network/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_AIM_NETWORK) += aim_network.o aim_network-objs := networking.o -ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index d98eb893d44c..5e082d7d0e82 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -15,7 +15,7 @@ #include #include #include -#include "mostcore.h" +#include "most/core.h" #define MEP_HDR_LEN 8 #define MDP_HDR_LEN 16 diff --git a/drivers/staging/most/aim-sound/Makefile b/drivers/staging/most/aim-sound/Makefile index beba9586fd28..d41b85baa83f 100644 --- a/drivers/staging/most/aim-sound/Makefile +++ b/drivers/staging/most/aim-sound/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_AIM_SOUND) += aim_sound.o aim_sound-objs := sound.o -ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c index d84a6e1b56a1..5826f710c925 100644 --- a/drivers/staging/most/aim-sound/sound.c +++ b/drivers/staging/most/aim-sound/sound.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #define DRIVER_NAME "sound" diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile index 69a7524b466c..a8e8b4930355 100644 --- a/drivers/staging/most/aim-v4l2/Makefile +++ b/drivers/staging/most/aim-v4l2/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o aim_v4l2-objs := video.o -ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 72e9a9a5d8b3..3c813ed7f3ec 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -21,7 +21,7 @@ #include #include -#include "mostcore.h" +#include "most/core.h" #define V4L2_AIM_MAX_INPUT 1 diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c new file mode 100644 index 000000000000..8fe3f2ecd4e4 --- /dev/null +++ b/drivers/staging/most/core.c @@ -0,0 +1,1943 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * core.c - Implementation of core module of MOST Linux driver stack + * + * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_CHANNELS 64 +#define STRING_SIZE 80 + +static struct class *most_class; +static struct device *core_dev; +static struct ida mdev_id; +static int dummy_num_buffers; + +struct most_c_aim_obj { + struct most_aim *ptr; + int refs; + int num_buffers; +}; + +struct most_c_obj { + struct kobject kobj; + struct completion cleanup; + atomic_t mbo_ref; + atomic_t mbo_nq_level; + u16 channel_id; + bool is_poisoned; + struct mutex start_mutex; + struct mutex nq_mutex; /* nq thread synchronization */ + int is_starving; + struct most_interface *iface; + struct most_inst_obj *inst; + struct most_channel_config cfg; + bool keep_mbo; + bool enqueue_halt; + struct list_head fifo; + spinlock_t fifo_lock; + struct list_head halt_fifo; + struct list_head list; + struct most_c_aim_obj aim0; + struct most_c_aim_obj aim1; + struct list_head trash_fifo; + struct task_struct *hdm_enqueue_task; + wait_queue_head_t hdm_fifo_wq; +}; + +#define to_c_obj(d) container_of(d, struct most_c_obj, kobj) + +struct most_inst_obj { + int dev_id; + struct most_interface *iface; + struct list_head channel_list; + struct most_c_obj *channel[MAX_CHANNELS]; + struct kobject kobj; + struct list_head list; +}; + +static const struct { + int most_ch_data_type; + const char *name; +} ch_data_type[] = { + { MOST_CH_CONTROL, "control\n" }, + { MOST_CH_ASYNC, "async\n" }, + { MOST_CH_SYNC, "sync\n" }, + { MOST_CH_ISOC, "isoc\n"}, + { MOST_CH_ISOC, "isoc_avp\n"}, +}; + +#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) + +/** + * list_pop_mbo - retrieves the first MBO of the list and removes it + * @ptr: the list head to grab the MBO from. + */ +#define list_pop_mbo(ptr) \ +({ \ + struct mbo *_mbo = list_first_entry(ptr, struct mbo, list); \ + list_del(&_mbo->list); \ + _mbo; \ +}) + +/* ___ ___ + * ___C H A N N E L___ + */ + +/** + * struct most_c_attr - to access the attributes of a channel object + * @attr: attributes of a channel + * @show: pointer to the show function + * @store: pointer to the store function + */ +struct most_c_attr { + struct attribute attr; + ssize_t (*show)(struct most_c_obj *d, + struct most_c_attr *attr, + char *buf); + ssize_t (*store)(struct most_c_obj *d, + struct most_c_attr *attr, + const char *buf, + size_t count); +}; + +#define to_channel_attr(a) container_of(a, struct most_c_attr, attr) + +/** + * channel_attr_show - show function of channel object + * @kobj: pointer to its kobject + * @attr: pointer to its attributes + * @buf: buffer + */ +static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct most_c_attr *channel_attr = to_channel_attr(attr); + struct most_c_obj *c_obj = to_c_obj(kobj); + + if (!channel_attr->show) + return -EIO; + + return channel_attr->show(c_obj, channel_attr, buf); +} + +/** + * channel_attr_store - store function of channel object + * @kobj: pointer to its kobject + * @attr: pointer to its attributes + * @buf: buffer + * @len: length of buffer + */ +static ssize_t channel_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, + size_t len) +{ + struct most_c_attr *channel_attr = to_channel_attr(attr); + struct most_c_obj *c_obj = to_c_obj(kobj); + + if (!channel_attr->store) + return -EIO; + return channel_attr->store(c_obj, channel_attr, buf, len); +} + +static const struct sysfs_ops most_channel_sysfs_ops = { + .show = channel_attr_show, + .store = channel_attr_store, +}; + +/** + * most_free_mbo_coherent - free an MBO and its coherent buffer + * @mbo: buffer to be released + * + */ +static void most_free_mbo_coherent(struct mbo *mbo) +{ + struct most_c_obj *c = mbo->context; + u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; + + dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address, + mbo->bus_address); + kfree(mbo); + if (atomic_sub_and_test(1, &c->mbo_ref)) + complete(&c->cleanup); +} + +/** + * flush_channel_fifos - clear the channel fifos + * @c: pointer to channel object + */ +static void flush_channel_fifos(struct most_c_obj *c) +{ + unsigned long flags, hf_flags; + struct mbo *mbo, *tmp; + + if (list_empty(&c->fifo) && list_empty(&c->halt_fifo)) + return; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_for_each_entry_safe(mbo, tmp, &c->fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, flags); + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, flags); + } + spin_unlock_irqrestore(&c->fifo_lock, flags); + + spin_lock_irqsave(&c->fifo_lock, hf_flags); + list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, hf_flags); + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, hf_flags); + } + spin_unlock_irqrestore(&c->fifo_lock, hf_flags); + + if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo)))) + pr_info("WARN: fifo | trash fifo not empty\n"); +} + +/** + * flush_trash_fifo - clear the trash fifo + * @c: pointer to channel object + */ +static int flush_trash_fifo(struct most_c_obj *c) +{ + struct mbo *mbo, *tmp; + unsigned long flags; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, flags); + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, flags); + } + spin_unlock_irqrestore(&c->fifo_lock, flags); + return 0; +} + +/** + * most_channel_release - release function of channel object + * @kobj: pointer to channel's kobject + */ +static void most_channel_release(struct kobject *kobj) +{ + struct most_c_obj *c = to_c_obj(kobj); + + kfree(c); +} + +static ssize_t available_directions_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + strcpy(buf, ""); + if (c->iface->channel_vector[i].direction & MOST_CH_RX) + strcat(buf, "rx "); + if (c->iface->channel_vector[i].direction & MOST_CH_TX) + strcat(buf, "tx "); + strcat(buf, "\n"); + return strlen(buf); +} + +static ssize_t available_datatypes_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + strcpy(buf, ""); + if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL) + strcat(buf, "control "); + if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC) + strcat(buf, "async "); + if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC) + strcat(buf, "sync "); + if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC) + strcat(buf, "isoc "); + strcat(buf, "\n"); + return strlen(buf); +} + +static ssize_t number_of_packet_buffers_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].num_buffers_packet); +} + +static ssize_t number_of_stream_buffers_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].num_buffers_streaming); +} + +static ssize_t size_of_packet_buffer_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].buffer_size_packet); +} + +static ssize_t size_of_stream_buffer_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].buffer_size_streaming); +} + +static ssize_t channel_starving_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); +} + +static ssize_t set_number_of_buffers_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); +} + +static ssize_t set_number_of_buffers_store(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); + + if (ret) + return ret; + return count; +} + +static ssize_t set_buffer_size_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); +} + +static ssize_t set_buffer_size_store(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); + + if (ret) + return ret; + return count; +} + +static ssize_t set_direction_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + if (c->cfg.direction & MOST_CH_TX) + return snprintf(buf, PAGE_SIZE, "tx\n"); + else if (c->cfg.direction & MOST_CH_RX) + return snprintf(buf, PAGE_SIZE, "rx\n"); + return snprintf(buf, PAGE_SIZE, "unconfigured\n"); +} + +static ssize_t set_direction_store(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + if (!strcmp(buf, "dir_rx\n")) { + c->cfg.direction = MOST_CH_RX; + } else if (!strcmp(buf, "rx\n")) { + c->cfg.direction = MOST_CH_RX; + } else if (!strcmp(buf, "dir_tx\n")) { + c->cfg.direction = MOST_CH_TX; + } else if (!strcmp(buf, "tx\n")) { + c->cfg.direction = MOST_CH_TX; + } else { + pr_info("WARN: invalid attribute settings\n"); + return -EINVAL; + } + return count; +} + +static ssize_t set_datatype_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) + return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); + } + return snprintf(buf, PAGE_SIZE, "unconfigured\n"); +} + +static ssize_t set_datatype_store(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (!strcmp(buf, ch_data_type[i].name)) { + c->cfg.data_type = ch_data_type[i].most_ch_data_type; + break; + } + } + + if (i == ARRAY_SIZE(ch_data_type)) { + pr_info("WARN: invalid attribute settings\n"); + return -EINVAL; + } + return count; +} + +static ssize_t set_subbuffer_size_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); +} + +static ssize_t set_subbuffer_size_store(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); + + if (ret) + return ret; + return count; +} + +static ssize_t set_packets_per_xact_show(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); +} + +static ssize_t set_packets_per_xact_store(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); + + if (ret) + return ret; + return count; +} + +static struct most_c_attr most_c_attrs[] = { + __ATTR_RO(available_directions), + __ATTR_RO(available_datatypes), + __ATTR_RO(number_of_packet_buffers), + __ATTR_RO(number_of_stream_buffers), + __ATTR_RO(size_of_stream_buffer), + __ATTR_RO(size_of_packet_buffer), + __ATTR_RO(channel_starving), + __ATTR_RW(set_buffer_size), + __ATTR_RW(set_number_of_buffers), + __ATTR_RW(set_direction), + __ATTR_RW(set_datatype), + __ATTR_RW(set_subbuffer_size), + __ATTR_RW(set_packets_per_xact), +}; + +/** + * most_channel_def_attrs - array of default attributes of channel object + */ +static struct attribute *most_channel_def_attrs[] = { + &most_c_attrs[0].attr, + &most_c_attrs[1].attr, + &most_c_attrs[2].attr, + &most_c_attrs[3].attr, + &most_c_attrs[4].attr, + &most_c_attrs[5].attr, + &most_c_attrs[6].attr, + &most_c_attrs[7].attr, + &most_c_attrs[8].attr, + &most_c_attrs[9].attr, + &most_c_attrs[10].attr, + &most_c_attrs[11].attr, + &most_c_attrs[12].attr, + NULL, +}; + +static struct kobj_type most_channel_ktype = { + .sysfs_ops = &most_channel_sysfs_ops, + .release = most_channel_release, + .default_attrs = most_channel_def_attrs, +}; + +static struct kset *most_channel_kset; + +/** + * create_most_c_obj - allocates a channel object + * @name: name of the channel object + * @parent: parent kobject + * + * This create a channel object and registers it with sysfs. + * Returns a pointer to the object or NULL when something went wrong. + */ +static struct most_c_obj * +create_most_c_obj(const char *name, struct kobject *parent) +{ + struct most_c_obj *c; + int retval; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return NULL; + c->kobj.kset = most_channel_kset; + retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent, + "%s", name); + if (retval) { + kobject_put(&c->kobj); + return NULL; + } + kobject_uevent(&c->kobj, KOBJ_ADD); + return c; +} + +/* ___ ___ + * ___I N S T A N C E___ + */ + +static struct list_head instance_list; + +/** + * struct most_inst_attribute - to access the attributes of instance object + * @attr: attributes of an instance + * @show: pointer to the show function + * @store: pointer to the store function + */ +struct most_inst_attribute { + struct attribute attr; + ssize_t (*show)(struct most_inst_obj *d, + struct most_inst_attribute *attr, + char *buf); + ssize_t (*store)(struct most_inst_obj *d, + struct most_inst_attribute *attr, + const char *buf, + size_t count); +}; + +#define to_instance_attr(a) \ + container_of(a, struct most_inst_attribute, attr) + +/** + * instance_attr_show - show function for an instance object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + */ +static ssize_t instance_attr_show(struct kobject *kobj, + struct attribute *attr, + char *buf) +{ + struct most_inst_attribute *instance_attr; + struct most_inst_obj *instance_obj; + + instance_attr = to_instance_attr(attr); + instance_obj = to_inst_obj(kobj); + + if (!instance_attr->show) + return -EIO; + + return instance_attr->show(instance_obj, instance_attr, buf); +} + +/** + * instance_attr_store - store function for an instance object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + * @len: length of buffer + */ +static ssize_t instance_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, + size_t len) +{ + struct most_inst_attribute *instance_attr; + struct most_inst_obj *instance_obj; + + instance_attr = to_instance_attr(attr); + instance_obj = to_inst_obj(kobj); + + if (!instance_attr->store) + return -EIO; + + return instance_attr->store(instance_obj, instance_attr, buf, len); +} + +static const struct sysfs_ops most_inst_sysfs_ops = { + .show = instance_attr_show, + .store = instance_attr_store, +}; + +/** + * most_inst_release - release function for instance object + * @kobj: pointer to instance's kobject + * + * This frees the allocated memory for the instance object + */ +static void most_inst_release(struct kobject *kobj) +{ + struct most_inst_obj *inst = to_inst_obj(kobj); + + kfree(inst); +} + +static ssize_t description_show(struct most_inst_obj *instance_obj, + struct most_inst_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", + instance_obj->iface->description); +} + +static ssize_t interface_show(struct most_inst_obj *instance_obj, + struct most_inst_attribute *attr, + char *buf) +{ + switch (instance_obj->iface->interface) { + case ITYPE_LOOPBACK: + return snprintf(buf, PAGE_SIZE, "loopback\n"); + case ITYPE_I2C: + return snprintf(buf, PAGE_SIZE, "i2c\n"); + case ITYPE_I2S: + return snprintf(buf, PAGE_SIZE, "i2s\n"); + case ITYPE_TSI: + return snprintf(buf, PAGE_SIZE, "tsi\n"); + case ITYPE_HBI: + return snprintf(buf, PAGE_SIZE, "hbi\n"); + case ITYPE_MEDIALB_DIM: + return snprintf(buf, PAGE_SIZE, "mlb_dim\n"); + case ITYPE_MEDIALB_DIM2: + return snprintf(buf, PAGE_SIZE, "mlb_dim2\n"); + case ITYPE_USB: + return snprintf(buf, PAGE_SIZE, "usb\n"); + case ITYPE_PCIE: + return snprintf(buf, PAGE_SIZE, "pcie\n"); + } + return snprintf(buf, PAGE_SIZE, "unknown\n"); +} + +static struct most_inst_attribute most_inst_attr_description = + __ATTR_RO(description); + +static struct most_inst_attribute most_inst_attr_interface = + __ATTR_RO(interface); + +static struct attribute *most_inst_def_attrs[] = { + &most_inst_attr_description.attr, + &most_inst_attr_interface.attr, + NULL, +}; + +static struct kobj_type most_inst_ktype = { + .sysfs_ops = &most_inst_sysfs_ops, + .release = most_inst_release, + .default_attrs = most_inst_def_attrs, +}; + +static struct kset *most_inst_kset; + +/** + * create_most_inst_obj - creates an instance object + * @name: name of the object to be created + * + * This allocates memory for an instance structure, assigns the proper kset + * and registers it with sysfs. + * + * Returns a pointer to the instance object or NULL when something went wrong. + */ +static struct most_inst_obj *create_most_inst_obj(const char *name) +{ + struct most_inst_obj *inst; + int retval; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return NULL; + inst->kobj.kset = most_inst_kset; + retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL, + "%s", name); + if (retval) { + kobject_put(&inst->kobj); + return NULL; + } + kobject_uevent(&inst->kobj, KOBJ_ADD); + return inst; +} + +/** + * destroy_most_inst_obj - MOST instance release function + * @inst: pointer to the instance object + * + * This decrements the reference counter of the instance object. + * If the reference count turns zero, its release function is called + */ +static void destroy_most_inst_obj(struct most_inst_obj *inst) +{ + struct most_c_obj *c, *tmp; + + list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { + flush_trash_fifo(c); + flush_channel_fifos(c); + kobject_put(&c->kobj); + } + kobject_put(&inst->kobj); +} + +/* ___ ___ + * ___A I M___ + */ +struct most_aim_obj { + struct kobject kobj; + struct list_head list; + struct most_aim *driver; +}; + +#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj) + +static struct list_head aim_list; + +/** + * struct most_aim_attribute - to access the attributes of AIM object + * @attr: attributes of an AIM + * @show: pointer to the show function + * @store: pointer to the store function + */ +struct most_aim_attribute { + struct attribute attr; + ssize_t (*show)(struct most_aim_obj *d, + struct most_aim_attribute *attr, + char *buf); + ssize_t (*store)(struct most_aim_obj *d, + struct most_aim_attribute *attr, + const char *buf, + size_t count); +}; + +#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr) + +/** + * aim_attr_show - show function of an AIM object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + */ +static ssize_t aim_attr_show(struct kobject *kobj, + struct attribute *attr, + char *buf) +{ + struct most_aim_attribute *aim_attr; + struct most_aim_obj *aim_obj; + + aim_attr = to_aim_attr(attr); + aim_obj = to_aim_obj(kobj); + + if (!aim_attr->show) + return -EIO; + + return aim_attr->show(aim_obj, aim_attr, buf); +} + +/** + * aim_attr_store - store function of an AIM object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + * @len: length of buffer + */ +static ssize_t aim_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, + size_t len) +{ + struct most_aim_attribute *aim_attr; + struct most_aim_obj *aim_obj; + + aim_attr = to_aim_attr(attr); + aim_obj = to_aim_obj(kobj); + + if (!aim_attr->store) + return -EIO; + return aim_attr->store(aim_obj, aim_attr, buf, len); +} + +static const struct sysfs_ops most_aim_sysfs_ops = { + .show = aim_attr_show, + .store = aim_attr_store, +}; + +/** + * most_aim_release - AIM release function + * @kobj: pointer to AIM's kobject + */ +static void most_aim_release(struct kobject *kobj) +{ + struct most_aim_obj *aim_obj = to_aim_obj(kobj); + + kfree(aim_obj); +} + +static ssize_t links_show(struct most_aim_obj *aim_obj, + struct most_aim_attribute *attr, + char *buf) +{ + struct most_c_obj *c; + struct most_inst_obj *i; + int offs = 0; + + list_for_each_entry(i, &instance_list, list) { + list_for_each_entry(c, &i->channel_list, list) { + if (c->aim0.ptr == aim_obj->driver || + c->aim1.ptr == aim_obj->driver) { + offs += snprintf(buf + offs, PAGE_SIZE - offs, + "%s:%s\n", + kobject_name(&i->kobj), + kobject_name(&c->kobj)); + } + } + } + + return offs; +} + +/** + * split_string - parses and changes string in the buffer buf and + * splits it into two mandatory and one optional substrings. + * + * @buf: complete string from attribute 'add_channel' + * @a: address of pointer to 1st substring (=instance name) + * @b: address of pointer to 2nd substring (=channel name) + * @c: optional address of pointer to 3rd substring (=user defined name) + * + * Examples: + * + * Input: "mdev0:ch6:my_channel\n" or + * "mdev0:ch6:my_channel" + * + * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel" + * + * Input: "mdev1:ep81\n" + * Output: *a -> "mdev1", *b -> "ep81", *c -> "" + * + * Input: "mdev1:ep81" + * Output: *a -> "mdev1", *b -> "ep81", *c == NULL + */ +static int split_string(char *buf, char **a, char **b, char **c) +{ + *a = strsep(&buf, ":"); + if (!*a) + return -EIO; + + *b = strsep(&buf, ":\n"); + if (!*b) + return -EIO; + + if (c) + *c = strsep(&buf, ":\n"); + + return 0; +} + +/** + * get_channel_by_name - get pointer to channel object + * @mdev: name of the device instance + * @mdev_ch: name of the respective channel + * + * This retrieves the pointer to a channel object. + */ +static struct +most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) +{ + struct most_c_obj *c, *tmp; + struct most_inst_obj *i, *i_tmp; + int found = 0; + + list_for_each_entry_safe(i, i_tmp, &instance_list, list) { + if (!strcmp(kobject_name(&i->kobj), mdev)) { + found++; + break; + } + } + if (unlikely(!found)) + return ERR_PTR(-EIO); + + list_for_each_entry_safe(c, tmp, &i->channel_list, list) { + if (!strcmp(kobject_name(&c->kobj), mdev_ch)) { + found++; + break; + } + } + if (unlikely(found < 2)) + return ERR_PTR(-EIO); + return c; +} + +/** + * add_link_store - store() function for add_link attribute + * @aim_obj: pointer to AIM object + * @attr: its attributes + * @buf: buffer + * @len: buffer length + * + * This parses the string given by buf and splits it into + * three substrings. Note: third substring is optional. In case a cdev + * AIM is loaded the optional 3rd substring will make up the name of + * device node in the /dev directory. If omitted, the device node will + * inherit the channel's name within sysfs. + * + * Searches for a pair of device and channel and probes the AIM + * + * Example: + * (1) echo "mdev0:ch6:my_rxchannel" >add_link + * (2) echo "mdev1:ep81" >add_link + * + * (1) would create the device node /dev/my_rxchannel + * (2) would create the device node /dev/mdev1-ep81 + */ +static ssize_t add_link_store(struct most_aim_obj *aim_obj, + struct most_aim_attribute *attr, + const char *buf, + size_t len) +{ + struct most_c_obj *c; + struct most_aim **aim_ptr; + char buffer[STRING_SIZE]; + char *mdev; + char *mdev_ch; + char *mdev_devnod; + char devnod_buf[STRING_SIZE]; + int ret; + size_t max_len = min_t(size_t, len + 1, STRING_SIZE); + + strlcpy(buffer, buf, max_len); + + ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod); + if (ret) + return ret; + + if (!mdev_devnod || *mdev_devnod == 0) { + snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, + mdev_ch); + mdev_devnod = devnod_buf; + } + + c = get_channel_by_name(mdev, mdev_ch); + if (IS_ERR(c)) + return -ENODEV; + + if (!c->aim0.ptr) + aim_ptr = &c->aim0.ptr; + else if (!c->aim1.ptr) + aim_ptr = &c->aim1.ptr; + else + return -ENOSPC; + + *aim_ptr = aim_obj->driver; + ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, + &c->cfg, &c->kobj, mdev_devnod); + if (ret) { + *aim_ptr = NULL; + return ret; + } + + return len; +} + +/** + * remove_link_store - store function for remove_link attribute + * @aim_obj: pointer to AIM object + * @attr: its attributes + * @buf: buffer + * @len: buffer length + * + * Example: + * echo "mdev0:ep81" >remove_link + */ +static ssize_t remove_link_store(struct most_aim_obj *aim_obj, + struct most_aim_attribute *attr, + const char *buf, + size_t len) +{ + struct most_c_obj *c; + char buffer[STRING_SIZE]; + char *mdev; + char *mdev_ch; + int ret; + size_t max_len = min_t(size_t, len + 1, STRING_SIZE); + + strlcpy(buffer, buf, max_len); + ret = split_string(buffer, &mdev, &mdev_ch, NULL); + if (ret) + return ret; + + c = get_channel_by_name(mdev, mdev_ch); + if (IS_ERR(c)) + return -ENODEV; + + if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) + return -EIO; + if (c->aim0.ptr == aim_obj->driver) + c->aim0.ptr = NULL; + if (c->aim1.ptr == aim_obj->driver) + c->aim1.ptr = NULL; + return len; +} + +static struct most_aim_attribute most_aim_attrs[] = { + __ATTR_RO(links), + __ATTR_WO(add_link), + __ATTR_WO(remove_link), +}; + +static struct attribute *most_aim_def_attrs[] = { + &most_aim_attrs[0].attr, + &most_aim_attrs[1].attr, + &most_aim_attrs[2].attr, + NULL, +}; + +static struct kobj_type most_aim_ktype = { + .sysfs_ops = &most_aim_sysfs_ops, + .release = most_aim_release, + .default_attrs = most_aim_def_attrs, +}; + +static struct kset *most_aim_kset; + +/** + * create_most_aim_obj - creates an AIM object + * @name: name of the AIM + * + * This creates an AIM object assigns the proper kset and registers + * it with sysfs. + * Returns a pointer to the object or NULL if something went wrong. + */ +static struct most_aim_obj *create_most_aim_obj(const char *name) +{ + struct most_aim_obj *most_aim; + int retval; + + most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL); + if (!most_aim) + return NULL; + most_aim->kobj.kset = most_aim_kset; + retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype, + NULL, "%s", name); + if (retval) { + kobject_put(&most_aim->kobj); + return NULL; + } + kobject_uevent(&most_aim->kobj, KOBJ_ADD); + return most_aim; +} + +/** + * destroy_most_aim_obj - AIM release function + * @p: pointer to AIM object + * + * This decrements the reference counter of the AIM object. If the + * reference count turns zero, its release function will be called. + */ +static void destroy_most_aim_obj(struct most_aim_obj *p) +{ + kobject_put(&p->kobj); +} + +/* ___ ___ + * ___C O R E___ + */ + +/** + * Instantiation of the MOST bus + */ +static struct bus_type most_bus = { + .name = "most", +}; + +/** + * Instantiation of the core driver + */ +static struct device_driver mostcore = { + .name = "mostcore", + .bus = &most_bus, +}; + +static inline void trash_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_c_obj *c = mbo->context; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_add(&mbo->list, &c->trash_fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); +} + +static bool hdm_mbo_ready(struct most_c_obj *c) +{ + bool empty; + + if (c->enqueue_halt) + return false; + + spin_lock_irq(&c->fifo_lock); + empty = list_empty(&c->halt_fifo); + spin_unlock_irq(&c->fifo_lock); + + return !empty; +} + +static void nq_hdm_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_c_obj *c = mbo->context; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_add_tail(&mbo->list, &c->halt_fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + wake_up_interruptible(&c->hdm_fifo_wq); +} + +static int hdm_enqueue_thread(void *data) +{ + struct most_c_obj *c = data; + struct mbo *mbo; + int ret; + typeof(c->iface->enqueue) enqueue = c->iface->enqueue; + + while (likely(!kthread_should_stop())) { + wait_event_interruptible(c->hdm_fifo_wq, + hdm_mbo_ready(c) || + kthread_should_stop()); + + mutex_lock(&c->nq_mutex); + spin_lock_irq(&c->fifo_lock); + if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) { + spin_unlock_irq(&c->fifo_lock); + mutex_unlock(&c->nq_mutex); + continue; + } + + mbo = list_pop_mbo(&c->halt_fifo); + spin_unlock_irq(&c->fifo_lock); + + if (c->cfg.direction == MOST_CH_RX) + mbo->buffer_length = c->cfg.buffer_size; + + ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo); + mutex_unlock(&c->nq_mutex); + + if (unlikely(ret)) { + pr_err("hdm enqueue failed\n"); + nq_hdm_mbo(mbo); + c->hdm_enqueue_task = NULL; + return 0; + } + } + + return 0; +} + +static int run_enqueue_thread(struct most_c_obj *c, int channel_id) +{ + struct task_struct *task = + kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d", + channel_id); + + if (IS_ERR(task)) + return PTR_ERR(task); + + c->hdm_enqueue_task = task; + return 0; +} + +/** + * arm_mbo - recycle MBO for further usage + * @mbo: buffer object + * + * This puts an MBO back to the list to have it ready for up coming + * tx transactions. + * + * In case the MBO belongs to a channel that recently has been + * poisoned, the MBO is scheduled to be trashed. + * Calls the completion handler of an attached AIM. + */ +static void arm_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_c_obj *c; + + BUG_ON((!mbo) || (!mbo->context)); + c = mbo->context; + + if (c->is_poisoned) { + trash_mbo(mbo); + return; + } + + spin_lock_irqsave(&c->fifo_lock, flags); + ++*mbo->num_buffers_ptr; + list_add_tail(&mbo->list, &c->fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + + if (c->aim0.refs && c->aim0.ptr->tx_completion) + c->aim0.ptr->tx_completion(c->iface, c->channel_id); + + if (c->aim1.refs && c->aim1.ptr->tx_completion) + c->aim1.ptr->tx_completion(c->iface, c->channel_id); +} + +/** + * arm_mbo_chain - helper function that arms an MBO chain for the HDM + * @c: pointer to interface channel + * @dir: direction of the channel + * @compl: pointer to completion function + * + * This allocates buffer objects including the containing DMA coherent + * buffer and puts them in the fifo. + * Buffers of Rx channels are put in the kthread fifo, hence immediately + * submitted to the HDM. + * + * Returns the number of allocated and enqueued MBOs. + */ +static int arm_mbo_chain(struct most_c_obj *c, int dir, + void (*compl)(struct mbo *)) +{ + unsigned int i; + int retval; + struct mbo *mbo; + u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; + + atomic_set(&c->mbo_nq_level, 0); + + for (i = 0; i < c->cfg.num_buffers; i++) { + mbo = kzalloc(sizeof(*mbo), GFP_KERNEL); + if (!mbo) { + retval = i; + goto _exit; + } + mbo->context = c; + mbo->ifp = c->iface; + mbo->hdm_channel_id = c->channel_id; + mbo->virt_address = dma_alloc_coherent(NULL, + coherent_buf_size, + &mbo->bus_address, + GFP_KERNEL); + if (!mbo->virt_address) { + pr_info("WARN: No DMA coherent buffer.\n"); + retval = i; + goto _error1; + } + mbo->complete = compl; + mbo->num_buffers_ptr = &dummy_num_buffers; + if (dir == MOST_CH_RX) { + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); + } else { + arm_mbo(mbo); + } + } + return i; + +_error1: + kfree(mbo); +_exit: + return retval; +} + +/** + * most_submit_mbo - submits an MBO to fifo + * @mbo: pointer to the MBO + */ +void most_submit_mbo(struct mbo *mbo) +{ + if (WARN_ONCE(!mbo || !mbo->context, + "bad mbo or missing channel reference\n")) + return; + + nq_hdm_mbo(mbo); +} +EXPORT_SYMBOL_GPL(most_submit_mbo); + +/** + * most_write_completion - write completion handler + * @mbo: pointer to MBO + * + * This recycles the MBO for further usage. In case the channel has been + * poisoned, the MBO is scheduled to be trashed. + */ +static void most_write_completion(struct mbo *mbo) +{ + struct most_c_obj *c; + + BUG_ON((!mbo) || (!mbo->context)); + + c = mbo->context; + if (mbo->status == MBO_E_INVAL) + pr_info("WARN: Tx MBO status: invalid\n"); + if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) + trash_mbo(mbo); + else + arm_mbo(mbo); +} + +/** + * get_channel_by_iface - get pointer to channel object + * @iface: pointer to interface instance + * @id: channel ID + * + * This retrieves a pointer to a channel of the given interface and channel ID. + */ +static struct +most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) +{ + struct most_inst_obj *i; + + if (unlikely(!iface)) { + pr_err("Bad interface\n"); + return NULL; + } + if (unlikely((id < 0) || (id >= iface->num_channels))) { + pr_err("Channel index (%d) out of range\n", id); + return NULL; + } + i = iface->priv; + if (unlikely(!i)) { + pr_err("interface is not registered\n"); + return NULL; + } + return i->channel[id]; +} + +int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) +{ + struct most_c_obj *c = get_channel_by_iface(iface, id); + unsigned long flags; + int empty; + + if (unlikely(!c)) + return -EINVAL; + + if (c->aim0.refs && c->aim1.refs && + ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || + (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) + return 0; + + spin_lock_irqsave(&c->fifo_lock, flags); + empty = list_empty(&c->fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + return !empty; +} +EXPORT_SYMBOL_GPL(channel_has_mbo); + +/** + * most_get_mbo - get pointer to an MBO of pool + * @iface: pointer to interface instance + * @id: channel ID + * + * This attempts to get a free buffer out of the channel fifo. + * Returns a pointer to MBO on success or NULL otherwise. + */ +struct mbo *most_get_mbo(struct most_interface *iface, int id, + struct most_aim *aim) +{ + struct mbo *mbo; + struct most_c_obj *c; + unsigned long flags; + int *num_buffers_ptr; + + c = get_channel_by_iface(iface, id); + if (unlikely(!c)) + return NULL; + + if (c->aim0.refs && c->aim1.refs && + ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || + (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) + return NULL; + + if (aim == c->aim0.ptr) + num_buffers_ptr = &c->aim0.num_buffers; + else if (aim == c->aim1.ptr) + num_buffers_ptr = &c->aim1.num_buffers; + else + num_buffers_ptr = &dummy_num_buffers; + + spin_lock_irqsave(&c->fifo_lock, flags); + if (list_empty(&c->fifo)) { + spin_unlock_irqrestore(&c->fifo_lock, flags); + return NULL; + } + mbo = list_pop_mbo(&c->fifo); + --*num_buffers_ptr; + spin_unlock_irqrestore(&c->fifo_lock, flags); + + mbo->num_buffers_ptr = num_buffers_ptr; + mbo->buffer_length = c->cfg.buffer_size; + return mbo; +} +EXPORT_SYMBOL_GPL(most_get_mbo); + +/** + * most_put_mbo - return buffer to pool + * @mbo: buffer object + */ +void most_put_mbo(struct mbo *mbo) +{ + struct most_c_obj *c = mbo->context; + + if (c->cfg.direction == MOST_CH_TX) { + arm_mbo(mbo); + return; + } + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); +} +EXPORT_SYMBOL_GPL(most_put_mbo); + +/** + * most_read_completion - read completion handler + * @mbo: pointer to MBO + * + * This function is called by the HDM when data has been received from the + * hardware and copied to the buffer of the MBO. + * + * In case the channel has been poisoned it puts the buffer in the trash queue. + * Otherwise, it passes the buffer to an AIM for further processing. + */ +static void most_read_completion(struct mbo *mbo) +{ + struct most_c_obj *c = mbo->context; + + if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) { + trash_mbo(mbo); + return; + } + + if (mbo->status == MBO_E_INVAL) { + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); + return; + } + + if (atomic_sub_and_test(1, &c->mbo_nq_level)) + c->is_starving = 1; + + if (c->aim0.refs && c->aim0.ptr->rx_completion && + c->aim0.ptr->rx_completion(mbo) == 0) + return; + + if (c->aim1.refs && c->aim1.ptr->rx_completion && + c->aim1.ptr->rx_completion(mbo) == 0) + return; + + most_put_mbo(mbo); +} + +/** + * most_start_channel - prepares a channel for communication + * @iface: pointer to interface instance + * @id: channel ID + * + * This prepares the channel for usage. Cross-checks whether the + * channel's been properly configured. + * + * Returns 0 on success or error code otherwise. + */ +int most_start_channel(struct most_interface *iface, int id, + struct most_aim *aim) +{ + int num_buffer; + int ret; + struct most_c_obj *c = get_channel_by_iface(iface, id); + + if (unlikely(!c)) + return -EINVAL; + + mutex_lock(&c->start_mutex); + if (c->aim0.refs + c->aim1.refs > 0) + goto out; /* already started by other aim */ + + if (!try_module_get(iface->mod)) { + pr_info("failed to acquire HDM lock\n"); + mutex_unlock(&c->start_mutex); + return -ENOLCK; + } + + c->cfg.extra_len = 0; + if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { + pr_info("channel configuration failed. Go check settings...\n"); + ret = -EINVAL; + goto error; + } + + init_waitqueue_head(&c->hdm_fifo_wq); + + if (c->cfg.direction == MOST_CH_RX) + num_buffer = arm_mbo_chain(c, c->cfg.direction, + most_read_completion); + else + num_buffer = arm_mbo_chain(c, c->cfg.direction, + most_write_completion); + if (unlikely(!num_buffer)) { + pr_info("failed to allocate memory\n"); + ret = -ENOMEM; + goto error; + } + + ret = run_enqueue_thread(c, id); + if (ret) + goto error; + + c->is_starving = 0; + c->aim0.num_buffers = c->cfg.num_buffers / 2; + c->aim1.num_buffers = c->cfg.num_buffers - c->aim0.num_buffers; + atomic_set(&c->mbo_ref, num_buffer); + +out: + if (aim == c->aim0.ptr) + c->aim0.refs++; + if (aim == c->aim1.ptr) + c->aim1.refs++; + mutex_unlock(&c->start_mutex); + return 0; + +error: + module_put(iface->mod); + mutex_unlock(&c->start_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(most_start_channel); + +/** + * most_stop_channel - stops a running channel + * @iface: pointer to interface instance + * @id: channel ID + */ +int most_stop_channel(struct most_interface *iface, int id, + struct most_aim *aim) +{ + struct most_c_obj *c; + + if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { + pr_err("Bad interface or index out of range\n"); + return -EINVAL; + } + c = get_channel_by_iface(iface, id); + if (unlikely(!c)) + return -EINVAL; + + mutex_lock(&c->start_mutex); + if (c->aim0.refs + c->aim1.refs >= 2) + goto out; + + if (c->hdm_enqueue_task) + kthread_stop(c->hdm_enqueue_task); + c->hdm_enqueue_task = NULL; + + if (iface->mod) + module_put(iface->mod); + + c->is_poisoned = true; + if (c->iface->poison_channel(c->iface, c->channel_id)) { + pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id, + c->iface->description); + mutex_unlock(&c->start_mutex); + return -EAGAIN; + } + flush_trash_fifo(c); + flush_channel_fifos(c); + +#ifdef CMPL_INTERRUPTIBLE + if (wait_for_completion_interruptible(&c->cleanup)) { + pr_info("Interrupted while clean up ch %d\n", c->channel_id); + mutex_unlock(&c->start_mutex); + return -EINTR; + } +#else + wait_for_completion(&c->cleanup); +#endif + c->is_poisoned = false; + +out: + if (aim == c->aim0.ptr) + c->aim0.refs--; + if (aim == c->aim1.ptr) + c->aim1.refs--; + mutex_unlock(&c->start_mutex); + return 0; +} +EXPORT_SYMBOL_GPL(most_stop_channel); + +/** + * most_register_aim - registers an AIM (driver) with the core + * @aim: instance of AIM to be registered + */ +int most_register_aim(struct most_aim *aim) +{ + struct most_aim_obj *aim_obj; + + if (!aim) { + pr_err("Bad driver\n"); + return -EINVAL; + } + aim_obj = create_most_aim_obj(aim->name); + if (!aim_obj) { + pr_info("failed to alloc driver object\n"); + return -ENOMEM; + } + aim_obj->driver = aim; + aim->context = aim_obj; + pr_info("registered new application interfacing module %s\n", + aim->name); + list_add_tail(&aim_obj->list, &aim_list); + return 0; +} +EXPORT_SYMBOL_GPL(most_register_aim); + +/** + * most_deregister_aim - deregisters an AIM (driver) with the core + * @aim: AIM to be removed + */ +int most_deregister_aim(struct most_aim *aim) +{ + struct most_aim_obj *aim_obj; + struct most_c_obj *c, *tmp; + struct most_inst_obj *i, *i_tmp; + + if (!aim) { + pr_err("Bad driver\n"); + return -EINVAL; + } + + aim_obj = aim->context; + if (!aim_obj) { + pr_info("driver not registered.\n"); + return -EINVAL; + } + list_for_each_entry_safe(i, i_tmp, &instance_list, list) { + list_for_each_entry_safe(c, tmp, &i->channel_list, list) { + if (c->aim0.ptr == aim || c->aim1.ptr == aim) + aim->disconnect_channel( + c->iface, c->channel_id); + if (c->aim0.ptr == aim) + c->aim0.ptr = NULL; + if (c->aim1.ptr == aim) + c->aim1.ptr = NULL; + } + } + list_del(&aim_obj->list); + destroy_most_aim_obj(aim_obj); + pr_info("deregistering application interfacing module %s\n", aim->name); + return 0; +} +EXPORT_SYMBOL_GPL(most_deregister_aim); + +/** + * most_register_interface - registers an interface with core + * @iface: pointer to the instance of the interface description. + * + * Allocates and initializes a new interface instance and all of its channels. + * Returns a pointer to kobject or an error pointer. + */ +struct kobject *most_register_interface(struct most_interface *iface) +{ + unsigned int i; + int id; + char name[STRING_SIZE]; + char channel_name[STRING_SIZE]; + struct most_c_obj *c; + struct most_inst_obj *inst; + + if (!iface || !iface->enqueue || !iface->configure || + !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { + pr_err("Bad interface or channel overflow\n"); + return ERR_PTR(-EINVAL); + } + + id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); + if (id < 0) { + pr_info("Failed to alloc mdev ID\n"); + return ERR_PTR(id); + } + snprintf(name, STRING_SIZE, "mdev%d", id); + + inst = create_most_inst_obj(name); + if (!inst) { + pr_info("Failed to allocate interface instance\n"); + ida_simple_remove(&mdev_id, id); + return ERR_PTR(-ENOMEM); + } + + iface->priv = inst; + INIT_LIST_HEAD(&inst->channel_list); + inst->iface = iface; + inst->dev_id = id; + list_add_tail(&inst->list, &instance_list); + + for (i = 0; i < iface->num_channels; i++) { + const char *name_suffix = iface->channel_vector[i].name_suffix; + + if (!name_suffix) + snprintf(channel_name, STRING_SIZE, "ch%d", i); + else + snprintf(channel_name, STRING_SIZE, "%s", name_suffix); + + /* this increments the reference count of this instance */ + c = create_most_c_obj(channel_name, &inst->kobj); + if (!c) + goto free_instance; + inst->channel[i] = c; + c->is_starving = 0; + c->iface = iface; + c->inst = inst; + c->channel_id = i; + c->keep_mbo = false; + c->enqueue_halt = false; + c->is_poisoned = false; + c->cfg.direction = 0; + c->cfg.data_type = 0; + c->cfg.num_buffers = 0; + c->cfg.buffer_size = 0; + c->cfg.subbuffer_size = 0; + c->cfg.packets_per_xact = 0; + spin_lock_init(&c->fifo_lock); + INIT_LIST_HEAD(&c->fifo); + INIT_LIST_HEAD(&c->trash_fifo); + INIT_LIST_HEAD(&c->halt_fifo); + init_completion(&c->cleanup); + atomic_set(&c->mbo_ref, 0); + mutex_init(&c->start_mutex); + mutex_init(&c->nq_mutex); + list_add_tail(&c->list, &inst->channel_list); + } + pr_info("registered new MOST device mdev%d (%s)\n", + inst->dev_id, iface->description); + return &inst->kobj; + +free_instance: + pr_info("Failed allocate channel(s)\n"); + list_del(&inst->list); + ida_simple_remove(&mdev_id, id); + destroy_most_inst_obj(inst); + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(most_register_interface); + +/** + * most_deregister_interface - deregisters an interface with core + * @iface: pointer to the interface instance description. + * + * Before removing an interface instance from the list, all running + * channels are stopped and poisoned. + */ +void most_deregister_interface(struct most_interface *iface) +{ + struct most_inst_obj *i = iface->priv; + struct most_c_obj *c; + + if (unlikely(!i)) { + pr_info("Bad Interface\n"); + return; + } + pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, + iface->description); + + list_for_each_entry(c, &i->channel_list, list) { + if (c->aim0.ptr) + c->aim0.ptr->disconnect_channel(c->iface, + c->channel_id); + if (c->aim1.ptr) + c->aim1.ptr->disconnect_channel(c->iface, + c->channel_id); + c->aim0.ptr = NULL; + c->aim1.ptr = NULL; + } + + ida_simple_remove(&mdev_id, i->dev_id); + list_del(&i->list); + destroy_most_inst_obj(i); +} +EXPORT_SYMBOL_GPL(most_deregister_interface); + +/** + * most_stop_enqueue - prevents core from enqueueing MBOs + * @iface: pointer to interface + * @id: channel id + * + * This is called by an HDM that _cannot_ attend to its duties and + * is imminent to get run over by the core. The core is not going to + * enqueue any further packets unless the flagging HDM calls + * most_resume enqueue(). + */ +void most_stop_enqueue(struct most_interface *iface, int id) +{ + struct most_c_obj *c = get_channel_by_iface(iface, id); + + if (!c) + return; + + mutex_lock(&c->nq_mutex); + c->enqueue_halt = true; + mutex_unlock(&c->nq_mutex); +} +EXPORT_SYMBOL_GPL(most_stop_enqueue); + +/** + * most_resume_enqueue - allow core to enqueue MBOs again + * @iface: pointer to interface + * @id: channel id + * + * This clears the enqueue halt flag and enqueues all MBOs currently + * sitting in the wait fifo. + */ +void most_resume_enqueue(struct most_interface *iface, int id) +{ + struct most_c_obj *c = get_channel_by_iface(iface, id); + + if (!c) + return; + + mutex_lock(&c->nq_mutex); + c->enqueue_halt = false; + mutex_unlock(&c->nq_mutex); + + wake_up_interruptible(&c->hdm_fifo_wq); +} +EXPORT_SYMBOL_GPL(most_resume_enqueue); + +static int __init most_init(void) +{ + int err; + + pr_info("init()\n"); + INIT_LIST_HEAD(&instance_list); + INIT_LIST_HEAD(&aim_list); + ida_init(&mdev_id); + + err = bus_register(&most_bus); + if (err) { + pr_info("Cannot register most bus\n"); + return err; + } + + most_class = class_create(THIS_MODULE, "most"); + if (IS_ERR(most_class)) { + pr_info("No udev support.\n"); + err = PTR_ERR(most_class); + goto exit_bus; + } + + err = driver_register(&mostcore); + if (err) { + pr_info("Cannot register core driver\n"); + goto exit_class; + } + + core_dev = device_create(most_class, NULL, 0, NULL, "mostcore"); + if (IS_ERR(core_dev)) { + err = PTR_ERR(core_dev); + goto exit_driver; + } + + most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj); + if (!most_aim_kset) { + err = -ENOMEM; + goto exit_class_container; + } + + most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj); + if (!most_inst_kset) { + err = -ENOMEM; + goto exit_driver_kset; + } + + return 0; + +exit_driver_kset: + kset_unregister(most_aim_kset); +exit_class_container: + device_destroy(most_class, 0); +exit_driver: + driver_unregister(&mostcore); +exit_class: + class_destroy(most_class); +exit_bus: + bus_unregister(&most_bus); + return err; +} + +static void __exit most_exit(void) +{ + struct most_inst_obj *i, *i_tmp; + struct most_aim_obj *d, *d_tmp; + + pr_info("exit core module\n"); + list_for_each_entry_safe(d, d_tmp, &aim_list, list) { + destroy_most_aim_obj(d); + } + + list_for_each_entry_safe(i, i_tmp, &instance_list, list) { + list_del(&i->list); + destroy_most_inst_obj(i); + } + kset_unregister(most_inst_kset); + kset_unregister(most_aim_kset); + device_destroy(most_class, 0); + driver_unregister(&mostcore); + class_destroy(most_class); + bus_unregister(&most_bus); + ida_destroy(&mdev_id); +} + +module_init(most_init); +module_exit(most_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Gromm "); +MODULE_DESCRIPTION("Core module of stacked MOST Linux driver"); diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h new file mode 100644 index 000000000000..5577e8735196 --- /dev/null +++ b/drivers/staging/most/core.h @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * most.h - Interface between MostCore, + * Hardware Dependent Module (HDM) and Application Interface Module (AIM). + * + * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG + */ + +/* + * Authors: + * Andrey Shvetsov + * Christian Gromm + * Sebastian Graf + */ + +#ifndef __MOST_CORE_H__ +#define __MOST_CORE_H__ + +#include + +struct kobject; +struct module; + +/** + * Interface type + */ +enum most_interface_type { + ITYPE_LOOPBACK = 1, + ITYPE_I2C, + ITYPE_I2S, + ITYPE_TSI, + ITYPE_HBI, + ITYPE_MEDIALB_DIM, + ITYPE_MEDIALB_DIM2, + ITYPE_USB, + ITYPE_PCIE +}; + +/** + * Channel direction. + */ +enum most_channel_direction { + MOST_CH_RX = 1 << 0, + MOST_CH_TX = 1 << 1, +}; + +/** + * Channel data type. + */ +enum most_channel_data_type { + MOST_CH_CONTROL = 1 << 0, + MOST_CH_ASYNC = 1 << 1, + MOST_CH_ISOC = 1 << 2, + MOST_CH_SYNC = 1 << 5, +}; + +enum mbo_status_flags { + /* MBO was processed successfully (data was send or received )*/ + MBO_SUCCESS = 0, + /* The MBO contains wrong or missing information. */ + MBO_E_INVAL, + /* MBO was completed as HDM Channel will be closed */ + MBO_E_CLOSE, +}; + +/** + * struct most_channel_capability - Channel capability + * @direction: Supported channel directions. + * The value is bitwise OR-combination of the values from the + * enumeration most_channel_direction. Zero is allowed value and means + * "channel may not be used". + * @data_type: Supported channel data types. + * The value is bitwise OR-combination of the values from the + * enumeration most_channel_data_type. Zero is allowed value and means + * "channel may not be used". + * @num_buffer_packet: Maximum number of buffers supported by this channel + * for packet data types (Async,Control,QoS) + * @buffer_size_packet: Maximum buffer size supported by this channel + * for packet data types (Async,Control,QoS) + * @num_buffer_streaming: Maximum number of buffers supported by this channel + * for streaming data types (Sync,AV Packetized) + * @buffer_size_streaming: Maximum buffer size supported by this channel + * for streaming data types (Sync,AV Packetized) + * @name_suffix: Optional suffix providean by an HDM that is attached to the + * regular channel name. + * + * Describes the capabilities of a MostCore channel like supported Data Types + * and directions. This information is provided by an HDM for the MostCore. + * + * The Core creates read only sysfs attribute files in + * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the + * following attributes: + * -available_directions + * -available_datatypes + * -number_of_packet_buffers + * -number_of_stream_buffers + * -size_of_packet_buffer + * -size_of_stream_buffer + * where content of each file is a string with all supported properties of this + * very channel attribute. + */ +struct most_channel_capability { + u16 direction; + u16 data_type; + u16 num_buffers_packet; + u16 buffer_size_packet; + u16 num_buffers_streaming; + u16 buffer_size_streaming; + const char *name_suffix; +}; + +/** + * struct most_channel_config - stores channel configuration + * @direction: direction of the channel + * @data_type: data type travelling over this channel + * @num_buffers: number of buffers + * @buffer_size: size of a buffer for AIM. + * Buffer size may be cutted down by HDM in a configure callback + * to match to a given interface and channel type. + * @extra_len: additional buffer space for internal HDM purposes like padding. + * May be set by HDM in a configure callback if needed. + * @subbuffer_size: size of a subbuffer + * @packets_per_xact: number of MOST frames that are packet inside one USB + * packet. This is USB specific + * + * Describes the configuration for a MostCore channel. This information is + * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a + * parameter of the "configure" function call. + */ +struct most_channel_config { + enum most_channel_direction direction; + enum most_channel_data_type data_type; + u16 num_buffers; + u16 buffer_size; + u16 extra_len; + u16 subbuffer_size; + u16 packets_per_xact; +}; + +/* + * struct mbo - MOST Buffer Object. + * @context: context for core completion handler + * @priv: private data for HDM + * + * public: documented fields that are used for the communications + * between MostCore and HDMs + * + * @list: list head for use by the mbo's current owner + * @ifp: (in) associated interface instance + * @hdm_channel_id: (in) HDM channel instance + * @virt_address: (in) kernel virtual address of the buffer + * @bus_address: (in) bus address of the buffer + * @buffer_length: (in) buffer payload length + * @processed_length: (out) processed length + * @status: (out) transfer status + * @complete: (in) completion routine + * + * The MostCore allocates and initializes the MBO. + * + * The HDM receives MBO for transfer from MostCore with the call to enqueue(). + * The HDM copies the data to- or from the buffer depending on configured + * channel direction, set "processed_length" and "status" and completes + * the transfer procedure by calling the completion routine. + * + * At the end the MostCore deallocates the MBO or recycles it for further + * transfers for the same or different HDM. + * + * Directions of usage: + * The core driver should never access any MBO fields (even if marked + * as "public") while the MBO is owned by an HDM. The ownership starts with + * the call of enqueue() and ends with the call of its complete() routine. + * + * II. + * Every HDM attached to the core driver _must_ ensure that it returns any MBO + * it owns (due to a previous call to enqueue() by the core driver) before it + * de-registers an interface or gets unloaded from the kernel. If this direction + * is violated memory leaks will occur, since the core driver does _not_ track + * MBOs it is currently not in control of. + * + */ +struct mbo { + void *context; + void *priv; + struct list_head list; + struct most_interface *ifp; + int *num_buffers_ptr; + u16 hdm_channel_id; + void *virt_address; + dma_addr_t bus_address; + u16 buffer_length; + u16 processed_length; + enum mbo_status_flags status; + void (*complete)(struct mbo *); +}; + +/** + * Interface instance description. + * + * Describes one instance of an interface like Medusa PCIe or Vantage USB. + * This structure is allocated and initialized in the HDM. MostCore may not + * modify this structure. + * + * @interface Interface type. \sa most_interface_type. + * @description PRELIMINARY. + * Unique description of the device instance from point of view of the + * interface in free text form (ASCII). + * It may be a hexadecimal presentation of the memory address for the MediaLB + * IP or USB device ID with USB properties for USB interface, etc. + * @num_channels Number of channels and size of the channel_vector. + * @channel_vector Properties of the channels. + * Array index represents channel ID by the driver. + * @configure Callback to change data type for the channel of the + * interface instance. May be zero if the instance of the interface is not + * configurable. Parameter channel_config describes direction and data + * type for the channel, configured by the higher level. The content of + * @enqueue Delivers MBO to the HDM for processing. + * After HDM completes Rx- or Tx- operation the processed MBO shall + * be returned back to the MostCore using completion routine. + * The reason to get the MBO delivered from the MostCore after the channel + * is poisoned is the re-opening of the channel by the application. + * In this case the HDM shall hold MBOs and service the channel as usual. + * The HDM must be able to hold at least one MBO for each channel. + * The callback returns a negative value on error, otherwise 0. + * @poison_channel Informs HDM about closing the channel. The HDM shall + * cancel all transfers and synchronously or asynchronously return + * all enqueued for this channel MBOs using the completion routine. + * The callback returns a negative value on error, otherwise 0. + * @request_netinfo: triggers retrieving of network info from the HDM by + * means of "Message exchange over MDP/MEP" + * The call of the function request_netinfo with the parameter on_netinfo as + * NULL prohibits use of the previously obtained function pointer. + * @priv Private field used by mostcore to store context information. + */ +struct most_interface { + struct module *mod; + enum most_interface_type interface; + const char *description; + int num_channels; + struct most_channel_capability *channel_vector; + int (*configure)(struct most_interface *iface, int channel_idx, + struct most_channel_config *channel_config); + int (*enqueue)(struct most_interface *iface, int channel_idx, + struct mbo *mbo); + int (*poison_channel)(struct most_interface *iface, int channel_idx); + void (*request_netinfo)(struct most_interface *iface, int channel_idx, + void (*on_netinfo)(struct most_interface *iface, + unsigned char link_stat, + unsigned char *mac_addr)); + void *priv; +}; + +/** + * struct most_aim - identifies MOST device driver to mostcore + * @name: Driver name + * @probe_channel: function for core to notify driver about channel connection + * @disconnect_channel: callback function to disconnect a certain channel + * @rx_completion: completion handler for received packets + * @tx_completion: completion handler for transmitted packets + * @context: context pointer to be used by mostcore + */ +struct most_aim { + const char *name; + int (*probe_channel)(struct most_interface *iface, int channel_idx, + struct most_channel_config *cfg, + struct kobject *parent, char *name); + int (*disconnect_channel)(struct most_interface *iface, + int channel_idx); + int (*rx_completion)(struct mbo *mbo); + int (*tx_completion)(struct most_interface *iface, int channel_idx); + void *context; +}; + +/** + * most_register_interface - Registers instance of the interface. + * @iface: Pointer to the interface instance description. + * + * Returns a pointer to the kobject of the generated instance. + * + * Note: HDM has to ensure that any reference held on the kobj is + * released before deregistering the interface. + */ +struct kobject *most_register_interface(struct most_interface *iface); + +/** + * Deregisters instance of the interface. + * @intf_instance Pointer to the interface instance description. + */ +void most_deregister_interface(struct most_interface *iface); +void most_submit_mbo(struct mbo *mbo); + +/** + * most_stop_enqueue - prevents core from enqueing MBOs + * @iface: pointer to interface + * @channel_idx: channel index + */ +void most_stop_enqueue(struct most_interface *iface, int channel_idx); + +/** + * most_resume_enqueue - allow core to enqueue MBOs again + * @iface: pointer to interface + * @channel_idx: channel index + * + * This clears the enqueue halt flag and enqueues all MBOs currently + * in wait fifo. + */ +void most_resume_enqueue(struct most_interface *iface, int channel_idx); +int most_register_aim(struct most_aim *aim); +int most_deregister_aim(struct most_aim *aim); +struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx, + struct most_aim *); +void most_put_mbo(struct mbo *mbo); +int channel_has_mbo(struct most_interface *iface, int channel_idx, + struct most_aim *aim); +int most_start_channel(struct most_interface *iface, int channel_idx, + struct most_aim *); +int most_stop_channel(struct most_interface *iface, int channel_idx, + struct most_aim *); + +#endif /* MOST_CORE_H_ */ diff --git a/drivers/staging/most/hdm-dim2/Makefile b/drivers/staging/most/hdm-dim2/Makefile index 6bbee879a8ea..b66492bf7674 100644 --- a/drivers/staging/most/hdm-dim2/Makefile +++ b/drivers/staging/most/hdm-dim2/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o -ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/staging/ ccflags-y += -Idrivers/staging/most/aim-network/ diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 312f4f75ef06..fedd2d06742a 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -19,7 +19,7 @@ #include #include -#include +#include "most/core.h" #include "dim2_hal.h" #include "dim2_hdm.h" #include "dim2_errors.h" diff --git a/drivers/staging/most/hdm-i2c/Makefile b/drivers/staging/most/hdm-i2c/Makefile index 03a4a59b1f9f..6ddc78aae3d9 100644 --- a/drivers/staging/most/hdm-i2c/Makefile +++ b/drivers/staging/most/hdm-i2c/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_HDM_I2C) += hdm_i2c.o -ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c index ed6793a1bc93..c73c76d0a6d5 100644 --- a/drivers/staging/most/hdm-i2c/hdm_i2c.c +++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c @@ -15,7 +15,7 @@ #include #include -#include +#include "most/core.h" enum { CH_RX, CH_TX, NUM_CHANNELS }; diff --git a/drivers/staging/most/hdm-usb/Makefile b/drivers/staging/most/hdm-usb/Makefile index 6bbacb41e94b..4fea7c2a7755 100644 --- a/drivers/staging/most/hdm-usb/Makefile +++ b/drivers/staging/most/hdm-usb/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_HDM_USB) += hdm_usb.o -ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/staging/ ccflags-y += -Idrivers/staging/most/aim-network/ diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index c01b93bb134f..f036614a1da6 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -23,7 +23,7 @@ #include #include #include -#include "mostcore.h" +#include "most/core.h" #define USB_MTU 512 #define NO_ISOCHRONOUS_URB 0 diff --git a/drivers/staging/most/mostcore/Kconfig b/drivers/staging/most/mostcore/Kconfig deleted file mode 100644 index 47172546d728..000000000000 --- a/drivers/staging/most/mostcore/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# -# MOSTCore configuration -# - -config MOSTCORE - tristate "MOST Core" - depends on HAS_DMA - - ---help--- - Say Y here if you want to enable MOST support. - This device driver needs at least an additional AIM and HDM to work. - - To compile this driver as a module, choose M here: the - module will be called mostcore. diff --git a/drivers/staging/most/mostcore/Makefile b/drivers/staging/most/mostcore/Makefile deleted file mode 100644 index a078f01cf7c2..000000000000 --- a/drivers/staging/most/mostcore/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_MOSTCORE) += mostcore.o - -mostcore-objs := core.o diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c deleted file mode 100644 index cb70e1029a93..000000000000 --- a/drivers/staging/most/mostcore/core.c +++ /dev/null @@ -1,1943 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * core.c - Implementation of core module of MOST Linux driver stack - * - * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mostcore.h" - -#define MAX_CHANNELS 64 -#define STRING_SIZE 80 - -static struct class *most_class; -static struct device *core_dev; -static struct ida mdev_id; -static int dummy_num_buffers; - -struct most_c_aim_obj { - struct most_aim *ptr; - int refs; - int num_buffers; -}; - -struct most_c_obj { - struct kobject kobj; - struct completion cleanup; - atomic_t mbo_ref; - atomic_t mbo_nq_level; - u16 channel_id; - bool is_poisoned; - struct mutex start_mutex; - struct mutex nq_mutex; /* nq thread synchronization */ - int is_starving; - struct most_interface *iface; - struct most_inst_obj *inst; - struct most_channel_config cfg; - bool keep_mbo; - bool enqueue_halt; - struct list_head fifo; - spinlock_t fifo_lock; - struct list_head halt_fifo; - struct list_head list; - struct most_c_aim_obj aim0; - struct most_c_aim_obj aim1; - struct list_head trash_fifo; - struct task_struct *hdm_enqueue_task; - wait_queue_head_t hdm_fifo_wq; -}; - -#define to_c_obj(d) container_of(d, struct most_c_obj, kobj) - -struct most_inst_obj { - int dev_id; - struct most_interface *iface; - struct list_head channel_list; - struct most_c_obj *channel[MAX_CHANNELS]; - struct kobject kobj; - struct list_head list; -}; - -static const struct { - int most_ch_data_type; - const char *name; -} ch_data_type[] = { - { MOST_CH_CONTROL, "control\n" }, - { MOST_CH_ASYNC, "async\n" }, - { MOST_CH_SYNC, "sync\n" }, - { MOST_CH_ISOC, "isoc\n"}, - { MOST_CH_ISOC, "isoc_avp\n"}, -}; - -#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) - -/** - * list_pop_mbo - retrieves the first MBO of the list and removes it - * @ptr: the list head to grab the MBO from. - */ -#define list_pop_mbo(ptr) \ -({ \ - struct mbo *_mbo = list_first_entry(ptr, struct mbo, list); \ - list_del(&_mbo->list); \ - _mbo; \ -}) - -/* ___ ___ - * ___C H A N N E L___ - */ - -/** - * struct most_c_attr - to access the attributes of a channel object - * @attr: attributes of a channel - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_c_attr { - struct attribute attr; - ssize_t (*show)(struct most_c_obj *d, - struct most_c_attr *attr, - char *buf); - ssize_t (*store)(struct most_c_obj *d, - struct most_c_attr *attr, - const char *buf, - size_t count); -}; - -#define to_channel_attr(a) container_of(a, struct most_c_attr, attr) - -/** - * channel_attr_show - show function of channel object - * @kobj: pointer to its kobject - * @attr: pointer to its attributes - * @buf: buffer - */ -static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct most_c_attr *channel_attr = to_channel_attr(attr); - struct most_c_obj *c_obj = to_c_obj(kobj); - - if (!channel_attr->show) - return -EIO; - - return channel_attr->show(c_obj, channel_attr, buf); -} - -/** - * channel_attr_store - store function of channel object - * @kobj: pointer to its kobject - * @attr: pointer to its attributes - * @buf: buffer - * @len: length of buffer - */ -static ssize_t channel_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_c_attr *channel_attr = to_channel_attr(attr); - struct most_c_obj *c_obj = to_c_obj(kobj); - - if (!channel_attr->store) - return -EIO; - return channel_attr->store(c_obj, channel_attr, buf, len); -} - -static const struct sysfs_ops most_channel_sysfs_ops = { - .show = channel_attr_show, - .store = channel_attr_store, -}; - -/** - * most_free_mbo_coherent - free an MBO and its coherent buffer - * @mbo: buffer to be released - * - */ -static void most_free_mbo_coherent(struct mbo *mbo) -{ - struct most_c_obj *c = mbo->context; - u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; - - dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address, - mbo->bus_address); - kfree(mbo); - if (atomic_sub_and_test(1, &c->mbo_ref)) - complete(&c->cleanup); -} - -/** - * flush_channel_fifos - clear the channel fifos - * @c: pointer to channel object - */ -static void flush_channel_fifos(struct most_c_obj *c) -{ - unsigned long flags, hf_flags; - struct mbo *mbo, *tmp; - - if (list_empty(&c->fifo) && list_empty(&c->halt_fifo)) - return; - - spin_lock_irqsave(&c->fifo_lock, flags); - list_for_each_entry_safe(mbo, tmp, &c->fifo, list) { - list_del(&mbo->list); - spin_unlock_irqrestore(&c->fifo_lock, flags); - most_free_mbo_coherent(mbo); - spin_lock_irqsave(&c->fifo_lock, flags); - } - spin_unlock_irqrestore(&c->fifo_lock, flags); - - spin_lock_irqsave(&c->fifo_lock, hf_flags); - list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) { - list_del(&mbo->list); - spin_unlock_irqrestore(&c->fifo_lock, hf_flags); - most_free_mbo_coherent(mbo); - spin_lock_irqsave(&c->fifo_lock, hf_flags); - } - spin_unlock_irqrestore(&c->fifo_lock, hf_flags); - - if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo)))) - pr_info("WARN: fifo | trash fifo not empty\n"); -} - -/** - * flush_trash_fifo - clear the trash fifo - * @c: pointer to channel object - */ -static int flush_trash_fifo(struct most_c_obj *c) -{ - struct mbo *mbo, *tmp; - unsigned long flags; - - spin_lock_irqsave(&c->fifo_lock, flags); - list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) { - list_del(&mbo->list); - spin_unlock_irqrestore(&c->fifo_lock, flags); - most_free_mbo_coherent(mbo); - spin_lock_irqsave(&c->fifo_lock, flags); - } - spin_unlock_irqrestore(&c->fifo_lock, flags); - return 0; -} - -/** - * most_channel_release - release function of channel object - * @kobj: pointer to channel's kobject - */ -static void most_channel_release(struct kobject *kobj) -{ - struct most_c_obj *c = to_c_obj(kobj); - - kfree(c); -} - -static ssize_t available_directions_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - strcpy(buf, ""); - if (c->iface->channel_vector[i].direction & MOST_CH_RX) - strcat(buf, "rx "); - if (c->iface->channel_vector[i].direction & MOST_CH_TX) - strcat(buf, "tx "); - strcat(buf, "\n"); - return strlen(buf); -} - -static ssize_t available_datatypes_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - strcpy(buf, ""); - if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL) - strcat(buf, "control "); - if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC) - strcat(buf, "async "); - if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC) - strcat(buf, "sync "); - if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC) - strcat(buf, "isoc "); - strcat(buf, "\n"); - return strlen(buf); -} - -static ssize_t number_of_packet_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - return snprintf(buf, PAGE_SIZE, "%d\n", - c->iface->channel_vector[i].num_buffers_packet); -} - -static ssize_t number_of_stream_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - return snprintf(buf, PAGE_SIZE, "%d\n", - c->iface->channel_vector[i].num_buffers_streaming); -} - -static ssize_t size_of_packet_buffer_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - return snprintf(buf, PAGE_SIZE, "%d\n", - c->iface->channel_vector[i].buffer_size_packet); -} - -static ssize_t size_of_stream_buffer_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - unsigned int i = c->channel_id; - - return snprintf(buf, PAGE_SIZE, "%d\n", - c->iface->channel_vector[i].buffer_size_streaming); -} - -static ssize_t channel_starving_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); -} - -static ssize_t set_number_of_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); -} - -static ssize_t set_number_of_buffers_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); - - if (ret) - return ret; - return count; -} - -static ssize_t set_buffer_size_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); -} - -static ssize_t set_buffer_size_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); - - if (ret) - return ret; - return count; -} - -static ssize_t set_direction_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - if (c->cfg.direction & MOST_CH_TX) - return snprintf(buf, PAGE_SIZE, "tx\n"); - else if (c->cfg.direction & MOST_CH_RX) - return snprintf(buf, PAGE_SIZE, "rx\n"); - return snprintf(buf, PAGE_SIZE, "unconfigured\n"); -} - -static ssize_t set_direction_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - if (!strcmp(buf, "dir_rx\n")) { - c->cfg.direction = MOST_CH_RX; - } else if (!strcmp(buf, "rx\n")) { - c->cfg.direction = MOST_CH_RX; - } else if (!strcmp(buf, "dir_tx\n")) { - c->cfg.direction = MOST_CH_TX; - } else if (!strcmp(buf, "tx\n")) { - c->cfg.direction = MOST_CH_TX; - } else { - pr_info("WARN: invalid attribute settings\n"); - return -EINVAL; - } - return count; -} - -static ssize_t set_datatype_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { - if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) - return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); - } - return snprintf(buf, PAGE_SIZE, "unconfigured\n"); -} - -static ssize_t set_datatype_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { - if (!strcmp(buf, ch_data_type[i].name)) { - c->cfg.data_type = ch_data_type[i].most_ch_data_type; - break; - } - } - - if (i == ARRAY_SIZE(ch_data_type)) { - pr_info("WARN: invalid attribute settings\n"); - return -EINVAL; - } - return count; -} - -static ssize_t set_subbuffer_size_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); -} - -static ssize_t set_subbuffer_size_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); - - if (ret) - return ret; - return count; -} - -static ssize_t set_packets_per_xact_show(struct most_c_obj *c, - struct most_c_attr *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); -} - -static ssize_t set_packets_per_xact_store(struct most_c_obj *c, - struct most_c_attr *attr, - const char *buf, - size_t count) -{ - int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); - - if (ret) - return ret; - return count; -} - -static struct most_c_attr most_c_attrs[] = { - __ATTR_RO(available_directions), - __ATTR_RO(available_datatypes), - __ATTR_RO(number_of_packet_buffers), - __ATTR_RO(number_of_stream_buffers), - __ATTR_RO(size_of_stream_buffer), - __ATTR_RO(size_of_packet_buffer), - __ATTR_RO(channel_starving), - __ATTR_RW(set_buffer_size), - __ATTR_RW(set_number_of_buffers), - __ATTR_RW(set_direction), - __ATTR_RW(set_datatype), - __ATTR_RW(set_subbuffer_size), - __ATTR_RW(set_packets_per_xact), -}; - -/** - * most_channel_def_attrs - array of default attributes of channel object - */ -static struct attribute *most_channel_def_attrs[] = { - &most_c_attrs[0].attr, - &most_c_attrs[1].attr, - &most_c_attrs[2].attr, - &most_c_attrs[3].attr, - &most_c_attrs[4].attr, - &most_c_attrs[5].attr, - &most_c_attrs[6].attr, - &most_c_attrs[7].attr, - &most_c_attrs[8].attr, - &most_c_attrs[9].attr, - &most_c_attrs[10].attr, - &most_c_attrs[11].attr, - &most_c_attrs[12].attr, - NULL, -}; - -static struct kobj_type most_channel_ktype = { - .sysfs_ops = &most_channel_sysfs_ops, - .release = most_channel_release, - .default_attrs = most_channel_def_attrs, -}; - -static struct kset *most_channel_kset; - -/** - * create_most_c_obj - allocates a channel object - * @name: name of the channel object - * @parent: parent kobject - * - * This create a channel object and registers it with sysfs. - * Returns a pointer to the object or NULL when something went wrong. - */ -static struct most_c_obj * -create_most_c_obj(const char *name, struct kobject *parent) -{ - struct most_c_obj *c; - int retval; - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) - return NULL; - c->kobj.kset = most_channel_kset; - retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent, - "%s", name); - if (retval) { - kobject_put(&c->kobj); - return NULL; - } - kobject_uevent(&c->kobj, KOBJ_ADD); - return c; -} - -/* ___ ___ - * ___I N S T A N C E___ - */ - -static struct list_head instance_list; - -/** - * struct most_inst_attribute - to access the attributes of instance object - * @attr: attributes of an instance - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_inst_attribute { - struct attribute attr; - ssize_t (*show)(struct most_inst_obj *d, - struct most_inst_attribute *attr, - char *buf); - ssize_t (*store)(struct most_inst_obj *d, - struct most_inst_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_instance_attr(a) \ - container_of(a, struct most_inst_attribute, attr) - -/** - * instance_attr_show - show function for an instance object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t instance_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct most_inst_attribute *instance_attr; - struct most_inst_obj *instance_obj; - - instance_attr = to_instance_attr(attr); - instance_obj = to_inst_obj(kobj); - - if (!instance_attr->show) - return -EIO; - - return instance_attr->show(instance_obj, instance_attr, buf); -} - -/** - * instance_attr_store - store function for an instance object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t instance_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_inst_attribute *instance_attr; - struct most_inst_obj *instance_obj; - - instance_attr = to_instance_attr(attr); - instance_obj = to_inst_obj(kobj); - - if (!instance_attr->store) - return -EIO; - - return instance_attr->store(instance_obj, instance_attr, buf, len); -} - -static const struct sysfs_ops most_inst_sysfs_ops = { - .show = instance_attr_show, - .store = instance_attr_store, -}; - -/** - * most_inst_release - release function for instance object - * @kobj: pointer to instance's kobject - * - * This frees the allocated memory for the instance object - */ -static void most_inst_release(struct kobject *kobj) -{ - struct most_inst_obj *inst = to_inst_obj(kobj); - - kfree(inst); -} - -static ssize_t description_show(struct most_inst_obj *instance_obj, - struct most_inst_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", - instance_obj->iface->description); -} - -static ssize_t interface_show(struct most_inst_obj *instance_obj, - struct most_inst_attribute *attr, - char *buf) -{ - switch (instance_obj->iface->interface) { - case ITYPE_LOOPBACK: - return snprintf(buf, PAGE_SIZE, "loopback\n"); - case ITYPE_I2C: - return snprintf(buf, PAGE_SIZE, "i2c\n"); - case ITYPE_I2S: - return snprintf(buf, PAGE_SIZE, "i2s\n"); - case ITYPE_TSI: - return snprintf(buf, PAGE_SIZE, "tsi\n"); - case ITYPE_HBI: - return snprintf(buf, PAGE_SIZE, "hbi\n"); - case ITYPE_MEDIALB_DIM: - return snprintf(buf, PAGE_SIZE, "mlb_dim\n"); - case ITYPE_MEDIALB_DIM2: - return snprintf(buf, PAGE_SIZE, "mlb_dim2\n"); - case ITYPE_USB: - return snprintf(buf, PAGE_SIZE, "usb\n"); - case ITYPE_PCIE: - return snprintf(buf, PAGE_SIZE, "pcie\n"); - } - return snprintf(buf, PAGE_SIZE, "unknown\n"); -} - -static struct most_inst_attribute most_inst_attr_description = - __ATTR_RO(description); - -static struct most_inst_attribute most_inst_attr_interface = - __ATTR_RO(interface); - -static struct attribute *most_inst_def_attrs[] = { - &most_inst_attr_description.attr, - &most_inst_attr_interface.attr, - NULL, -}; - -static struct kobj_type most_inst_ktype = { - .sysfs_ops = &most_inst_sysfs_ops, - .release = most_inst_release, - .default_attrs = most_inst_def_attrs, -}; - -static struct kset *most_inst_kset; - -/** - * create_most_inst_obj - creates an instance object - * @name: name of the object to be created - * - * This allocates memory for an instance structure, assigns the proper kset - * and registers it with sysfs. - * - * Returns a pointer to the instance object or NULL when something went wrong. - */ -static struct most_inst_obj *create_most_inst_obj(const char *name) -{ - struct most_inst_obj *inst; - int retval; - - inst = kzalloc(sizeof(*inst), GFP_KERNEL); - if (!inst) - return NULL; - inst->kobj.kset = most_inst_kset; - retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL, - "%s", name); - if (retval) { - kobject_put(&inst->kobj); - return NULL; - } - kobject_uevent(&inst->kobj, KOBJ_ADD); - return inst; -} - -/** - * destroy_most_inst_obj - MOST instance release function - * @inst: pointer to the instance object - * - * This decrements the reference counter of the instance object. - * If the reference count turns zero, its release function is called - */ -static void destroy_most_inst_obj(struct most_inst_obj *inst) -{ - struct most_c_obj *c, *tmp; - - list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - flush_trash_fifo(c); - flush_channel_fifos(c); - kobject_put(&c->kobj); - } - kobject_put(&inst->kobj); -} - -/* ___ ___ - * ___A I M___ - */ -struct most_aim_obj { - struct kobject kobj; - struct list_head list; - struct most_aim *driver; -}; - -#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj) - -static struct list_head aim_list; - -/** - * struct most_aim_attribute - to access the attributes of AIM object - * @attr: attributes of an AIM - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_aim_attribute { - struct attribute attr; - ssize_t (*show)(struct most_aim_obj *d, - struct most_aim_attribute *attr, - char *buf); - ssize_t (*store)(struct most_aim_obj *d, - struct most_aim_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr) - -/** - * aim_attr_show - show function of an AIM object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t aim_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct most_aim_attribute *aim_attr; - struct most_aim_obj *aim_obj; - - aim_attr = to_aim_attr(attr); - aim_obj = to_aim_obj(kobj); - - if (!aim_attr->show) - return -EIO; - - return aim_attr->show(aim_obj, aim_attr, buf); -} - -/** - * aim_attr_store - store function of an AIM object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t aim_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_aim_attribute *aim_attr; - struct most_aim_obj *aim_obj; - - aim_attr = to_aim_attr(attr); - aim_obj = to_aim_obj(kobj); - - if (!aim_attr->store) - return -EIO; - return aim_attr->store(aim_obj, aim_attr, buf, len); -} - -static const struct sysfs_ops most_aim_sysfs_ops = { - .show = aim_attr_show, - .store = aim_attr_store, -}; - -/** - * most_aim_release - AIM release function - * @kobj: pointer to AIM's kobject - */ -static void most_aim_release(struct kobject *kobj) -{ - struct most_aim_obj *aim_obj = to_aim_obj(kobj); - - kfree(aim_obj); -} - -static ssize_t links_show(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, - char *buf) -{ - struct most_c_obj *c; - struct most_inst_obj *i; - int offs = 0; - - list_for_each_entry(i, &instance_list, list) { - list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.ptr == aim_obj->driver || - c->aim1.ptr == aim_obj->driver) { - offs += snprintf(buf + offs, PAGE_SIZE - offs, - "%s:%s\n", - kobject_name(&i->kobj), - kobject_name(&c->kobj)); - } - } - } - - return offs; -} - -/** - * split_string - parses and changes string in the buffer buf and - * splits it into two mandatory and one optional substrings. - * - * @buf: complete string from attribute 'add_channel' - * @a: address of pointer to 1st substring (=instance name) - * @b: address of pointer to 2nd substring (=channel name) - * @c: optional address of pointer to 3rd substring (=user defined name) - * - * Examples: - * - * Input: "mdev0:ch6:my_channel\n" or - * "mdev0:ch6:my_channel" - * - * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel" - * - * Input: "mdev1:ep81\n" - * Output: *a -> "mdev1", *b -> "ep81", *c -> "" - * - * Input: "mdev1:ep81" - * Output: *a -> "mdev1", *b -> "ep81", *c == NULL - */ -static int split_string(char *buf, char **a, char **b, char **c) -{ - *a = strsep(&buf, ":"); - if (!*a) - return -EIO; - - *b = strsep(&buf, ":\n"); - if (!*b) - return -EIO; - - if (c) - *c = strsep(&buf, ":\n"); - - return 0; -} - -/** - * get_channel_by_name - get pointer to channel object - * @mdev: name of the device instance - * @mdev_ch: name of the respective channel - * - * This retrieves the pointer to a channel object. - */ -static struct -most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) -{ - struct most_c_obj *c, *tmp; - struct most_inst_obj *i, *i_tmp; - int found = 0; - - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - if (!strcmp(kobject_name(&i->kobj), mdev)) { - found++; - break; - } - } - if (unlikely(!found)) - return ERR_PTR(-EIO); - - list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (!strcmp(kobject_name(&c->kobj), mdev_ch)) { - found++; - break; - } - } - if (unlikely(found < 2)) - return ERR_PTR(-EIO); - return c; -} - -/** - * add_link_store - store() function for add_link attribute - * @aim_obj: pointer to AIM object - * @attr: its attributes - * @buf: buffer - * @len: buffer length - * - * This parses the string given by buf and splits it into - * three substrings. Note: third substring is optional. In case a cdev - * AIM is loaded the optional 3rd substring will make up the name of - * device node in the /dev directory. If omitted, the device node will - * inherit the channel's name within sysfs. - * - * Searches for a pair of device and channel and probes the AIM - * - * Example: - * (1) echo "mdev0:ch6:my_rxchannel" >add_link - * (2) echo "mdev1:ep81" >add_link - * - * (1) would create the device node /dev/my_rxchannel - * (2) would create the device node /dev/mdev1-ep81 - */ -static ssize_t add_link_store(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, - const char *buf, - size_t len) -{ - struct most_c_obj *c; - struct most_aim **aim_ptr; - char buffer[STRING_SIZE]; - char *mdev; - char *mdev_ch; - char *mdev_devnod; - char devnod_buf[STRING_SIZE]; - int ret; - size_t max_len = min_t(size_t, len + 1, STRING_SIZE); - - strlcpy(buffer, buf, max_len); - - ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod); - if (ret) - return ret; - - if (!mdev_devnod || *mdev_devnod == 0) { - snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, - mdev_ch); - mdev_devnod = devnod_buf; - } - - c = get_channel_by_name(mdev, mdev_ch); - if (IS_ERR(c)) - return -ENODEV; - - if (!c->aim0.ptr) - aim_ptr = &c->aim0.ptr; - else if (!c->aim1.ptr) - aim_ptr = &c->aim1.ptr; - else - return -ENOSPC; - - *aim_ptr = aim_obj->driver; - ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, - &c->cfg, &c->kobj, mdev_devnod); - if (ret) { - *aim_ptr = NULL; - return ret; - } - - return len; -} - -/** - * remove_link_store - store function for remove_link attribute - * @aim_obj: pointer to AIM object - * @attr: its attributes - * @buf: buffer - * @len: buffer length - * - * Example: - * echo "mdev0:ep81" >remove_link - */ -static ssize_t remove_link_store(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, - const char *buf, - size_t len) -{ - struct most_c_obj *c; - char buffer[STRING_SIZE]; - char *mdev; - char *mdev_ch; - int ret; - size_t max_len = min_t(size_t, len + 1, STRING_SIZE); - - strlcpy(buffer, buf, max_len); - ret = split_string(buffer, &mdev, &mdev_ch, NULL); - if (ret) - return ret; - - c = get_channel_by_name(mdev, mdev_ch); - if (IS_ERR(c)) - return -ENODEV; - - if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) - return -EIO; - if (c->aim0.ptr == aim_obj->driver) - c->aim0.ptr = NULL; - if (c->aim1.ptr == aim_obj->driver) - c->aim1.ptr = NULL; - return len; -} - -static struct most_aim_attribute most_aim_attrs[] = { - __ATTR_RO(links), - __ATTR_WO(add_link), - __ATTR_WO(remove_link), -}; - -static struct attribute *most_aim_def_attrs[] = { - &most_aim_attrs[0].attr, - &most_aim_attrs[1].attr, - &most_aim_attrs[2].attr, - NULL, -}; - -static struct kobj_type most_aim_ktype = { - .sysfs_ops = &most_aim_sysfs_ops, - .release = most_aim_release, - .default_attrs = most_aim_def_attrs, -}; - -static struct kset *most_aim_kset; - -/** - * create_most_aim_obj - creates an AIM object - * @name: name of the AIM - * - * This creates an AIM object assigns the proper kset and registers - * it with sysfs. - * Returns a pointer to the object or NULL if something went wrong. - */ -static struct most_aim_obj *create_most_aim_obj(const char *name) -{ - struct most_aim_obj *most_aim; - int retval; - - most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL); - if (!most_aim) - return NULL; - most_aim->kobj.kset = most_aim_kset; - retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype, - NULL, "%s", name); - if (retval) { - kobject_put(&most_aim->kobj); - return NULL; - } - kobject_uevent(&most_aim->kobj, KOBJ_ADD); - return most_aim; -} - -/** - * destroy_most_aim_obj - AIM release function - * @p: pointer to AIM object - * - * This decrements the reference counter of the AIM object. If the - * reference count turns zero, its release function will be called. - */ -static void destroy_most_aim_obj(struct most_aim_obj *p) -{ - kobject_put(&p->kobj); -} - -/* ___ ___ - * ___C O R E___ - */ - -/** - * Instantiation of the MOST bus - */ -static struct bus_type most_bus = { - .name = "most", -}; - -/** - * Instantiation of the core driver - */ -static struct device_driver mostcore = { - .name = "mostcore", - .bus = &most_bus, -}; - -static inline void trash_mbo(struct mbo *mbo) -{ - unsigned long flags; - struct most_c_obj *c = mbo->context; - - spin_lock_irqsave(&c->fifo_lock, flags); - list_add(&mbo->list, &c->trash_fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); -} - -static bool hdm_mbo_ready(struct most_c_obj *c) -{ - bool empty; - - if (c->enqueue_halt) - return false; - - spin_lock_irq(&c->fifo_lock); - empty = list_empty(&c->halt_fifo); - spin_unlock_irq(&c->fifo_lock); - - return !empty; -} - -static void nq_hdm_mbo(struct mbo *mbo) -{ - unsigned long flags; - struct most_c_obj *c = mbo->context; - - spin_lock_irqsave(&c->fifo_lock, flags); - list_add_tail(&mbo->list, &c->halt_fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); - wake_up_interruptible(&c->hdm_fifo_wq); -} - -static int hdm_enqueue_thread(void *data) -{ - struct most_c_obj *c = data; - struct mbo *mbo; - int ret; - typeof(c->iface->enqueue) enqueue = c->iface->enqueue; - - while (likely(!kthread_should_stop())) { - wait_event_interruptible(c->hdm_fifo_wq, - hdm_mbo_ready(c) || - kthread_should_stop()); - - mutex_lock(&c->nq_mutex); - spin_lock_irq(&c->fifo_lock); - if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) { - spin_unlock_irq(&c->fifo_lock); - mutex_unlock(&c->nq_mutex); - continue; - } - - mbo = list_pop_mbo(&c->halt_fifo); - spin_unlock_irq(&c->fifo_lock); - - if (c->cfg.direction == MOST_CH_RX) - mbo->buffer_length = c->cfg.buffer_size; - - ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo); - mutex_unlock(&c->nq_mutex); - - if (unlikely(ret)) { - pr_err("hdm enqueue failed\n"); - nq_hdm_mbo(mbo); - c->hdm_enqueue_task = NULL; - return 0; - } - } - - return 0; -} - -static int run_enqueue_thread(struct most_c_obj *c, int channel_id) -{ - struct task_struct *task = - kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d", - channel_id); - - if (IS_ERR(task)) - return PTR_ERR(task); - - c->hdm_enqueue_task = task; - return 0; -} - -/** - * arm_mbo - recycle MBO for further usage - * @mbo: buffer object - * - * This puts an MBO back to the list to have it ready for up coming - * tx transactions. - * - * In case the MBO belongs to a channel that recently has been - * poisoned, the MBO is scheduled to be trashed. - * Calls the completion handler of an attached AIM. - */ -static void arm_mbo(struct mbo *mbo) -{ - unsigned long flags; - struct most_c_obj *c; - - BUG_ON((!mbo) || (!mbo->context)); - c = mbo->context; - - if (c->is_poisoned) { - trash_mbo(mbo); - return; - } - - spin_lock_irqsave(&c->fifo_lock, flags); - ++*mbo->num_buffers_ptr; - list_add_tail(&mbo->list, &c->fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); - - if (c->aim0.refs && c->aim0.ptr->tx_completion) - c->aim0.ptr->tx_completion(c->iface, c->channel_id); - - if (c->aim1.refs && c->aim1.ptr->tx_completion) - c->aim1.ptr->tx_completion(c->iface, c->channel_id); -} - -/** - * arm_mbo_chain - helper function that arms an MBO chain for the HDM - * @c: pointer to interface channel - * @dir: direction of the channel - * @compl: pointer to completion function - * - * This allocates buffer objects including the containing DMA coherent - * buffer and puts them in the fifo. - * Buffers of Rx channels are put in the kthread fifo, hence immediately - * submitted to the HDM. - * - * Returns the number of allocated and enqueued MBOs. - */ -static int arm_mbo_chain(struct most_c_obj *c, int dir, - void (*compl)(struct mbo *)) -{ - unsigned int i; - int retval; - struct mbo *mbo; - u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; - - atomic_set(&c->mbo_nq_level, 0); - - for (i = 0; i < c->cfg.num_buffers; i++) { - mbo = kzalloc(sizeof(*mbo), GFP_KERNEL); - if (!mbo) { - retval = i; - goto _exit; - } - mbo->context = c; - mbo->ifp = c->iface; - mbo->hdm_channel_id = c->channel_id; - mbo->virt_address = dma_alloc_coherent(NULL, - coherent_buf_size, - &mbo->bus_address, - GFP_KERNEL); - if (!mbo->virt_address) { - pr_info("WARN: No DMA coherent buffer.\n"); - retval = i; - goto _error1; - } - mbo->complete = compl; - mbo->num_buffers_ptr = &dummy_num_buffers; - if (dir == MOST_CH_RX) { - nq_hdm_mbo(mbo); - atomic_inc(&c->mbo_nq_level); - } else { - arm_mbo(mbo); - } - } - return i; - -_error1: - kfree(mbo); -_exit: - return retval; -} - -/** - * most_submit_mbo - submits an MBO to fifo - * @mbo: pointer to the MBO - */ -void most_submit_mbo(struct mbo *mbo) -{ - if (WARN_ONCE(!mbo || !mbo->context, - "bad mbo or missing channel reference\n")) - return; - - nq_hdm_mbo(mbo); -} -EXPORT_SYMBOL_GPL(most_submit_mbo); - -/** - * most_write_completion - write completion handler - * @mbo: pointer to MBO - * - * This recycles the MBO for further usage. In case the channel has been - * poisoned, the MBO is scheduled to be trashed. - */ -static void most_write_completion(struct mbo *mbo) -{ - struct most_c_obj *c; - - BUG_ON((!mbo) || (!mbo->context)); - - c = mbo->context; - if (mbo->status == MBO_E_INVAL) - pr_info("WARN: Tx MBO status: invalid\n"); - if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) - trash_mbo(mbo); - else - arm_mbo(mbo); -} - -/** - * get_channel_by_iface - get pointer to channel object - * @iface: pointer to interface instance - * @id: channel ID - * - * This retrieves a pointer to a channel of the given interface and channel ID. - */ -static struct -most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) -{ - struct most_inst_obj *i; - - if (unlikely(!iface)) { - pr_err("Bad interface\n"); - return NULL; - } - if (unlikely((id < 0) || (id >= iface->num_channels))) { - pr_err("Channel index (%d) out of range\n", id); - return NULL; - } - i = iface->priv; - if (unlikely(!i)) { - pr_err("interface is not registered\n"); - return NULL; - } - return i->channel[id]; -} - -int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) -{ - struct most_c_obj *c = get_channel_by_iface(iface, id); - unsigned long flags; - int empty; - - if (unlikely(!c)) - return -EINVAL; - - if (c->aim0.refs && c->aim1.refs && - ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || - (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) - return 0; - - spin_lock_irqsave(&c->fifo_lock, flags); - empty = list_empty(&c->fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); - return !empty; -} -EXPORT_SYMBOL_GPL(channel_has_mbo); - -/** - * most_get_mbo - get pointer to an MBO of pool - * @iface: pointer to interface instance - * @id: channel ID - * - * This attempts to get a free buffer out of the channel fifo. - * Returns a pointer to MBO on success or NULL otherwise. - */ -struct mbo *most_get_mbo(struct most_interface *iface, int id, - struct most_aim *aim) -{ - struct mbo *mbo; - struct most_c_obj *c; - unsigned long flags; - int *num_buffers_ptr; - - c = get_channel_by_iface(iface, id); - if (unlikely(!c)) - return NULL; - - if (c->aim0.refs && c->aim1.refs && - ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || - (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) - return NULL; - - if (aim == c->aim0.ptr) - num_buffers_ptr = &c->aim0.num_buffers; - else if (aim == c->aim1.ptr) - num_buffers_ptr = &c->aim1.num_buffers; - else - num_buffers_ptr = &dummy_num_buffers; - - spin_lock_irqsave(&c->fifo_lock, flags); - if (list_empty(&c->fifo)) { - spin_unlock_irqrestore(&c->fifo_lock, flags); - return NULL; - } - mbo = list_pop_mbo(&c->fifo); - --*num_buffers_ptr; - spin_unlock_irqrestore(&c->fifo_lock, flags); - - mbo->num_buffers_ptr = num_buffers_ptr; - mbo->buffer_length = c->cfg.buffer_size; - return mbo; -} -EXPORT_SYMBOL_GPL(most_get_mbo); - -/** - * most_put_mbo - return buffer to pool - * @mbo: buffer object - */ -void most_put_mbo(struct mbo *mbo) -{ - struct most_c_obj *c = mbo->context; - - if (c->cfg.direction == MOST_CH_TX) { - arm_mbo(mbo); - return; - } - nq_hdm_mbo(mbo); - atomic_inc(&c->mbo_nq_level); -} -EXPORT_SYMBOL_GPL(most_put_mbo); - -/** - * most_read_completion - read completion handler - * @mbo: pointer to MBO - * - * This function is called by the HDM when data has been received from the - * hardware and copied to the buffer of the MBO. - * - * In case the channel has been poisoned it puts the buffer in the trash queue. - * Otherwise, it passes the buffer to an AIM for further processing. - */ -static void most_read_completion(struct mbo *mbo) -{ - struct most_c_obj *c = mbo->context; - - if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) { - trash_mbo(mbo); - return; - } - - if (mbo->status == MBO_E_INVAL) { - nq_hdm_mbo(mbo); - atomic_inc(&c->mbo_nq_level); - return; - } - - if (atomic_sub_and_test(1, &c->mbo_nq_level)) - c->is_starving = 1; - - if (c->aim0.refs && c->aim0.ptr->rx_completion && - c->aim0.ptr->rx_completion(mbo) == 0) - return; - - if (c->aim1.refs && c->aim1.ptr->rx_completion && - c->aim1.ptr->rx_completion(mbo) == 0) - return; - - most_put_mbo(mbo); -} - -/** - * most_start_channel - prepares a channel for communication - * @iface: pointer to interface instance - * @id: channel ID - * - * This prepares the channel for usage. Cross-checks whether the - * channel's been properly configured. - * - * Returns 0 on success or error code otherwise. - */ -int most_start_channel(struct most_interface *iface, int id, - struct most_aim *aim) -{ - int num_buffer; - int ret; - struct most_c_obj *c = get_channel_by_iface(iface, id); - - if (unlikely(!c)) - return -EINVAL; - - mutex_lock(&c->start_mutex); - if (c->aim0.refs + c->aim1.refs > 0) - goto out; /* already started by other aim */ - - if (!try_module_get(iface->mod)) { - pr_info("failed to acquire HDM lock\n"); - mutex_unlock(&c->start_mutex); - return -ENOLCK; - } - - c->cfg.extra_len = 0; - if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { - pr_info("channel configuration failed. Go check settings...\n"); - ret = -EINVAL; - goto error; - } - - init_waitqueue_head(&c->hdm_fifo_wq); - - if (c->cfg.direction == MOST_CH_RX) - num_buffer = arm_mbo_chain(c, c->cfg.direction, - most_read_completion); - else - num_buffer = arm_mbo_chain(c, c->cfg.direction, - most_write_completion); - if (unlikely(!num_buffer)) { - pr_info("failed to allocate memory\n"); - ret = -ENOMEM; - goto error; - } - - ret = run_enqueue_thread(c, id); - if (ret) - goto error; - - c->is_starving = 0; - c->aim0.num_buffers = c->cfg.num_buffers / 2; - c->aim1.num_buffers = c->cfg.num_buffers - c->aim0.num_buffers; - atomic_set(&c->mbo_ref, num_buffer); - -out: - if (aim == c->aim0.ptr) - c->aim0.refs++; - if (aim == c->aim1.ptr) - c->aim1.refs++; - mutex_unlock(&c->start_mutex); - return 0; - -error: - module_put(iface->mod); - mutex_unlock(&c->start_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(most_start_channel); - -/** - * most_stop_channel - stops a running channel - * @iface: pointer to interface instance - * @id: channel ID - */ -int most_stop_channel(struct most_interface *iface, int id, - struct most_aim *aim) -{ - struct most_c_obj *c; - - if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { - pr_err("Bad interface or index out of range\n"); - return -EINVAL; - } - c = get_channel_by_iface(iface, id); - if (unlikely(!c)) - return -EINVAL; - - mutex_lock(&c->start_mutex); - if (c->aim0.refs + c->aim1.refs >= 2) - goto out; - - if (c->hdm_enqueue_task) - kthread_stop(c->hdm_enqueue_task); - c->hdm_enqueue_task = NULL; - - if (iface->mod) - module_put(iface->mod); - - c->is_poisoned = true; - if (c->iface->poison_channel(c->iface, c->channel_id)) { - pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id, - c->iface->description); - mutex_unlock(&c->start_mutex); - return -EAGAIN; - } - flush_trash_fifo(c); - flush_channel_fifos(c); - -#ifdef CMPL_INTERRUPTIBLE - if (wait_for_completion_interruptible(&c->cleanup)) { - pr_info("Interrupted while clean up ch %d\n", c->channel_id); - mutex_unlock(&c->start_mutex); - return -EINTR; - } -#else - wait_for_completion(&c->cleanup); -#endif - c->is_poisoned = false; - -out: - if (aim == c->aim0.ptr) - c->aim0.refs--; - if (aim == c->aim1.ptr) - c->aim1.refs--; - mutex_unlock(&c->start_mutex); - return 0; -} -EXPORT_SYMBOL_GPL(most_stop_channel); - -/** - * most_register_aim - registers an AIM (driver) with the core - * @aim: instance of AIM to be registered - */ -int most_register_aim(struct most_aim *aim) -{ - struct most_aim_obj *aim_obj; - - if (!aim) { - pr_err("Bad driver\n"); - return -EINVAL; - } - aim_obj = create_most_aim_obj(aim->name); - if (!aim_obj) { - pr_info("failed to alloc driver object\n"); - return -ENOMEM; - } - aim_obj->driver = aim; - aim->context = aim_obj; - pr_info("registered new application interfacing module %s\n", - aim->name); - list_add_tail(&aim_obj->list, &aim_list); - return 0; -} -EXPORT_SYMBOL_GPL(most_register_aim); - -/** - * most_deregister_aim - deregisters an AIM (driver) with the core - * @aim: AIM to be removed - */ -int most_deregister_aim(struct most_aim *aim) -{ - struct most_aim_obj *aim_obj; - struct most_c_obj *c, *tmp; - struct most_inst_obj *i, *i_tmp; - - if (!aim) { - pr_err("Bad driver\n"); - return -EINVAL; - } - - aim_obj = aim->context; - if (!aim_obj) { - pr_info("driver not registered.\n"); - return -EINVAL; - } - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (c->aim0.ptr == aim || c->aim1.ptr == aim) - aim->disconnect_channel( - c->iface, c->channel_id); - if (c->aim0.ptr == aim) - c->aim0.ptr = NULL; - if (c->aim1.ptr == aim) - c->aim1.ptr = NULL; - } - } - list_del(&aim_obj->list); - destroy_most_aim_obj(aim_obj); - pr_info("deregistering application interfacing module %s\n", aim->name); - return 0; -} -EXPORT_SYMBOL_GPL(most_deregister_aim); - -/** - * most_register_interface - registers an interface with core - * @iface: pointer to the instance of the interface description. - * - * Allocates and initializes a new interface instance and all of its channels. - * Returns a pointer to kobject or an error pointer. - */ -struct kobject *most_register_interface(struct most_interface *iface) -{ - unsigned int i; - int id; - char name[STRING_SIZE]; - char channel_name[STRING_SIZE]; - struct most_c_obj *c; - struct most_inst_obj *inst; - - if (!iface || !iface->enqueue || !iface->configure || - !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { - pr_err("Bad interface or channel overflow\n"); - return ERR_PTR(-EINVAL); - } - - id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); - if (id < 0) { - pr_info("Failed to alloc mdev ID\n"); - return ERR_PTR(id); - } - snprintf(name, STRING_SIZE, "mdev%d", id); - - inst = create_most_inst_obj(name); - if (!inst) { - pr_info("Failed to allocate interface instance\n"); - ida_simple_remove(&mdev_id, id); - return ERR_PTR(-ENOMEM); - } - - iface->priv = inst; - INIT_LIST_HEAD(&inst->channel_list); - inst->iface = iface; - inst->dev_id = id; - list_add_tail(&inst->list, &instance_list); - - for (i = 0; i < iface->num_channels; i++) { - const char *name_suffix = iface->channel_vector[i].name_suffix; - - if (!name_suffix) - snprintf(channel_name, STRING_SIZE, "ch%d", i); - else - snprintf(channel_name, STRING_SIZE, "%s", name_suffix); - - /* this increments the reference count of this instance */ - c = create_most_c_obj(channel_name, &inst->kobj); - if (!c) - goto free_instance; - inst->channel[i] = c; - c->is_starving = 0; - c->iface = iface; - c->inst = inst; - c->channel_id = i; - c->keep_mbo = false; - c->enqueue_halt = false; - c->is_poisoned = false; - c->cfg.direction = 0; - c->cfg.data_type = 0; - c->cfg.num_buffers = 0; - c->cfg.buffer_size = 0; - c->cfg.subbuffer_size = 0; - c->cfg.packets_per_xact = 0; - spin_lock_init(&c->fifo_lock); - INIT_LIST_HEAD(&c->fifo); - INIT_LIST_HEAD(&c->trash_fifo); - INIT_LIST_HEAD(&c->halt_fifo); - init_completion(&c->cleanup); - atomic_set(&c->mbo_ref, 0); - mutex_init(&c->start_mutex); - mutex_init(&c->nq_mutex); - list_add_tail(&c->list, &inst->channel_list); - } - pr_info("registered new MOST device mdev%d (%s)\n", - inst->dev_id, iface->description); - return &inst->kobj; - -free_instance: - pr_info("Failed allocate channel(s)\n"); - list_del(&inst->list); - ida_simple_remove(&mdev_id, id); - destroy_most_inst_obj(inst); - return ERR_PTR(-ENOMEM); -} -EXPORT_SYMBOL_GPL(most_register_interface); - -/** - * most_deregister_interface - deregisters an interface with core - * @iface: pointer to the interface instance description. - * - * Before removing an interface instance from the list, all running - * channels are stopped and poisoned. - */ -void most_deregister_interface(struct most_interface *iface) -{ - struct most_inst_obj *i = iface->priv; - struct most_c_obj *c; - - if (unlikely(!i)) { - pr_info("Bad Interface\n"); - return; - } - pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, - iface->description); - - list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.ptr) - c->aim0.ptr->disconnect_channel(c->iface, - c->channel_id); - if (c->aim1.ptr) - c->aim1.ptr->disconnect_channel(c->iface, - c->channel_id); - c->aim0.ptr = NULL; - c->aim1.ptr = NULL; - } - - ida_simple_remove(&mdev_id, i->dev_id); - list_del(&i->list); - destroy_most_inst_obj(i); -} -EXPORT_SYMBOL_GPL(most_deregister_interface); - -/** - * most_stop_enqueue - prevents core from enqueueing MBOs - * @iface: pointer to interface - * @id: channel id - * - * This is called by an HDM that _cannot_ attend to its duties and - * is imminent to get run over by the core. The core is not going to - * enqueue any further packets unless the flagging HDM calls - * most_resume enqueue(). - */ -void most_stop_enqueue(struct most_interface *iface, int id) -{ - struct most_c_obj *c = get_channel_by_iface(iface, id); - - if (!c) - return; - - mutex_lock(&c->nq_mutex); - c->enqueue_halt = true; - mutex_unlock(&c->nq_mutex); -} -EXPORT_SYMBOL_GPL(most_stop_enqueue); - -/** - * most_resume_enqueue - allow core to enqueue MBOs again - * @iface: pointer to interface - * @id: channel id - * - * This clears the enqueue halt flag and enqueues all MBOs currently - * sitting in the wait fifo. - */ -void most_resume_enqueue(struct most_interface *iface, int id) -{ - struct most_c_obj *c = get_channel_by_iface(iface, id); - - if (!c) - return; - - mutex_lock(&c->nq_mutex); - c->enqueue_halt = false; - mutex_unlock(&c->nq_mutex); - - wake_up_interruptible(&c->hdm_fifo_wq); -} -EXPORT_SYMBOL_GPL(most_resume_enqueue); - -static int __init most_init(void) -{ - int err; - - pr_info("init()\n"); - INIT_LIST_HEAD(&instance_list); - INIT_LIST_HEAD(&aim_list); - ida_init(&mdev_id); - - err = bus_register(&most_bus); - if (err) { - pr_info("Cannot register most bus\n"); - return err; - } - - most_class = class_create(THIS_MODULE, "most"); - if (IS_ERR(most_class)) { - pr_info("No udev support.\n"); - err = PTR_ERR(most_class); - goto exit_bus; - } - - err = driver_register(&mostcore); - if (err) { - pr_info("Cannot register core driver\n"); - goto exit_class; - } - - core_dev = device_create(most_class, NULL, 0, NULL, "mostcore"); - if (IS_ERR(core_dev)) { - err = PTR_ERR(core_dev); - goto exit_driver; - } - - most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj); - if (!most_aim_kset) { - err = -ENOMEM; - goto exit_class_container; - } - - most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj); - if (!most_inst_kset) { - err = -ENOMEM; - goto exit_driver_kset; - } - - return 0; - -exit_driver_kset: - kset_unregister(most_aim_kset); -exit_class_container: - device_destroy(most_class, 0); -exit_driver: - driver_unregister(&mostcore); -exit_class: - class_destroy(most_class); -exit_bus: - bus_unregister(&most_bus); - return err; -} - -static void __exit most_exit(void) -{ - struct most_inst_obj *i, *i_tmp; - struct most_aim_obj *d, *d_tmp; - - pr_info("exit core module\n"); - list_for_each_entry_safe(d, d_tmp, &aim_list, list) { - destroy_most_aim_obj(d); - } - - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - list_del(&i->list); - destroy_most_inst_obj(i); - } - kset_unregister(most_inst_kset); - kset_unregister(most_aim_kset); - device_destroy(most_class, 0); - driver_unregister(&mostcore); - class_destroy(most_class); - bus_unregister(&most_bus); - ida_destroy(&mdev_id); -} - -module_init(most_init); -module_exit(most_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Gromm "); -MODULE_DESCRIPTION("Core module of stacked MOST Linux driver"); diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h deleted file mode 100644 index f6fdba0c5eaf..000000000000 --- a/drivers/staging/most/mostcore/mostcore.h +++ /dev/null @@ -1,319 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * mostcore.h - Interface between MostCore, - * Hardware Dependent Module (HDM) and Application Interface Module (AIM). - * - * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG - */ - -/* - * Authors: - * Andrey Shvetsov - * Christian Gromm - * Sebastian Graf - */ - -#ifndef __MOST_CORE_H__ -#define __MOST_CORE_H__ - -#include - -struct kobject; -struct module; - -/** - * Interface type - */ -enum most_interface_type { - ITYPE_LOOPBACK = 1, - ITYPE_I2C, - ITYPE_I2S, - ITYPE_TSI, - ITYPE_HBI, - ITYPE_MEDIALB_DIM, - ITYPE_MEDIALB_DIM2, - ITYPE_USB, - ITYPE_PCIE -}; - -/** - * Channel direction. - */ -enum most_channel_direction { - MOST_CH_RX = 1 << 0, - MOST_CH_TX = 1 << 1, -}; - -/** - * Channel data type. - */ -enum most_channel_data_type { - MOST_CH_CONTROL = 1 << 0, - MOST_CH_ASYNC = 1 << 1, - MOST_CH_ISOC = 1 << 2, - MOST_CH_SYNC = 1 << 5, -}; - -enum mbo_status_flags { - /* MBO was processed successfully (data was send or received )*/ - MBO_SUCCESS = 0, - /* The MBO contains wrong or missing information. */ - MBO_E_INVAL, - /* MBO was completed as HDM Channel will be closed */ - MBO_E_CLOSE, -}; - -/** - * struct most_channel_capability - Channel capability - * @direction: Supported channel directions. - * The value is bitwise OR-combination of the values from the - * enumeration most_channel_direction. Zero is allowed value and means - * "channel may not be used". - * @data_type: Supported channel data types. - * The value is bitwise OR-combination of the values from the - * enumeration most_channel_data_type. Zero is allowed value and means - * "channel may not be used". - * @num_buffer_packet: Maximum number of buffers supported by this channel - * for packet data types (Async,Control,QoS) - * @buffer_size_packet: Maximum buffer size supported by this channel - * for packet data types (Async,Control,QoS) - * @num_buffer_streaming: Maximum number of buffers supported by this channel - * for streaming data types (Sync,AV Packetized) - * @buffer_size_streaming: Maximum buffer size supported by this channel - * for streaming data types (Sync,AV Packetized) - * @name_suffix: Optional suffix providean by an HDM that is attached to the - * regular channel name. - * - * Describes the capabilities of a MostCore channel like supported Data Types - * and directions. This information is provided by an HDM for the MostCore. - * - * The Core creates read only sysfs attribute files in - * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the - * following attributes: - * -available_directions - * -available_datatypes - * -number_of_packet_buffers - * -number_of_stream_buffers - * -size_of_packet_buffer - * -size_of_stream_buffer - * where content of each file is a string with all supported properties of this - * very channel attribute. - */ -struct most_channel_capability { - u16 direction; - u16 data_type; - u16 num_buffers_packet; - u16 buffer_size_packet; - u16 num_buffers_streaming; - u16 buffer_size_streaming; - const char *name_suffix; -}; - -/** - * struct most_channel_config - stores channel configuration - * @direction: direction of the channel - * @data_type: data type travelling over this channel - * @num_buffers: number of buffers - * @buffer_size: size of a buffer for AIM. - * Buffer size may be cutted down by HDM in a configure callback - * to match to a given interface and channel type. - * @extra_len: additional buffer space for internal HDM purposes like padding. - * May be set by HDM in a configure callback if needed. - * @subbuffer_size: size of a subbuffer - * @packets_per_xact: number of MOST frames that are packet inside one USB - * packet. This is USB specific - * - * Describes the configuration for a MostCore channel. This information is - * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a - * parameter of the "configure" function call. - */ -struct most_channel_config { - enum most_channel_direction direction; - enum most_channel_data_type data_type; - u16 num_buffers; - u16 buffer_size; - u16 extra_len; - u16 subbuffer_size; - u16 packets_per_xact; -}; - -/* - * struct mbo - MOST Buffer Object. - * @context: context for core completion handler - * @priv: private data for HDM - * - * public: documented fields that are used for the communications - * between MostCore and HDMs - * - * @list: list head for use by the mbo's current owner - * @ifp: (in) associated interface instance - * @hdm_channel_id: (in) HDM channel instance - * @virt_address: (in) kernel virtual address of the buffer - * @bus_address: (in) bus address of the buffer - * @buffer_length: (in) buffer payload length - * @processed_length: (out) processed length - * @status: (out) transfer status - * @complete: (in) completion routine - * - * The MostCore allocates and initializes the MBO. - * - * The HDM receives MBO for transfer from MostCore with the call to enqueue(). - * The HDM copies the data to- or from the buffer depending on configured - * channel direction, set "processed_length" and "status" and completes - * the transfer procedure by calling the completion routine. - * - * At the end the MostCore deallocates the MBO or recycles it for further - * transfers for the same or different HDM. - * - * Directions of usage: - * The core driver should never access any MBO fields (even if marked - * as "public") while the MBO is owned by an HDM. The ownership starts with - * the call of enqueue() and ends with the call of its complete() routine. - * - * II. - * Every HDM attached to the core driver _must_ ensure that it returns any MBO - * it owns (due to a previous call to enqueue() by the core driver) before it - * de-registers an interface or gets unloaded from the kernel. If this direction - * is violated memory leaks will occur, since the core driver does _not_ track - * MBOs it is currently not in control of. - * - */ -struct mbo { - void *context; - void *priv; - struct list_head list; - struct most_interface *ifp; - int *num_buffers_ptr; - u16 hdm_channel_id; - void *virt_address; - dma_addr_t bus_address; - u16 buffer_length; - u16 processed_length; - enum mbo_status_flags status; - void (*complete)(struct mbo *); -}; - -/** - * Interface instance description. - * - * Describes one instance of an interface like Medusa PCIe or Vantage USB. - * This structure is allocated and initialized in the HDM. MostCore may not - * modify this structure. - * - * @interface Interface type. \sa most_interface_type. - * @description PRELIMINARY. - * Unique description of the device instance from point of view of the - * interface in free text form (ASCII). - * It may be a hexadecimal presentation of the memory address for the MediaLB - * IP or USB device ID with USB properties for USB interface, etc. - * @num_channels Number of channels and size of the channel_vector. - * @channel_vector Properties of the channels. - * Array index represents channel ID by the driver. - * @configure Callback to change data type for the channel of the - * interface instance. May be zero if the instance of the interface is not - * configurable. Parameter channel_config describes direction and data - * type for the channel, configured by the higher level. The content of - * @enqueue Delivers MBO to the HDM for processing. - * After HDM completes Rx- or Tx- operation the processed MBO shall - * be returned back to the MostCore using completion routine. - * The reason to get the MBO delivered from the MostCore after the channel - * is poisoned is the re-opening of the channel by the application. - * In this case the HDM shall hold MBOs and service the channel as usual. - * The HDM must be able to hold at least one MBO for each channel. - * The callback returns a negative value on error, otherwise 0. - * @poison_channel Informs HDM about closing the channel. The HDM shall - * cancel all transfers and synchronously or asynchronously return - * all enqueued for this channel MBOs using the completion routine. - * The callback returns a negative value on error, otherwise 0. - * @request_netinfo: triggers retrieving of network info from the HDM by - * means of "Message exchange over MDP/MEP" - * The call of the function request_netinfo with the parameter on_netinfo as - * NULL prohibits use of the previously obtained function pointer. - * @priv Private field used by mostcore to store context information. - */ -struct most_interface { - struct module *mod; - enum most_interface_type interface; - const char *description; - int num_channels; - struct most_channel_capability *channel_vector; - int (*configure)(struct most_interface *iface, int channel_idx, - struct most_channel_config *channel_config); - int (*enqueue)(struct most_interface *iface, int channel_idx, - struct mbo *mbo); - int (*poison_channel)(struct most_interface *iface, int channel_idx); - void (*request_netinfo)(struct most_interface *iface, int channel_idx, - void (*on_netinfo)(struct most_interface *iface, - unsigned char link_stat, - unsigned char *mac_addr)); - void *priv; -}; - -/** - * struct most_aim - identifies MOST device driver to mostcore - * @name: Driver name - * @probe_channel: function for core to notify driver about channel connection - * @disconnect_channel: callback function to disconnect a certain channel - * @rx_completion: completion handler for received packets - * @tx_completion: completion handler for transmitted packets - * @context: context pointer to be used by mostcore - */ -struct most_aim { - const char *name; - int (*probe_channel)(struct most_interface *iface, int channel_idx, - struct most_channel_config *cfg, - struct kobject *parent, char *name); - int (*disconnect_channel)(struct most_interface *iface, - int channel_idx); - int (*rx_completion)(struct mbo *mbo); - int (*tx_completion)(struct most_interface *iface, int channel_idx); - void *context; -}; - -/** - * most_register_interface - Registers instance of the interface. - * @iface: Pointer to the interface instance description. - * - * Returns a pointer to the kobject of the generated instance. - * - * Note: HDM has to ensure that any reference held on the kobj is - * released before deregistering the interface. - */ -struct kobject *most_register_interface(struct most_interface *iface); - -/** - * Deregisters instance of the interface. - * @intf_instance Pointer to the interface instance description. - */ -void most_deregister_interface(struct most_interface *iface); -void most_submit_mbo(struct mbo *mbo); - -/** - * most_stop_enqueue - prevents core from enqueing MBOs - * @iface: pointer to interface - * @channel_idx: channel index - */ -void most_stop_enqueue(struct most_interface *iface, int channel_idx); - -/** - * most_resume_enqueue - allow core to enqueue MBOs again - * @iface: pointer to interface - * @channel_idx: channel index - * - * This clears the enqueue halt flag and enqueues all MBOs currently - * in wait fifo. - */ -void most_resume_enqueue(struct most_interface *iface, int channel_idx); -int most_register_aim(struct most_aim *aim); -int most_deregister_aim(struct most_aim *aim); -struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx, - struct most_aim *); -void most_put_mbo(struct mbo *mbo); -int channel_has_mbo(struct most_interface *iface, int channel_idx, - struct most_aim *aim); -int most_start_channel(struct most_interface *iface, int channel_idx, - struct most_aim *); -int most_stop_channel(struct most_interface *iface, int channel_idx, - struct most_aim *); - -#endif /* MOST_CORE_H_ */ -- cgit v1.2.3 From 7b9cdcf6ea8062b4a003b0a06601d94a52f95eeb Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:36 +0100 Subject: staging: most: cdev: rename module This patch renames the folder of the cdev module. This is needed to clear the directory layout. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Kconfig | 2 +- drivers/staging/most/aim-cdev/Kconfig | 12 - drivers/staging/most/aim-cdev/cdev.c | 558 ---------------------------------- drivers/staging/most/cdev/Kconfig | 12 + drivers/staging/most/cdev/Makefile | 4 + drivers/staging/most/cdev/cdev.c | 558 ++++++++++++++++++++++++++++++++++ 6 files changed, 575 insertions(+), 571 deletions(-) delete mode 100644 drivers/staging/most/aim-cdev/Kconfig delete mode 100644 drivers/staging/most/aim-cdev/cdev.c create mode 100644 drivers/staging/most/cdev/Kconfig create mode 100644 drivers/staging/most/cdev/Makefile create mode 100644 drivers/staging/most/cdev/cdev.c (limited to 'drivers') diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 2045f7ac5081..60a2825e6076 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -17,7 +17,7 @@ menuconfig MOST if MOST -source "drivers/staging/most/aim-cdev/Kconfig" +source "drivers/staging/most/cdev/Kconfig" source "drivers/staging/most/aim-network/Kconfig" diff --git a/drivers/staging/most/aim-cdev/Kconfig b/drivers/staging/most/aim-cdev/Kconfig deleted file mode 100644 index 3c59f1bac127..000000000000 --- a/drivers/staging/most/aim-cdev/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# -# MOST Cdev configuration -# - -config AIM_CDEV - tristate "Cdev AIM" - - ---help--- - Say Y here if you want to commumicate via character devices. - - To compile this driver as a module, choose M here: the - module will be called aim_cdev. \ No newline at end of file diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c deleted file mode 100644 index 3ae9246c0c5c..000000000000 --- a/drivers/staging/most/aim-cdev/cdev.c +++ /dev/null @@ -1,558 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * cdev.c - Application interfacing module for character devices - * - * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "most/core.h" - -static dev_t aim_devno; -static struct class *aim_class; -static struct ida minor_id; -static unsigned int major; -static struct most_aim cdev_aim; - -struct aim_channel { - wait_queue_head_t wq; - spinlock_t unlink; /* synchronization lock to unlink channels */ - struct cdev cdev; - struct device *dev; - struct mutex io_mutex; - struct most_interface *iface; - struct most_channel_config *cfg; - unsigned int channel_id; - dev_t devno; - size_t mbo_offs; - DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); - int access_ref; - struct list_head list; -}; - -#define to_channel(d) container_of(d, struct aim_channel, cdev) -static struct list_head channel_list; -static spinlock_t ch_list_lock; - -static inline bool ch_has_mbo(struct aim_channel *c) -{ - return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; -} - -static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) -{ - if (!kfifo_peek(&c->fifo, mbo)) { - *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); - if (*mbo) - kfifo_in(&c->fifo, mbo, 1); - } - return *mbo; -} - -static struct aim_channel *get_channel(struct most_interface *iface, int id) -{ - struct aim_channel *c, *tmp; - unsigned long flags; - int found_channel = 0; - - spin_lock_irqsave(&ch_list_lock, flags); - list_for_each_entry_safe(c, tmp, &channel_list, list) { - if ((c->iface == iface) && (c->channel_id == id)) { - found_channel = 1; - break; - } - } - spin_unlock_irqrestore(&ch_list_lock, flags); - if (!found_channel) - return NULL; - return c; -} - -static void stop_channel(struct aim_channel *c) -{ - struct mbo *mbo; - - while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) - most_put_mbo(mbo); - most_stop_channel(c->iface, c->channel_id, &cdev_aim); -} - -static void destroy_cdev(struct aim_channel *c) -{ - unsigned long flags; - - device_destroy(aim_class, c->devno); - cdev_del(&c->cdev); - spin_lock_irqsave(&ch_list_lock, flags); - list_del(&c->list); - spin_unlock_irqrestore(&ch_list_lock, flags); -} - -static void destroy_channel(struct aim_channel *c) -{ - ida_simple_remove(&minor_id, MINOR(c->devno)); - kfifo_free(&c->fifo); - kfree(c); -} - -/** - * aim_open - implements the syscall to open the device - * @inode: inode pointer - * @filp: file pointer - * - * This stores the channel pointer in the private data field of - * the file structure and activates the channel within the core. - */ -static int aim_open(struct inode *inode, struct file *filp) -{ - struct aim_channel *c; - int ret; - - c = to_channel(inode->i_cdev); - filp->private_data = c; - - if (((c->cfg->direction == MOST_CH_RX) && - ((filp->f_flags & O_ACCMODE) != O_RDONLY)) || - ((c->cfg->direction == MOST_CH_TX) && - ((filp->f_flags & O_ACCMODE) != O_WRONLY))) { - pr_info("WARN: Access flags mismatch\n"); - return -EACCES; - } - - mutex_lock(&c->io_mutex); - if (!c->dev) { - pr_info("WARN: Device is destroyed\n"); - mutex_unlock(&c->io_mutex); - return -ENODEV; - } - - if (c->access_ref) { - pr_info("WARN: Device is busy\n"); - mutex_unlock(&c->io_mutex); - return -EBUSY; - } - - c->mbo_offs = 0; - ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); - if (!ret) - c->access_ref = 1; - mutex_unlock(&c->io_mutex); - return ret; -} - -/** - * aim_close - implements the syscall to close the device - * @inode: inode pointer - * @filp: file pointer - * - * This stops the channel within the core. - */ -static int aim_close(struct inode *inode, struct file *filp) -{ - struct aim_channel *c = to_channel(inode->i_cdev); - - mutex_lock(&c->io_mutex); - spin_lock(&c->unlink); - c->access_ref = 0; - spin_unlock(&c->unlink); - if (c->dev) { - stop_channel(c); - mutex_unlock(&c->io_mutex); - } else { - mutex_unlock(&c->io_mutex); - destroy_channel(c); - } - return 0; -} - -/** - * aim_write - implements the syscall to write to the device - * @filp: file pointer - * @buf: pointer to user buffer - * @count: number of bytes to write - * @offset: offset from where to start writing - */ -static ssize_t aim_write(struct file *filp, const char __user *buf, - size_t count, loff_t *offset) -{ - int ret; - size_t to_copy, left; - struct mbo *mbo = NULL; - struct aim_channel *c = filp->private_data; - - mutex_lock(&c->io_mutex); - while (c->dev && !ch_get_mbo(c, &mbo)) { - mutex_unlock(&c->io_mutex); - - if ((filp->f_flags & O_NONBLOCK)) - return -EAGAIN; - if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev)) - return -ERESTARTSYS; - mutex_lock(&c->io_mutex); - } - - if (unlikely(!c->dev)) { - ret = -ENODEV; - goto unlock; - } - - to_copy = min(count, c->cfg->buffer_size - c->mbo_offs); - left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy); - if (left == to_copy) { - ret = -EFAULT; - goto unlock; - } - - c->mbo_offs += to_copy - left; - if (c->mbo_offs >= c->cfg->buffer_size || - c->cfg->data_type == MOST_CH_CONTROL || - c->cfg->data_type == MOST_CH_ASYNC) { - kfifo_skip(&c->fifo); - mbo->buffer_length = c->mbo_offs; - c->mbo_offs = 0; - most_submit_mbo(mbo); - } - - ret = to_copy - left; -unlock: - mutex_unlock(&c->io_mutex); - return ret; -} - -/** - * aim_read - implements the syscall to read from the device - * @filp: file pointer - * @buf: pointer to user buffer - * @count: number of bytes to read - * @offset: offset from where to start reading - */ -static ssize_t -aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) -{ - size_t to_copy, not_copied, copied; - struct mbo *mbo; - struct aim_channel *c = filp->private_data; - - mutex_lock(&c->io_mutex); - while (c->dev && !kfifo_peek(&c->fifo, &mbo)) { - mutex_unlock(&c->io_mutex); - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - if (wait_event_interruptible(c->wq, - (!kfifo_is_empty(&c->fifo) || - (!c->dev)))) - return -ERESTARTSYS; - mutex_lock(&c->io_mutex); - } - - /* make sure we don't submit to gone devices */ - if (unlikely(!c->dev)) { - mutex_unlock(&c->io_mutex); - return -ENODEV; - } - - to_copy = min_t(size_t, - count, - mbo->processed_length - c->mbo_offs); - - not_copied = copy_to_user(buf, - mbo->virt_address + c->mbo_offs, - to_copy); - - copied = to_copy - not_copied; - - c->mbo_offs += copied; - if (c->mbo_offs >= mbo->processed_length) { - kfifo_skip(&c->fifo); - most_put_mbo(mbo); - c->mbo_offs = 0; - } - mutex_unlock(&c->io_mutex); - return copied; -} - -static unsigned int aim_poll(struct file *filp, poll_table *wait) -{ - struct aim_channel *c = filp->private_data; - unsigned int mask = 0; - - poll_wait(filp, &c->wq, wait); - - if (c->cfg->direction == MOST_CH_RX) { - if (!kfifo_is_empty(&c->fifo)) - mask |= POLLIN | POLLRDNORM; - } else { - if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c)) - mask |= POLLOUT | POLLWRNORM; - } - return mask; -} - -/** - * Initialization of struct file_operations - */ -static const struct file_operations channel_fops = { - .owner = THIS_MODULE, - .read = aim_read, - .write = aim_write, - .open = aim_open, - .release = aim_close, - .poll = aim_poll, -}; - -/** - * aim_disconnect_channel - disconnect a channel - * @iface: pointer to interface instance - * @channel_id: channel index - * - * This frees allocated memory and removes the cdev that represents this - * channel in user space. - */ -static int aim_disconnect_channel(struct most_interface *iface, int channel_id) -{ - struct aim_channel *c; - - if (!iface) { - pr_info("Bad interface pointer\n"); - return -EINVAL; - } - - c = get_channel(iface, channel_id); - if (!c) - return -ENXIO; - - mutex_lock(&c->io_mutex); - spin_lock(&c->unlink); - c->dev = NULL; - spin_unlock(&c->unlink); - destroy_cdev(c); - if (c->access_ref) { - stop_channel(c); - wake_up_interruptible(&c->wq); - mutex_unlock(&c->io_mutex); - } else { - mutex_unlock(&c->io_mutex); - destroy_channel(c); - } - return 0; -} - -/** - * aim_rx_completion - completion handler for rx channels - * @mbo: pointer to buffer object that has completed - * - * This searches for the channel linked to this MBO and stores it in the local - * fifo buffer. - */ -static int aim_rx_completion(struct mbo *mbo) -{ - struct aim_channel *c; - - if (!mbo) - return -EINVAL; - - c = get_channel(mbo->ifp, mbo->hdm_channel_id); - if (!c) - return -ENXIO; - - spin_lock(&c->unlink); - if (!c->access_ref || !c->dev) { - spin_unlock(&c->unlink); - return -ENODEV; - } - kfifo_in(&c->fifo, &mbo, 1); - spin_unlock(&c->unlink); -#ifdef DEBUG_MESG - if (kfifo_is_full(&c->fifo)) - pr_info("WARN: Fifo is full\n"); -#endif - wake_up_interruptible(&c->wq); - return 0; -} - -/** - * aim_tx_completion - completion handler for tx channels - * @iface: pointer to interface instance - * @channel_id: channel index/ID - * - * This wakes sleeping processes in the wait-queue. - */ -static int aim_tx_completion(struct most_interface *iface, int channel_id) -{ - struct aim_channel *c; - - if (!iface) { - pr_info("Bad interface pointer\n"); - return -EINVAL; - } - if ((channel_id < 0) || (channel_id >= iface->num_channels)) { - pr_info("Channel ID out of range\n"); - return -EINVAL; - } - - c = get_channel(iface, channel_id); - if (!c) - return -ENXIO; - wake_up_interruptible(&c->wq); - return 0; -} - -/** - * aim_probe - probe function of the driver module - * @iface: pointer to interface instance - * @channel_id: channel index/ID - * @cfg: pointer to actual channel configuration - * @parent: pointer to kobject (needed for sysfs hook-up) - * @name: name of the device to be created - * - * This allocates achannel object and creates the device node in /dev - * - * Returns 0 on success or error code otherwise. - */ -static int aim_probe(struct most_interface *iface, int channel_id, - struct most_channel_config *cfg, - struct kobject *parent, char *name) -{ - struct aim_channel *c; - unsigned long cl_flags; - int retval; - int current_minor; - - if ((!iface) || (!cfg) || (!parent) || (!name)) { - pr_info("Probing AIM with bad arguments"); - return -EINVAL; - } - c = get_channel(iface, channel_id); - if (c) - return -EEXIST; - - current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL); - if (current_minor < 0) - return current_minor; - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) { - retval = -ENOMEM; - goto error_alloc_channel; - } - - c->devno = MKDEV(major, current_minor); - cdev_init(&c->cdev, &channel_fops); - c->cdev.owner = THIS_MODULE; - cdev_add(&c->cdev, c->devno, 1); - c->iface = iface; - c->cfg = cfg; - c->channel_id = channel_id; - c->access_ref = 0; - spin_lock_init(&c->unlink); - INIT_KFIFO(c->fifo); - retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); - if (retval) { - pr_info("failed to alloc channel kfifo"); - goto error_alloc_kfifo; - } - init_waitqueue_head(&c->wq); - mutex_init(&c->io_mutex); - spin_lock_irqsave(&ch_list_lock, cl_flags); - list_add_tail(&c->list, &channel_list); - spin_unlock_irqrestore(&ch_list_lock, cl_flags); - c->dev = device_create(aim_class, - NULL, - c->devno, - NULL, - "%s", name); - - if (IS_ERR(c->dev)) { - retval = PTR_ERR(c->dev); - pr_info("failed to create new device node %s\n", name); - goto error_create_device; - } - kobject_uevent(&c->dev->kobj, KOBJ_ADD); - return 0; - -error_create_device: - kfifo_free(&c->fifo); - list_del(&c->list); -error_alloc_kfifo: - cdev_del(&c->cdev); - kfree(c); -error_alloc_channel: - ida_simple_remove(&minor_id, current_minor); - return retval; -} - -static struct most_aim cdev_aim = { - .name = "cdev", - .probe_channel = aim_probe, - .disconnect_channel = aim_disconnect_channel, - .rx_completion = aim_rx_completion, - .tx_completion = aim_tx_completion, -}; - -static int __init mod_init(void) -{ - int err; - - pr_info("init()\n"); - - INIT_LIST_HEAD(&channel_list); - spin_lock_init(&ch_list_lock); - ida_init(&minor_id); - - err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev"); - if (err < 0) - goto dest_ida; - major = MAJOR(aim_devno); - - aim_class = class_create(THIS_MODULE, "most_cdev_aim"); - if (IS_ERR(aim_class)) { - pr_err("no udev support\n"); - err = PTR_ERR(aim_class); - goto free_cdev; - } - err = most_register_aim(&cdev_aim); - if (err) - goto dest_class; - return 0; - -dest_class: - class_destroy(aim_class); -free_cdev: - unregister_chrdev_region(aim_devno, 1); -dest_ida: - ida_destroy(&minor_id); - return err; -} - -static void __exit mod_exit(void) -{ - struct aim_channel *c, *tmp; - - pr_info("exit module\n"); - - most_deregister_aim(&cdev_aim); - - list_for_each_entry_safe(c, tmp, &channel_list, list) { - destroy_cdev(c); - destroy_channel(c); - } - class_destroy(aim_class); - unregister_chrdev_region(aim_devno, 1); - ida_destroy(&minor_id); -} - -module_init(mod_init); -module_exit(mod_exit); -MODULE_AUTHOR("Christian Gromm "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("character device AIM for mostcore"); diff --git a/drivers/staging/most/cdev/Kconfig b/drivers/staging/most/cdev/Kconfig new file mode 100644 index 000000000000..2b04e26bcbea --- /dev/null +++ b/drivers/staging/most/cdev/Kconfig @@ -0,0 +1,12 @@ +# +# MOST Cdev configuration +# + +config MOST_CDEV + tristate "Cdev" + + ---help--- + Say Y here if you want to commumicate via character devices. + + To compile this driver as a module, choose M here: the + module will be called most_cdev. diff --git a/drivers/staging/most/cdev/Makefile b/drivers/staging/most/cdev/Makefile new file mode 100644 index 000000000000..afb9870eb50f --- /dev/null +++ b/drivers/staging/most/cdev/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_CDEV) += most_cdev.o + +most_cdev-objs := cdev.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c new file mode 100644 index 000000000000..3ae9246c0c5c --- /dev/null +++ b/drivers/staging/most/cdev/cdev.c @@ -0,0 +1,558 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * cdev.c - Application interfacing module for character devices + * + * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "most/core.h" + +static dev_t aim_devno; +static struct class *aim_class; +static struct ida minor_id; +static unsigned int major; +static struct most_aim cdev_aim; + +struct aim_channel { + wait_queue_head_t wq; + spinlock_t unlink; /* synchronization lock to unlink channels */ + struct cdev cdev; + struct device *dev; + struct mutex io_mutex; + struct most_interface *iface; + struct most_channel_config *cfg; + unsigned int channel_id; + dev_t devno; + size_t mbo_offs; + DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); + int access_ref; + struct list_head list; +}; + +#define to_channel(d) container_of(d, struct aim_channel, cdev) +static struct list_head channel_list; +static spinlock_t ch_list_lock; + +static inline bool ch_has_mbo(struct aim_channel *c) +{ + return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; +} + +static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) +{ + if (!kfifo_peek(&c->fifo, mbo)) { + *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + if (*mbo) + kfifo_in(&c->fifo, mbo, 1); + } + return *mbo; +} + +static struct aim_channel *get_channel(struct most_interface *iface, int id) +{ + struct aim_channel *c, *tmp; + unsigned long flags; + int found_channel = 0; + + spin_lock_irqsave(&ch_list_lock, flags); + list_for_each_entry_safe(c, tmp, &channel_list, list) { + if ((c->iface == iface) && (c->channel_id == id)) { + found_channel = 1; + break; + } + } + spin_unlock_irqrestore(&ch_list_lock, flags); + if (!found_channel) + return NULL; + return c; +} + +static void stop_channel(struct aim_channel *c) +{ + struct mbo *mbo; + + while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) + most_put_mbo(mbo); + most_stop_channel(c->iface, c->channel_id, &cdev_aim); +} + +static void destroy_cdev(struct aim_channel *c) +{ + unsigned long flags; + + device_destroy(aim_class, c->devno); + cdev_del(&c->cdev); + spin_lock_irqsave(&ch_list_lock, flags); + list_del(&c->list); + spin_unlock_irqrestore(&ch_list_lock, flags); +} + +static void destroy_channel(struct aim_channel *c) +{ + ida_simple_remove(&minor_id, MINOR(c->devno)); + kfifo_free(&c->fifo); + kfree(c); +} + +/** + * aim_open - implements the syscall to open the device + * @inode: inode pointer + * @filp: file pointer + * + * This stores the channel pointer in the private data field of + * the file structure and activates the channel within the core. + */ +static int aim_open(struct inode *inode, struct file *filp) +{ + struct aim_channel *c; + int ret; + + c = to_channel(inode->i_cdev); + filp->private_data = c; + + if (((c->cfg->direction == MOST_CH_RX) && + ((filp->f_flags & O_ACCMODE) != O_RDONLY)) || + ((c->cfg->direction == MOST_CH_TX) && + ((filp->f_flags & O_ACCMODE) != O_WRONLY))) { + pr_info("WARN: Access flags mismatch\n"); + return -EACCES; + } + + mutex_lock(&c->io_mutex); + if (!c->dev) { + pr_info("WARN: Device is destroyed\n"); + mutex_unlock(&c->io_mutex); + return -ENODEV; + } + + if (c->access_ref) { + pr_info("WARN: Device is busy\n"); + mutex_unlock(&c->io_mutex); + return -EBUSY; + } + + c->mbo_offs = 0; + ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); + if (!ret) + c->access_ref = 1; + mutex_unlock(&c->io_mutex); + return ret; +} + +/** + * aim_close - implements the syscall to close the device + * @inode: inode pointer + * @filp: file pointer + * + * This stops the channel within the core. + */ +static int aim_close(struct inode *inode, struct file *filp) +{ + struct aim_channel *c = to_channel(inode->i_cdev); + + mutex_lock(&c->io_mutex); + spin_lock(&c->unlink); + c->access_ref = 0; + spin_unlock(&c->unlink); + if (c->dev) { + stop_channel(c); + mutex_unlock(&c->io_mutex); + } else { + mutex_unlock(&c->io_mutex); + destroy_channel(c); + } + return 0; +} + +/** + * aim_write - implements the syscall to write to the device + * @filp: file pointer + * @buf: pointer to user buffer + * @count: number of bytes to write + * @offset: offset from where to start writing + */ +static ssize_t aim_write(struct file *filp, const char __user *buf, + size_t count, loff_t *offset) +{ + int ret; + size_t to_copy, left; + struct mbo *mbo = NULL; + struct aim_channel *c = filp->private_data; + + mutex_lock(&c->io_mutex); + while (c->dev && !ch_get_mbo(c, &mbo)) { + mutex_unlock(&c->io_mutex); + + if ((filp->f_flags & O_NONBLOCK)) + return -EAGAIN; + if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev)) + return -ERESTARTSYS; + mutex_lock(&c->io_mutex); + } + + if (unlikely(!c->dev)) { + ret = -ENODEV; + goto unlock; + } + + to_copy = min(count, c->cfg->buffer_size - c->mbo_offs); + left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy); + if (left == to_copy) { + ret = -EFAULT; + goto unlock; + } + + c->mbo_offs += to_copy - left; + if (c->mbo_offs >= c->cfg->buffer_size || + c->cfg->data_type == MOST_CH_CONTROL || + c->cfg->data_type == MOST_CH_ASYNC) { + kfifo_skip(&c->fifo); + mbo->buffer_length = c->mbo_offs; + c->mbo_offs = 0; + most_submit_mbo(mbo); + } + + ret = to_copy - left; +unlock: + mutex_unlock(&c->io_mutex); + return ret; +} + +/** + * aim_read - implements the syscall to read from the device + * @filp: file pointer + * @buf: pointer to user buffer + * @count: number of bytes to read + * @offset: offset from where to start reading + */ +static ssize_t +aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) +{ + size_t to_copy, not_copied, copied; + struct mbo *mbo; + struct aim_channel *c = filp->private_data; + + mutex_lock(&c->io_mutex); + while (c->dev && !kfifo_peek(&c->fifo, &mbo)) { + mutex_unlock(&c->io_mutex); + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(c->wq, + (!kfifo_is_empty(&c->fifo) || + (!c->dev)))) + return -ERESTARTSYS; + mutex_lock(&c->io_mutex); + } + + /* make sure we don't submit to gone devices */ + if (unlikely(!c->dev)) { + mutex_unlock(&c->io_mutex); + return -ENODEV; + } + + to_copy = min_t(size_t, + count, + mbo->processed_length - c->mbo_offs); + + not_copied = copy_to_user(buf, + mbo->virt_address + c->mbo_offs, + to_copy); + + copied = to_copy - not_copied; + + c->mbo_offs += copied; + if (c->mbo_offs >= mbo->processed_length) { + kfifo_skip(&c->fifo); + most_put_mbo(mbo); + c->mbo_offs = 0; + } + mutex_unlock(&c->io_mutex); + return copied; +} + +static unsigned int aim_poll(struct file *filp, poll_table *wait) +{ + struct aim_channel *c = filp->private_data; + unsigned int mask = 0; + + poll_wait(filp, &c->wq, wait); + + if (c->cfg->direction == MOST_CH_RX) { + if (!kfifo_is_empty(&c->fifo)) + mask |= POLLIN | POLLRDNORM; + } else { + if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c)) + mask |= POLLOUT | POLLWRNORM; + } + return mask; +} + +/** + * Initialization of struct file_operations + */ +static const struct file_operations channel_fops = { + .owner = THIS_MODULE, + .read = aim_read, + .write = aim_write, + .open = aim_open, + .release = aim_close, + .poll = aim_poll, +}; + +/** + * aim_disconnect_channel - disconnect a channel + * @iface: pointer to interface instance + * @channel_id: channel index + * + * This frees allocated memory and removes the cdev that represents this + * channel in user space. + */ +static int aim_disconnect_channel(struct most_interface *iface, int channel_id) +{ + struct aim_channel *c; + + if (!iface) { + pr_info("Bad interface pointer\n"); + return -EINVAL; + } + + c = get_channel(iface, channel_id); + if (!c) + return -ENXIO; + + mutex_lock(&c->io_mutex); + spin_lock(&c->unlink); + c->dev = NULL; + spin_unlock(&c->unlink); + destroy_cdev(c); + if (c->access_ref) { + stop_channel(c); + wake_up_interruptible(&c->wq); + mutex_unlock(&c->io_mutex); + } else { + mutex_unlock(&c->io_mutex); + destroy_channel(c); + } + return 0; +} + +/** + * aim_rx_completion - completion handler for rx channels + * @mbo: pointer to buffer object that has completed + * + * This searches for the channel linked to this MBO and stores it in the local + * fifo buffer. + */ +static int aim_rx_completion(struct mbo *mbo) +{ + struct aim_channel *c; + + if (!mbo) + return -EINVAL; + + c = get_channel(mbo->ifp, mbo->hdm_channel_id); + if (!c) + return -ENXIO; + + spin_lock(&c->unlink); + if (!c->access_ref || !c->dev) { + spin_unlock(&c->unlink); + return -ENODEV; + } + kfifo_in(&c->fifo, &mbo, 1); + spin_unlock(&c->unlink); +#ifdef DEBUG_MESG + if (kfifo_is_full(&c->fifo)) + pr_info("WARN: Fifo is full\n"); +#endif + wake_up_interruptible(&c->wq); + return 0; +} + +/** + * aim_tx_completion - completion handler for tx channels + * @iface: pointer to interface instance + * @channel_id: channel index/ID + * + * This wakes sleeping processes in the wait-queue. + */ +static int aim_tx_completion(struct most_interface *iface, int channel_id) +{ + struct aim_channel *c; + + if (!iface) { + pr_info("Bad interface pointer\n"); + return -EINVAL; + } + if ((channel_id < 0) || (channel_id >= iface->num_channels)) { + pr_info("Channel ID out of range\n"); + return -EINVAL; + } + + c = get_channel(iface, channel_id); + if (!c) + return -ENXIO; + wake_up_interruptible(&c->wq); + return 0; +} + +/** + * aim_probe - probe function of the driver module + * @iface: pointer to interface instance + * @channel_id: channel index/ID + * @cfg: pointer to actual channel configuration + * @parent: pointer to kobject (needed for sysfs hook-up) + * @name: name of the device to be created + * + * This allocates achannel object and creates the device node in /dev + * + * Returns 0 on success or error code otherwise. + */ +static int aim_probe(struct most_interface *iface, int channel_id, + struct most_channel_config *cfg, + struct kobject *parent, char *name) +{ + struct aim_channel *c; + unsigned long cl_flags; + int retval; + int current_minor; + + if ((!iface) || (!cfg) || (!parent) || (!name)) { + pr_info("Probing AIM with bad arguments"); + return -EINVAL; + } + c = get_channel(iface, channel_id); + if (c) + return -EEXIST; + + current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL); + if (current_minor < 0) + return current_minor; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) { + retval = -ENOMEM; + goto error_alloc_channel; + } + + c->devno = MKDEV(major, current_minor); + cdev_init(&c->cdev, &channel_fops); + c->cdev.owner = THIS_MODULE; + cdev_add(&c->cdev, c->devno, 1); + c->iface = iface; + c->cfg = cfg; + c->channel_id = channel_id; + c->access_ref = 0; + spin_lock_init(&c->unlink); + INIT_KFIFO(c->fifo); + retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); + if (retval) { + pr_info("failed to alloc channel kfifo"); + goto error_alloc_kfifo; + } + init_waitqueue_head(&c->wq); + mutex_init(&c->io_mutex); + spin_lock_irqsave(&ch_list_lock, cl_flags); + list_add_tail(&c->list, &channel_list); + spin_unlock_irqrestore(&ch_list_lock, cl_flags); + c->dev = device_create(aim_class, + NULL, + c->devno, + NULL, + "%s", name); + + if (IS_ERR(c->dev)) { + retval = PTR_ERR(c->dev); + pr_info("failed to create new device node %s\n", name); + goto error_create_device; + } + kobject_uevent(&c->dev->kobj, KOBJ_ADD); + return 0; + +error_create_device: + kfifo_free(&c->fifo); + list_del(&c->list); +error_alloc_kfifo: + cdev_del(&c->cdev); + kfree(c); +error_alloc_channel: + ida_simple_remove(&minor_id, current_minor); + return retval; +} + +static struct most_aim cdev_aim = { + .name = "cdev", + .probe_channel = aim_probe, + .disconnect_channel = aim_disconnect_channel, + .rx_completion = aim_rx_completion, + .tx_completion = aim_tx_completion, +}; + +static int __init mod_init(void) +{ + int err; + + pr_info("init()\n"); + + INIT_LIST_HEAD(&channel_list); + spin_lock_init(&ch_list_lock); + ida_init(&minor_id); + + err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev"); + if (err < 0) + goto dest_ida; + major = MAJOR(aim_devno); + + aim_class = class_create(THIS_MODULE, "most_cdev_aim"); + if (IS_ERR(aim_class)) { + pr_err("no udev support\n"); + err = PTR_ERR(aim_class); + goto free_cdev; + } + err = most_register_aim(&cdev_aim); + if (err) + goto dest_class; + return 0; + +dest_class: + class_destroy(aim_class); +free_cdev: + unregister_chrdev_region(aim_devno, 1); +dest_ida: + ida_destroy(&minor_id); + return err; +} + +static void __exit mod_exit(void) +{ + struct aim_channel *c, *tmp; + + pr_info("exit module\n"); + + most_deregister_aim(&cdev_aim); + + list_for_each_entry_safe(c, tmp, &channel_list, list) { + destroy_cdev(c); + destroy_channel(c); + } + class_destroy(aim_class); + unregister_chrdev_region(aim_devno, 1); + ida_destroy(&minor_id); +} + +module_init(mod_init); +module_exit(mod_exit); +MODULE_AUTHOR("Christian Gromm "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("character device AIM for mostcore"); -- cgit v1.2.3 From 77550c20121f07b0f2389c39e076e034660724e0 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:37 +0100 Subject: staging: most: i2c: rename module This patch renames the folder of the i2c module. It is needed to clear the directory layout. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Kconfig | 2 +- drivers/staging/most/hdm-i2c/Kconfig | 12 - drivers/staging/most/hdm-i2c/hdm_i2c.c | 417 --------------------------------- drivers/staging/most/i2c/Kconfig | 12 + drivers/staging/most/i2c/Makefile | 4 + drivers/staging/most/i2c/i2c.c | 417 +++++++++++++++++++++++++++++++++ 6 files changed, 434 insertions(+), 430 deletions(-) delete mode 100644 drivers/staging/most/hdm-i2c/Kconfig delete mode 100644 drivers/staging/most/hdm-i2c/hdm_i2c.c create mode 100644 drivers/staging/most/i2c/Kconfig create mode 100644 drivers/staging/most/i2c/Makefile create mode 100644 drivers/staging/most/i2c/i2c.c (limited to 'drivers') diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 60a2825e6076..b3393a5f5706 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -27,7 +27,7 @@ source "drivers/staging/most/aim-v4l2/Kconfig" source "drivers/staging/most/hdm-dim2/Kconfig" -source "drivers/staging/most/hdm-i2c/Kconfig" +source "drivers/staging/most/i2c/Kconfig" source "drivers/staging/most/hdm-usb/Kconfig" diff --git a/drivers/staging/most/hdm-i2c/Kconfig b/drivers/staging/most/hdm-i2c/Kconfig deleted file mode 100644 index 6fd7983668ad..000000000000 --- a/drivers/staging/most/hdm-i2c/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# -# MOST I2C configuration -# - -config HDM_I2C - tristate "I2C HDM" - depends on I2C - ---help--- - Say Y here if you want to connect via I2C to network tranceiver. - - To compile this driver as a module, choose M here: the - module will be called hdm_i2c. diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c deleted file mode 100644 index c73c76d0a6d5..000000000000 --- a/drivers/staging/most/hdm-i2c/hdm_i2c.c +++ /dev/null @@ -1,417 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * hdm_i2c.c - Hardware Dependent Module for I2C Interface - * - * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include - -#include "most/core.h" - -enum { CH_RX, CH_TX, NUM_CHANNELS }; - -#define MAX_BUFFERS_CONTROL 32 -#define MAX_BUF_SIZE_CONTROL 256 - -/** - * list_first_mbo - get the first mbo from a list - * @ptr: the list head to take the mbo from. - */ -#define list_first_mbo(ptr) \ - list_first_entry(ptr, struct mbo, list) - -/* IRQ / Polling option */ -static bool polling_req; -module_param(polling_req, bool, 0444); -MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); - -/* Polling Rate */ -static int scan_rate = 100; -module_param(scan_rate, int, 0644); -MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100"); - -struct hdm_i2c { - bool is_open[NUM_CHANNELS]; - bool polling_mode; - struct most_interface most_iface; - struct most_channel_capability capabilities[NUM_CHANNELS]; - struct i2c_client *client; - struct rx { - struct delayed_work dwork; - wait_queue_head_t waitq; - struct list_head list; - struct mutex list_mutex; - } rx; - char name[64]; -}; - -#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface) - -/** - * configure_channel - called from MOST core to configure a channel - * @iface: interface the channel belongs to - * @channel: channel to be configured - * @channel_config: structure that holds the configuration information - * - * Return 0 on success, negative on failure. - * - * Receives configuration information from MOST core and initialize the - * corresponding channel. - */ -static int configure_channel(struct most_interface *most_iface, - int ch_idx, - struct most_channel_config *channel_config) -{ - struct hdm_i2c *dev = to_hdm(most_iface); - - BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); - BUG_ON(dev->is_open[ch_idx]); - - if (channel_config->data_type != MOST_CH_CONTROL) { - pr_err("bad data type for channel %d\n", ch_idx); - return -EPERM; - } - - if (channel_config->direction != dev->capabilities[ch_idx].direction) { - pr_err("bad direction for channel %d\n", ch_idx); - return -EPERM; - } - - if ((channel_config->direction == MOST_CH_RX) && (dev->polling_mode)) { - schedule_delayed_work(&dev->rx.dwork, - msecs_to_jiffies(MSEC_PER_SEC / 4)); - } - dev->is_open[ch_idx] = true; - - return 0; -} - -/** - * enqueue - called from MOST core to enqueue a buffer for data transfer - * @iface: intended interface - * @channel: ID of the channel the buffer is intended for - * @mbo: pointer to the buffer object - * - * Return 0 on success, negative on failure. - * - * Transmit the data over I2C if it is a "write" request or push the buffer into - * list if it is an "read" request - */ -static int enqueue(struct most_interface *most_iface, - int ch_idx, struct mbo *mbo) -{ - struct hdm_i2c *dev = to_hdm(most_iface); - int ret; - - BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); - BUG_ON(!dev->is_open[ch_idx]); - - if (ch_idx == CH_RX) { - /* RX */ - mutex_lock(&dev->rx.list_mutex); - list_add_tail(&mbo->list, &dev->rx.list); - mutex_unlock(&dev->rx.list_mutex); - wake_up_interruptible(&dev->rx.waitq); - } else { - /* TX */ - ret = i2c_master_send(dev->client, mbo->virt_address, - mbo->buffer_length); - if (ret <= 0) { - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - } else { - mbo->processed_length = mbo->buffer_length; - mbo->status = MBO_SUCCESS; - } - mbo->complete(mbo); - } - - return 0; -} - -/** - * poison_channel - called from MOST core to poison buffers of a channel - * @iface: pointer to the interface the channel to be poisoned belongs to - * @channel_id: corresponding channel ID - * - * Return 0 on success, negative on failure. - * - * If channel direction is RX, complete the buffers in list with - * status MBO_E_CLOSE - */ -static int poison_channel(struct most_interface *most_iface, - int ch_idx) -{ - struct hdm_i2c *dev = to_hdm(most_iface); - struct mbo *mbo; - - BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); - BUG_ON(!dev->is_open[ch_idx]); - - dev->is_open[ch_idx] = false; - - if (ch_idx == CH_RX) { - mutex_lock(&dev->rx.list_mutex); - while (!list_empty(&dev->rx.list)) { - mbo = list_first_mbo(&dev->rx.list); - list_del(&mbo->list); - mutex_unlock(&dev->rx.list_mutex); - - mbo->processed_length = 0; - mbo->status = MBO_E_CLOSE; - mbo->complete(mbo); - - mutex_lock(&dev->rx.list_mutex); - } - mutex_unlock(&dev->rx.list_mutex); - wake_up_interruptible(&dev->rx.waitq); - } - - return 0; -} - -static void do_rx_work(struct hdm_i2c *dev) -{ - struct mbo *mbo; - unsigned char msg[MAX_BUF_SIZE_CONTROL]; - int ret, ch_idx = CH_RX; - u16 pml, data_size; - - /* Read PML (2 bytes) */ - ret = i2c_master_recv(dev->client, msg, 2); - if (ret <= 0) { - pr_err("Failed to receive PML\n"); - return; - } - - pml = (msg[0] << 8) | msg[1]; - if (!pml) - return; - - data_size = pml + 2; - - /* Read the whole message, including PML */ - ret = i2c_master_recv(dev->client, msg, data_size); - if (ret <= 0) { - pr_err("Failed to receive a Port Message\n"); - return; - } - - for (;;) { - /* Conditions to wait for: poisoned channel or free buffer - * available for reading - */ - if (wait_event_interruptible(dev->rx.waitq, - !dev->is_open[ch_idx] || - !list_empty(&dev->rx.list))) { - pr_err("wait_event_interruptible() failed\n"); - return; - } - - if (!dev->is_open[ch_idx]) - return; - - mutex_lock(&dev->rx.list_mutex); - - /* list may be empty if poison or remove is called */ - if (!list_empty(&dev->rx.list)) - break; - - mutex_unlock(&dev->rx.list_mutex); - } - - mbo = list_first_mbo(&dev->rx.list); - list_del(&mbo->list); - mutex_unlock(&dev->rx.list_mutex); - - mbo->processed_length = min(data_size, mbo->buffer_length); - memcpy(mbo->virt_address, msg, mbo->processed_length); - mbo->status = MBO_SUCCESS; - mbo->complete(mbo); -} - -/** - * pending_rx_work - Read pending messages through I2C - * @work: definition of this work item - * - * Invoked by the Interrupt Service Routine, most_irq_handler() - */ -static void pending_rx_work(struct work_struct *work) -{ - struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work); - - do_rx_work(dev); - - if (dev->polling_mode) { - if (dev->is_open[CH_RX]) - schedule_delayed_work(&dev->rx.dwork, - msecs_to_jiffies(MSEC_PER_SEC - / scan_rate)); - } else { - enable_irq(dev->client->irq); - } -} - -/* - * most_irq_handler - Interrupt Service Routine - * @irq: irq number - * @_dev: private data - * - * Schedules a delayed work - * - * By default the interrupt line behavior is Active Low. Once an interrupt is - * generated by the device, until driver clears the interrupt (by reading - * the PMP message), device keeps the interrupt line in low state. Since i2c - * read is done in work queue, the interrupt line must be disabled temporarily - * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue, - * after reading the message. - * - * Note: If we use the interrupt line in Falling edge mode, there is a - * possibility to miss interrupts when ISR is getting executed. - * - */ -static irqreturn_t most_irq_handler(int irq, void *_dev) -{ - struct hdm_i2c *dev = _dev; - - disable_irq_nosync(irq); - - schedule_delayed_work(&dev->rx.dwork, 0); - - return IRQ_HANDLED; -} - -/* - * i2c_probe - i2c probe handler - * @client: i2c client device structure - * @id: i2c client device id - * - * Return 0 on success, negative on failure. - * - * Register the i2c client device as a MOST interface - */ -static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct hdm_i2c *dev; - int ret, i; - struct kobject *kobj; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - /* ID format: i2c--
*/ - snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x", - client->adapter->nr, client->addr); - - for (i = 0; i < NUM_CHANNELS; i++) { - dev->is_open[i] = false; - dev->capabilities[i].data_type = MOST_CH_CONTROL; - dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL; - dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL; - } - dev->capabilities[CH_RX].direction = MOST_CH_RX; - dev->capabilities[CH_RX].name_suffix = "rx"; - dev->capabilities[CH_TX].direction = MOST_CH_TX; - dev->capabilities[CH_TX].name_suffix = "tx"; - - dev->most_iface.interface = ITYPE_I2C; - dev->most_iface.description = dev->name; - dev->most_iface.num_channels = NUM_CHANNELS; - dev->most_iface.channel_vector = dev->capabilities; - dev->most_iface.configure = configure_channel; - dev->most_iface.enqueue = enqueue; - dev->most_iface.poison_channel = poison_channel; - - INIT_LIST_HEAD(&dev->rx.list); - mutex_init(&dev->rx.list_mutex); - init_waitqueue_head(&dev->rx.waitq); - - INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work); - - dev->client = client; - i2c_set_clientdata(client, dev); - - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { - pr_err("Failed to register i2c as a MOST interface\n"); - kfree(dev); - return PTR_ERR(kobj); - } - - dev->polling_mode = polling_req || client->irq <= 0; - if (!dev->polling_mode) { - pr_info("Requesting IRQ: %d\n", client->irq); - ret = request_irq(client->irq, most_irq_handler, 0, - client->name, dev); - if (ret) { - pr_info("IRQ request failed: %d, falling back to polling\n", - ret); - dev->polling_mode = true; - } - } - - if (dev->polling_mode) - pr_info("Using polling at rate: %d times/sec\n", scan_rate); - - return 0; -} - -/* - * i2c_remove - i2c remove handler - * @client: i2c client device structure - * - * Return 0 on success. - * - * Unregister the i2c client device as a MOST interface - */ -static int i2c_remove(struct i2c_client *client) -{ - struct hdm_i2c *dev = i2c_get_clientdata(client); - int i; - - if (!dev->polling_mode) - free_irq(client->irq, dev); - - most_deregister_interface(&dev->most_iface); - - for (i = 0 ; i < NUM_CHANNELS; i++) - if (dev->is_open[i]) - poison_channel(&dev->most_iface, i); - cancel_delayed_work_sync(&dev->rx.dwork); - kfree(dev); - - return 0; -} - -static const struct i2c_device_id i2c_id[] = { - { "most_i2c", 0 }, - { }, /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(i2c, i2c_id); - -static struct i2c_driver i2c_driver = { - .driver = { - .name = "hdm_i2c", - }, - .probe = i2c_probe, - .remove = i2c_remove, - .id_table = i2c_id, -}; - -module_i2c_driver(i2c_driver); - -MODULE_AUTHOR("Jain Roy Ambi "); -MODULE_AUTHOR("Andrey Shvetsov "); -MODULE_DESCRIPTION("I2C Hardware Dependent Module"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/most/i2c/Kconfig b/drivers/staging/most/i2c/Kconfig new file mode 100644 index 000000000000..79d0ff27f56d --- /dev/null +++ b/drivers/staging/most/i2c/Kconfig @@ -0,0 +1,12 @@ +# +# MOST I2C configuration +# + +config MOST_I2C + tristate "I2C" + depends on I2C + ---help--- + Say Y here if you want to connect via I2C to network tranceiver. + + To compile this driver as a module, choose M here: the + module will be called most_i2c. diff --git a/drivers/staging/most/i2c/Makefile b/drivers/staging/most/i2c/Makefile new file mode 100644 index 000000000000..a7d094c1e1c2 --- /dev/null +++ b/drivers/staging/most/i2c/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_I2C) += most_i2c.o + +most_i2c-objs := i2c.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c new file mode 100644 index 000000000000..156b2b1bdba9 --- /dev/null +++ b/drivers/staging/most/i2c/i2c.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * i2c.c - Hardware Dependent Module for I2C Interface + * + * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include "most/core.h" + +enum { CH_RX, CH_TX, NUM_CHANNELS }; + +#define MAX_BUFFERS_CONTROL 32 +#define MAX_BUF_SIZE_CONTROL 256 + +/** + * list_first_mbo - get the first mbo from a list + * @ptr: the list head to take the mbo from. + */ +#define list_first_mbo(ptr) \ + list_first_entry(ptr, struct mbo, list) + +/* IRQ / Polling option */ +static bool polling_req; +module_param(polling_req, bool, 0444); +MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); + +/* Polling Rate */ +static int scan_rate = 100; +module_param(scan_rate, int, 0644); +MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100"); + +struct hdm_i2c { + bool is_open[NUM_CHANNELS]; + bool polling_mode; + struct most_interface most_iface; + struct most_channel_capability capabilities[NUM_CHANNELS]; + struct i2c_client *client; + struct rx { + struct delayed_work dwork; + wait_queue_head_t waitq; + struct list_head list; + struct mutex list_mutex; + } rx; + char name[64]; +}; + +#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface) + +/** + * configure_channel - called from MOST core to configure a channel + * @iface: interface the channel belongs to + * @channel: channel to be configured + * @channel_config: structure that holds the configuration information + * + * Return 0 on success, negative on failure. + * + * Receives configuration information from MOST core and initialize the + * corresponding channel. + */ +static int configure_channel(struct most_interface *most_iface, + int ch_idx, + struct most_channel_config *channel_config) +{ + struct hdm_i2c *dev = to_hdm(most_iface); + + BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); + BUG_ON(dev->is_open[ch_idx]); + + if (channel_config->data_type != MOST_CH_CONTROL) { + pr_err("bad data type for channel %d\n", ch_idx); + return -EPERM; + } + + if (channel_config->direction != dev->capabilities[ch_idx].direction) { + pr_err("bad direction for channel %d\n", ch_idx); + return -EPERM; + } + + if ((channel_config->direction == MOST_CH_RX) && (dev->polling_mode)) { + schedule_delayed_work(&dev->rx.dwork, + msecs_to_jiffies(MSEC_PER_SEC / 4)); + } + dev->is_open[ch_idx] = true; + + return 0; +} + +/** + * enqueue - called from MOST core to enqueue a buffer for data transfer + * @iface: intended interface + * @channel: ID of the channel the buffer is intended for + * @mbo: pointer to the buffer object + * + * Return 0 on success, negative on failure. + * + * Transmit the data over I2C if it is a "write" request or push the buffer into + * list if it is an "read" request + */ +static int enqueue(struct most_interface *most_iface, + int ch_idx, struct mbo *mbo) +{ + struct hdm_i2c *dev = to_hdm(most_iface); + int ret; + + BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); + BUG_ON(!dev->is_open[ch_idx]); + + if (ch_idx == CH_RX) { + /* RX */ + mutex_lock(&dev->rx.list_mutex); + list_add_tail(&mbo->list, &dev->rx.list); + mutex_unlock(&dev->rx.list_mutex); + wake_up_interruptible(&dev->rx.waitq); + } else { + /* TX */ + ret = i2c_master_send(dev->client, mbo->virt_address, + mbo->buffer_length); + if (ret <= 0) { + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + } else { + mbo->processed_length = mbo->buffer_length; + mbo->status = MBO_SUCCESS; + } + mbo->complete(mbo); + } + + return 0; +} + +/** + * poison_channel - called from MOST core to poison buffers of a channel + * @iface: pointer to the interface the channel to be poisoned belongs to + * @channel_id: corresponding channel ID + * + * Return 0 on success, negative on failure. + * + * If channel direction is RX, complete the buffers in list with + * status MBO_E_CLOSE + */ +static int poison_channel(struct most_interface *most_iface, + int ch_idx) +{ + struct hdm_i2c *dev = to_hdm(most_iface); + struct mbo *mbo; + + BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); + BUG_ON(!dev->is_open[ch_idx]); + + dev->is_open[ch_idx] = false; + + if (ch_idx == CH_RX) { + mutex_lock(&dev->rx.list_mutex); + while (!list_empty(&dev->rx.list)) { + mbo = list_first_mbo(&dev->rx.list); + list_del(&mbo->list); + mutex_unlock(&dev->rx.list_mutex); + + mbo->processed_length = 0; + mbo->status = MBO_E_CLOSE; + mbo->complete(mbo); + + mutex_lock(&dev->rx.list_mutex); + } + mutex_unlock(&dev->rx.list_mutex); + wake_up_interruptible(&dev->rx.waitq); + } + + return 0; +} + +static void do_rx_work(struct hdm_i2c *dev) +{ + struct mbo *mbo; + unsigned char msg[MAX_BUF_SIZE_CONTROL]; + int ret, ch_idx = CH_RX; + u16 pml, data_size; + + /* Read PML (2 bytes) */ + ret = i2c_master_recv(dev->client, msg, 2); + if (ret <= 0) { + pr_err("Failed to receive PML\n"); + return; + } + + pml = (msg[0] << 8) | msg[1]; + if (!pml) + return; + + data_size = pml + 2; + + /* Read the whole message, including PML */ + ret = i2c_master_recv(dev->client, msg, data_size); + if (ret <= 0) { + pr_err("Failed to receive a Port Message\n"); + return; + } + + for (;;) { + /* Conditions to wait for: poisoned channel or free buffer + * available for reading + */ + if (wait_event_interruptible(dev->rx.waitq, + !dev->is_open[ch_idx] || + !list_empty(&dev->rx.list))) { + pr_err("wait_event_interruptible() failed\n"); + return; + } + + if (!dev->is_open[ch_idx]) + return; + + mutex_lock(&dev->rx.list_mutex); + + /* list may be empty if poison or remove is called */ + if (!list_empty(&dev->rx.list)) + break; + + mutex_unlock(&dev->rx.list_mutex); + } + + mbo = list_first_mbo(&dev->rx.list); + list_del(&mbo->list); + mutex_unlock(&dev->rx.list_mutex); + + mbo->processed_length = min(data_size, mbo->buffer_length); + memcpy(mbo->virt_address, msg, mbo->processed_length); + mbo->status = MBO_SUCCESS; + mbo->complete(mbo); +} + +/** + * pending_rx_work - Read pending messages through I2C + * @work: definition of this work item + * + * Invoked by the Interrupt Service Routine, most_irq_handler() + */ +static void pending_rx_work(struct work_struct *work) +{ + struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work); + + do_rx_work(dev); + + if (dev->polling_mode) { + if (dev->is_open[CH_RX]) + schedule_delayed_work(&dev->rx.dwork, + msecs_to_jiffies(MSEC_PER_SEC + / scan_rate)); + } else { + enable_irq(dev->client->irq); + } +} + +/* + * most_irq_handler - Interrupt Service Routine + * @irq: irq number + * @_dev: private data + * + * Schedules a delayed work + * + * By default the interrupt line behavior is Active Low. Once an interrupt is + * generated by the device, until driver clears the interrupt (by reading + * the PMP message), device keeps the interrupt line in low state. Since i2c + * read is done in work queue, the interrupt line must be disabled temporarily + * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue, + * after reading the message. + * + * Note: If we use the interrupt line in Falling edge mode, there is a + * possibility to miss interrupts when ISR is getting executed. + * + */ +static irqreturn_t most_irq_handler(int irq, void *_dev) +{ + struct hdm_i2c *dev = _dev; + + disable_irq_nosync(irq); + + schedule_delayed_work(&dev->rx.dwork, 0); + + return IRQ_HANDLED; +} + +/* + * i2c_probe - i2c probe handler + * @client: i2c client device structure + * @id: i2c client device id + * + * Return 0 on success, negative on failure. + * + * Register the i2c client device as a MOST interface + */ +static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct hdm_i2c *dev; + int ret, i; + struct kobject *kobj; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + /* ID format: i2c--
*/ + snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x", + client->adapter->nr, client->addr); + + for (i = 0; i < NUM_CHANNELS; i++) { + dev->is_open[i] = false; + dev->capabilities[i].data_type = MOST_CH_CONTROL; + dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL; + dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL; + } + dev->capabilities[CH_RX].direction = MOST_CH_RX; + dev->capabilities[CH_RX].name_suffix = "rx"; + dev->capabilities[CH_TX].direction = MOST_CH_TX; + dev->capabilities[CH_TX].name_suffix = "tx"; + + dev->most_iface.interface = ITYPE_I2C; + dev->most_iface.description = dev->name; + dev->most_iface.num_channels = NUM_CHANNELS; + dev->most_iface.channel_vector = dev->capabilities; + dev->most_iface.configure = configure_channel; + dev->most_iface.enqueue = enqueue; + dev->most_iface.poison_channel = poison_channel; + + INIT_LIST_HEAD(&dev->rx.list); + mutex_init(&dev->rx.list_mutex); + init_waitqueue_head(&dev->rx.waitq); + + INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work); + + dev->client = client; + i2c_set_clientdata(client, dev); + + kobj = most_register_interface(&dev->most_iface); + if (IS_ERR(kobj)) { + pr_err("Failed to register i2c as a MOST interface\n"); + kfree(dev); + return PTR_ERR(kobj); + } + + dev->polling_mode = polling_req || client->irq <= 0; + if (!dev->polling_mode) { + pr_info("Requesting IRQ: %d\n", client->irq); + ret = request_irq(client->irq, most_irq_handler, 0, + client->name, dev); + if (ret) { + pr_info("IRQ request failed: %d, falling back to polling\n", + ret); + dev->polling_mode = true; + } + } + + if (dev->polling_mode) + pr_info("Using polling at rate: %d times/sec\n", scan_rate); + + return 0; +} + +/* + * i2c_remove - i2c remove handler + * @client: i2c client device structure + * + * Return 0 on success. + * + * Unregister the i2c client device as a MOST interface + */ +static int i2c_remove(struct i2c_client *client) +{ + struct hdm_i2c *dev = i2c_get_clientdata(client); + int i; + + if (!dev->polling_mode) + free_irq(client->irq, dev); + + most_deregister_interface(&dev->most_iface); + + for (i = 0 ; i < NUM_CHANNELS; i++) + if (dev->is_open[i]) + poison_channel(&dev->most_iface, i); + cancel_delayed_work_sync(&dev->rx.dwork); + kfree(dev); + + return 0; +} + +static const struct i2c_device_id i2c_id[] = { + { "most_i2c", 0 }, + { }, /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(i2c, i2c_id); + +static struct i2c_driver i2c_driver = { + .driver = { + .name = "hdm_i2c", + }, + .probe = i2c_probe, + .remove = i2c_remove, + .id_table = i2c_id, +}; + +module_i2c_driver(i2c_driver); + +MODULE_AUTHOR("Jain Roy Ambi "); +MODULE_AUTHOR("Andrey Shvetsov "); +MODULE_DESCRIPTION("I2C Hardware Dependent Module"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 9249c6a6d3560f09cddd04e2fda856f237b64987 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:38 +0100 Subject: staging: most: dim2: rename module This patch renames the folder and source files of the dim2 module. It is needed to clear the directory layout of the driver. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Kconfig | 2 +- drivers/staging/most/dim2/Kconfig | 16 + drivers/staging/most/dim2/Makefile | 4 + drivers/staging/most/dim2/dim2.c | 912 ++++++++++++++++++++++++++ drivers/staging/most/dim2/dim2.h | 21 + drivers/staging/most/dim2/errors.h | 51 ++ drivers/staging/most/dim2/hal.c | 979 ++++++++++++++++++++++++++++ drivers/staging/most/dim2/hal.h | 106 +++ drivers/staging/most/dim2/reg.h | 157 +++++ drivers/staging/most/dim2/sysfs.c | 109 ++++ drivers/staging/most/dim2/sysfs.h | 30 + drivers/staging/most/hdm-dim2/Kconfig | 16 - drivers/staging/most/hdm-dim2/dim2_errors.h | 51 -- drivers/staging/most/hdm-dim2/dim2_hal.c | 979 ---------------------------- drivers/staging/most/hdm-dim2/dim2_hal.h | 106 --- drivers/staging/most/hdm-dim2/dim2_hdm.c | 912 -------------------------- drivers/staging/most/hdm-dim2/dim2_hdm.h | 21 - drivers/staging/most/hdm-dim2/dim2_reg.h | 157 ----- drivers/staging/most/hdm-dim2/dim2_sysfs.c | 109 ---- drivers/staging/most/hdm-dim2/dim2_sysfs.h | 30 - 20 files changed, 2386 insertions(+), 2382 deletions(-) create mode 100644 drivers/staging/most/dim2/Kconfig create mode 100644 drivers/staging/most/dim2/Makefile create mode 100644 drivers/staging/most/dim2/dim2.c create mode 100644 drivers/staging/most/dim2/dim2.h create mode 100644 drivers/staging/most/dim2/errors.h create mode 100644 drivers/staging/most/dim2/hal.c create mode 100644 drivers/staging/most/dim2/hal.h create mode 100644 drivers/staging/most/dim2/reg.h create mode 100644 drivers/staging/most/dim2/sysfs.c create mode 100644 drivers/staging/most/dim2/sysfs.h delete mode 100644 drivers/staging/most/hdm-dim2/Kconfig delete mode 100644 drivers/staging/most/hdm-dim2/dim2_errors.h delete mode 100644 drivers/staging/most/hdm-dim2/dim2_hal.c delete mode 100644 drivers/staging/most/hdm-dim2/dim2_hal.h delete mode 100644 drivers/staging/most/hdm-dim2/dim2_hdm.c delete mode 100644 drivers/staging/most/hdm-dim2/dim2_hdm.h delete mode 100644 drivers/staging/most/hdm-dim2/dim2_reg.h delete mode 100644 drivers/staging/most/hdm-dim2/dim2_sysfs.c delete mode 100644 drivers/staging/most/hdm-dim2/dim2_sysfs.h (limited to 'drivers') diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index b3393a5f5706..88a415b8d07a 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -25,7 +25,7 @@ source "drivers/staging/most/aim-sound/Kconfig" source "drivers/staging/most/aim-v4l2/Kconfig" -source "drivers/staging/most/hdm-dim2/Kconfig" +source "drivers/staging/most/dim2/Kconfig" source "drivers/staging/most/i2c/Kconfig" diff --git a/drivers/staging/most/dim2/Kconfig b/drivers/staging/most/dim2/Kconfig new file mode 100644 index 000000000000..e39c4e525cac --- /dev/null +++ b/drivers/staging/most/dim2/Kconfig @@ -0,0 +1,16 @@ +# +# MediaLB configuration +# + +config MOST_DIM2 + tristate "DIM2" + depends on HAS_IOMEM + + ---help--- + Say Y here if you want to connect via MediaLB to network transceiver. + This device driver is platform dependent and needs an additional + platform driver to be installed. For more information contact + maintainer of this driver. + + To compile this driver as a module, choose M here: the + module will be called most_dim2. diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile new file mode 100644 index 000000000000..66676f5907ee --- /dev/null +++ b/drivers/staging/most/dim2/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_DIM2) += most_dim2.o + +most_dim2-objs := dim2.o hal.o sysfs.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c new file mode 100644 index 000000000000..921db9880d80 --- /dev/null +++ b/drivers/staging/most/dim2/dim2.c @@ -0,0 +1,912 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * dim2.c - MediaLB DIM2 Hardware Dependent Module + * + * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "most/core.h" +#include "hal.h" +#include "dim2.h" +#include "errors.h" +#include "sysfs.h" + +#define DMA_CHANNELS (32 - 1) /* channel 0 is a system channel */ + +#define MAX_BUFFERS_PACKET 32 +#define MAX_BUFFERS_STREAMING 32 +#define MAX_BUF_SIZE_PACKET 2048 +#define MAX_BUF_SIZE_STREAMING (8 * 1024) + +/* command line parameter to select clock speed */ +static char *clock_speed; +module_param(clock_speed, charp, 0000); +MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed"); + +/* + * The parameter representing the number of frames per sub-buffer for + * synchronous channels. Valid values: [0 .. 6]. + * + * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per + * sub-buffer 1, 2, 4, 8, 16, 32, 64. + */ +static u8 fcnt = 4; /* (1 << fcnt) frames per subbuffer */ +module_param(fcnt, byte, 0000); +MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2"); + +static DEFINE_SPINLOCK(dim_lock); + +static void dim2_tasklet_fn(unsigned long data); +static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0); + +/** + * struct hdm_channel - private structure to keep channel specific data + * @is_initialized: identifier to know whether the channel is initialized + * @ch: HAL specific channel data + * @pending_list: list to keep MBO's before starting transfer + * @started_list: list to keep MBO's after starting transfer + * @direction: channel direction (TX or RX) + * @data_type: channel data type + */ +struct hdm_channel { + char name[sizeof "caNNN"]; + bool is_initialized; + struct dim_channel ch; + struct list_head pending_list; /* before dim_enqueue_buffer() */ + struct list_head started_list; /* after dim_enqueue_buffer() */ + enum most_channel_direction direction; + enum most_channel_data_type data_type; +}; + +/** + * struct dim2_hdm - private structure to keep interface specific data + * @hch: an array of channel specific data + * @most_iface: most interface structure + * @capabilities: an array of channel capability data + * @io_base: I/O register base address + * @clk_speed: user selectable (through command line parameter) clock speed + * @netinfo_task: thread to deliver network status + * @netinfo_waitq: waitq for the thread to sleep + * @deliver_netinfo: to identify whether network status received + * @mac_addrs: INIC mac address + * @link_state: network link state + * @atx_idx: index of async tx channel + */ +struct dim2_hdm { + struct hdm_channel hch[DMA_CHANNELS]; + struct most_channel_capability capabilities[DMA_CHANNELS]; + struct most_interface most_iface; + char name[16 + sizeof "dim2-"]; + void __iomem *io_base; + int clk_speed; + struct task_struct *netinfo_task; + wait_queue_head_t netinfo_waitq; + int deliver_netinfo; + unsigned char mac_addrs[6]; + unsigned char link_state; + int atx_idx; + struct medialb_bus bus; + void (*on_netinfo)(struct most_interface *, + unsigned char, unsigned char *); +}; + +#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface) + +/* Macro to identify a network status message */ +#define PACKET_IS_NET_INFO(p) \ + (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ + ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) + +bool dim2_sysfs_get_state_cb(void) +{ + bool state; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + state = dim_get_lock_state(); + spin_unlock_irqrestore(&dim_lock, flags); + + return state; +} + +/** + * dimcb_io_read - callback from HAL to read an I/O register + * @ptr32: register address + */ +u32 dimcb_io_read(u32 __iomem *ptr32) +{ + return readl(ptr32); +} + +/** + * dimcb_io_write - callback from HAL to write value to an I/O register + * @ptr32: register address + * @value: value to write + */ +void dimcb_io_write(u32 __iomem *ptr32, u32 value) +{ + writel(value, ptr32); +} + +/** + * dimcb_on_error - callback from HAL to report miscommunication between + * HDM and HAL + * @error_id: Error ID + * @error_message: Error message. Some text in a free format + */ +void dimcb_on_error(u8 error_id, const char *error_message) +{ + pr_err("dimcb_on_error: error_id - %d, error_message - %s\n", error_id, + error_message); +} + +/** + * startup_dim - initialize the dim2 interface + * @pdev: platform device + * + * Get the value of command line parameter "clock_speed" if given or use the + * default value, enable the clock and PLL, and initialize the dim2 interface. + */ +static int startup_dim(struct platform_device *pdev) +{ + struct dim2_hdm *dev = platform_get_drvdata(pdev); + struct dim2_platform_data *pdata = pdev->dev.platform_data; + u8 hal_ret; + + dev->clk_speed = -1; + + if (clock_speed) { + if (!strcmp(clock_speed, "256fs")) + dev->clk_speed = CLK_256FS; + else if (!strcmp(clock_speed, "512fs")) + dev->clk_speed = CLK_512FS; + else if (!strcmp(clock_speed, "1024fs")) + dev->clk_speed = CLK_1024FS; + else if (!strcmp(clock_speed, "2048fs")) + dev->clk_speed = CLK_2048FS; + else if (!strcmp(clock_speed, "3072fs")) + dev->clk_speed = CLK_3072FS; + else if (!strcmp(clock_speed, "4096fs")) + dev->clk_speed = CLK_4096FS; + else if (!strcmp(clock_speed, "6144fs")) + dev->clk_speed = CLK_6144FS; + else if (!strcmp(clock_speed, "8192fs")) + dev->clk_speed = CLK_8192FS; + } + + if (dev->clk_speed == -1) { + pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n"); + dev->clk_speed = CLK_3072FS; + } else { + pr_info("Selected clock speed: %s\n", clock_speed); + } + if (pdata && pdata->init) { + int ret = pdata->init(pdata, dev->io_base, dev->clk_speed); + + if (ret) + return ret; + } + + pr_info("sync: num of frames per sub-buffer: %u\n", fcnt); + hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); + if (hal_ret != DIM_NO_ERROR) { + pr_err("dim_startup failed: %d\n", hal_ret); + if (pdata && pdata->destroy) + pdata->destroy(pdata); + return -ENODEV; + } + + return 0; +} + +/** + * try_start_dim_transfer - try to transfer a buffer on a channel + * @hdm_ch: channel specific data + * + * Transfer a buffer from pending_list if the channel is ready + */ +static int try_start_dim_transfer(struct hdm_channel *hdm_ch) +{ + u16 buf_size; + struct list_head *head = &hdm_ch->pending_list; + struct mbo *mbo; + unsigned long flags; + struct dim_ch_state_t st; + + BUG_ON(!hdm_ch); + BUG_ON(!hdm_ch->is_initialized); + + spin_lock_irqsave(&dim_lock, flags); + if (list_empty(head)) { + spin_unlock_irqrestore(&dim_lock, flags); + return -EAGAIN; + } + + if (!dim_get_channel_state(&hdm_ch->ch, &st)->ready) { + spin_unlock_irqrestore(&dim_lock, flags); + return -EAGAIN; + } + + mbo = list_first_entry(head, struct mbo, list); + buf_size = mbo->buffer_length; + + if (dim_dbr_space(&hdm_ch->ch) < buf_size) { + spin_unlock_irqrestore(&dim_lock, flags); + return -EAGAIN; + } + + BUG_ON(mbo->bus_address == 0); + if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) { + list_del(head->next); + spin_unlock_irqrestore(&dim_lock, flags); + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + mbo->complete(mbo); + return -EFAULT; + } + + list_move_tail(head->next, &hdm_ch->started_list); + spin_unlock_irqrestore(&dim_lock, flags); + + return 0; +} + +/** + * deliver_netinfo_thread - thread to deliver network status to mostcore + * @data: private data + * + * Wait for network status and deliver it to mostcore once it is received + */ +static int deliver_netinfo_thread(void *data) +{ + struct dim2_hdm *dev = data; + + while (!kthread_should_stop()) { + wait_event_interruptible(dev->netinfo_waitq, + dev->deliver_netinfo || + kthread_should_stop()); + + if (dev->deliver_netinfo) { + dev->deliver_netinfo--; + if (dev->on_netinfo) { + dev->on_netinfo(&dev->most_iface, + dev->link_state, + dev->mac_addrs); + } + } + } + + return 0; +} + +/** + * retrieve_netinfo - retrieve network status from received buffer + * @dev: private data + * @mbo: received MBO + * + * Parse the message in buffer and get node address, link state, MAC address. + * Wake up a thread to deliver this status to mostcore + */ +static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo) +{ + u8 *data = mbo->virt_address; + + pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]); + dev->link_state = data[18]; + pr_info("NIState: %d\n", dev->link_state); + memcpy(dev->mac_addrs, data + 19, 6); + dev->deliver_netinfo++; + wake_up_interruptible(&dev->netinfo_waitq); +} + +/** + * service_done_flag - handle completed buffers + * @dev: private data + * @ch_idx: channel index + * + * Return back the completed buffers to mostcore, using completion callback + */ +static void service_done_flag(struct dim2_hdm *dev, int ch_idx) +{ + struct hdm_channel *hdm_ch = dev->hch + ch_idx; + struct dim_ch_state_t st; + struct list_head *head; + struct mbo *mbo; + int done_buffers; + unsigned long flags; + u8 *data; + + BUG_ON(!hdm_ch); + BUG_ON(!hdm_ch->is_initialized); + + spin_lock_irqsave(&dim_lock, flags); + + done_buffers = dim_get_channel_state(&hdm_ch->ch, &st)->done_buffers; + if (!done_buffers) { + spin_unlock_irqrestore(&dim_lock, flags); + return; + } + + if (!dim_detach_buffers(&hdm_ch->ch, done_buffers)) { + spin_unlock_irqrestore(&dim_lock, flags); + return; + } + spin_unlock_irqrestore(&dim_lock, flags); + + head = &hdm_ch->started_list; + + while (done_buffers) { + spin_lock_irqsave(&dim_lock, flags); + if (list_empty(head)) { + spin_unlock_irqrestore(&dim_lock, flags); + pr_crit("hard error: started_mbo list is empty whereas DIM2 has sent buffers\n"); + break; + } + + mbo = list_first_entry(head, struct mbo, list); + list_del(head->next); + spin_unlock_irqrestore(&dim_lock, flags); + + data = mbo->virt_address; + + if (hdm_ch->data_type == MOST_CH_ASYNC && + hdm_ch->direction == MOST_CH_RX && + PACKET_IS_NET_INFO(data)) { + retrieve_netinfo(dev, mbo); + + spin_lock_irqsave(&dim_lock, flags); + list_add_tail(&mbo->list, &hdm_ch->pending_list); + spin_unlock_irqrestore(&dim_lock, flags); + } else { + if (hdm_ch->data_type == MOST_CH_CONTROL || + hdm_ch->data_type == MOST_CH_ASYNC) { + u32 const data_size = + (u32)data[0] * 256 + data[1] + 2; + + mbo->processed_length = + min_t(u32, data_size, + mbo->buffer_length); + } else { + mbo->processed_length = mbo->buffer_length; + } + mbo->status = MBO_SUCCESS; + mbo->complete(mbo); + } + + done_buffers--; + } +} + +static struct dim_channel **get_active_channels(struct dim2_hdm *dev, + struct dim_channel **buffer) +{ + int idx = 0; + int ch_idx; + + for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) { + if (dev->hch[ch_idx].is_initialized) + buffer[idx++] = &dev->hch[ch_idx].ch; + } + buffer[idx++] = NULL; + + return buffer; +} + +static irqreturn_t dim2_mlb_isr(int irq, void *_dev) +{ + struct dim2_hdm *dev = _dev; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + dim_service_mlb_int_irq(); + spin_unlock_irqrestore(&dim_lock, flags); + + if (dev->atx_idx >= 0 && dev->hch[dev->atx_idx].is_initialized) + while (!try_start_dim_transfer(dev->hch + dev->atx_idx)) + continue; + + return IRQ_HANDLED; +} + +/** + * dim2_tasklet_fn - tasklet function + * @data: private data + * + * Service each initialized channel, if needed + */ +static void dim2_tasklet_fn(unsigned long data) +{ + struct dim2_hdm *dev = (struct dim2_hdm *)data; + unsigned long flags; + int ch_idx; + + for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) { + if (!dev->hch[ch_idx].is_initialized) + continue; + + spin_lock_irqsave(&dim_lock, flags); + dim_service_channel(&dev->hch[ch_idx].ch); + spin_unlock_irqrestore(&dim_lock, flags); + + service_done_flag(dev, ch_idx); + while (!try_start_dim_transfer(dev->hch + ch_idx)) + continue; + } +} + +/** + * dim2_ahb_isr - interrupt service routine + * @irq: irq number + * @_dev: private data + * + * Acknowledge the interrupt and schedule a tasklet to service channels. + * Return IRQ_HANDLED. + */ +static irqreturn_t dim2_ahb_isr(int irq, void *_dev) +{ + struct dim2_hdm *dev = _dev; + struct dim_channel *buffer[DMA_CHANNELS + 1]; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + dim_service_ahb_int_irq(get_active_channels(dev, buffer)); + spin_unlock_irqrestore(&dim_lock, flags); + + dim2_tasklet.data = (unsigned long)dev; + tasklet_schedule(&dim2_tasklet); + return IRQ_HANDLED; +} + +/** + * complete_all_mbos - complete MBO's in a list + * @head: list head + * + * Delete all the entries in list and return back MBO's to mostcore using + * completion call back. + */ +static void complete_all_mbos(struct list_head *head) +{ + unsigned long flags; + struct mbo *mbo; + + for (;;) { + spin_lock_irqsave(&dim_lock, flags); + if (list_empty(head)) { + spin_unlock_irqrestore(&dim_lock, flags); + break; + } + + mbo = list_first_entry(head, struct mbo, list); + list_del(head->next); + spin_unlock_irqrestore(&dim_lock, flags); + + mbo->processed_length = 0; + mbo->status = MBO_E_CLOSE; + mbo->complete(mbo); + } +} + +/** + * configure_channel - initialize a channel + * @iface: interface the channel belongs to + * @channel: channel to be configured + * @channel_config: structure that holds the configuration information + * + * Receives configuration information from mostcore and initialize + * the corresponding channel. Return 0 on success, negative on failure. + */ +static int configure_channel(struct most_interface *most_iface, int ch_idx, + struct most_channel_config *ccfg) +{ + struct dim2_hdm *dev = iface_to_hdm(most_iface); + bool const is_tx = ccfg->direction == MOST_CH_TX; + u16 const sub_size = ccfg->subbuffer_size; + u16 const buf_size = ccfg->buffer_size; + u16 new_size; + unsigned long flags; + u8 hal_ret; + int const ch_addr = ch_idx * 2 + 2; + struct hdm_channel *const hdm_ch = dev->hch + ch_idx; + + BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); + + if (hdm_ch->is_initialized) + return -EPERM; + + switch (ccfg->data_type) { + case MOST_CH_CONTROL: + new_size = dim_norm_ctrl_async_buffer_size(buf_size); + if (new_size == 0) { + pr_err("%s: too small buffer size\n", hdm_ch->name); + return -EINVAL; + } + ccfg->buffer_size = new_size; + if (new_size != buf_size) + pr_warn("%s: fixed buffer size (%d -> %d)\n", + hdm_ch->name, buf_size, new_size); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr, + is_tx ? new_size * 2 : new_size); + break; + case MOST_CH_ASYNC: + new_size = dim_norm_ctrl_async_buffer_size(buf_size); + if (new_size == 0) { + pr_err("%s: too small buffer size\n", hdm_ch->name); + return -EINVAL; + } + ccfg->buffer_size = new_size; + if (new_size != buf_size) + pr_warn("%s: fixed buffer size (%d -> %d)\n", + hdm_ch->name, buf_size, new_size); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, + is_tx ? new_size * 2 : new_size); + break; + case MOST_CH_ISOC: + new_size = dim_norm_isoc_buffer_size(buf_size, sub_size); + if (new_size == 0) { + pr_err("%s: invalid sub-buffer size or too small buffer size\n", + hdm_ch->name); + return -EINVAL; + } + ccfg->buffer_size = new_size; + if (new_size != buf_size) + pr_warn("%s: fixed buffer size (%d -> %d)\n", + hdm_ch->name, buf_size, new_size); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = dim_init_isoc(&hdm_ch->ch, is_tx, ch_addr, sub_size); + break; + case MOST_CH_SYNC: + new_size = dim_norm_sync_buffer_size(buf_size, sub_size); + if (new_size == 0) { + pr_err("%s: invalid sub-buffer size or too small buffer size\n", + hdm_ch->name); + return -EINVAL; + } + ccfg->buffer_size = new_size; + if (new_size != buf_size) + pr_warn("%s: fixed buffer size (%d -> %d)\n", + hdm_ch->name, buf_size, new_size); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = dim_init_sync(&hdm_ch->ch, is_tx, ch_addr, sub_size); + break; + default: + pr_err("%s: configure failed, bad channel type: %d\n", + hdm_ch->name, ccfg->data_type); + return -EINVAL; + } + + if (hal_ret != DIM_NO_ERROR) { + spin_unlock_irqrestore(&dim_lock, flags); + pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n", + hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx); + return -ENODEV; + } + + hdm_ch->data_type = ccfg->data_type; + hdm_ch->direction = ccfg->direction; + hdm_ch->is_initialized = true; + + if (hdm_ch->data_type == MOST_CH_ASYNC && + hdm_ch->direction == MOST_CH_TX && + dev->atx_idx < 0) + dev->atx_idx = ch_idx; + + spin_unlock_irqrestore(&dim_lock, flags); + + return 0; +} + +/** + * enqueue - enqueue a buffer for data transfer + * @iface: intended interface + * @channel: ID of the channel the buffer is intended for + * @mbo: pointer to the buffer object + * + * Push the buffer into pending_list and try to transfer one buffer from + * pending_list. Return 0 on success, negative on failure. + */ +static int enqueue(struct most_interface *most_iface, int ch_idx, + struct mbo *mbo) +{ + struct dim2_hdm *dev = iface_to_hdm(most_iface); + struct hdm_channel *hdm_ch = dev->hch + ch_idx; + unsigned long flags; + + BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); + + if (!hdm_ch->is_initialized) + return -EPERM; + + if (mbo->bus_address == 0) + return -EFAULT; + + spin_lock_irqsave(&dim_lock, flags); + list_add_tail(&mbo->list, &hdm_ch->pending_list); + spin_unlock_irqrestore(&dim_lock, flags); + + (void)try_start_dim_transfer(hdm_ch); + + return 0; +} + +/** + * request_netinfo - triggers retrieving of network info + * @iface: pointer to the interface + * @channel_id: corresponding channel ID + * + * Send a command to INIC which triggers retrieving of network info by means of + * "Message exchange over MDP/MEP". Return 0 on success, negative on failure. + */ +static void request_netinfo(struct most_interface *most_iface, int ch_idx, + void (*on_netinfo)(struct most_interface *, + unsigned char, unsigned char *)) +{ + struct dim2_hdm *dev = iface_to_hdm(most_iface); + struct mbo *mbo; + u8 *data; + + dev->on_netinfo = on_netinfo; + if (!on_netinfo) + return; + + if (dev->atx_idx < 0) { + pr_err("Async Tx Not initialized\n"); + return; + } + + mbo = most_get_mbo(&dev->most_iface, dev->atx_idx, NULL); + if (!mbo) + return; + + mbo->buffer_length = 5; + + data = mbo->virt_address; + + data[0] = 0x00; /* PML High byte */ + data[1] = 0x03; /* PML Low byte */ + data[2] = 0x02; /* PMHL */ + data[3] = 0x08; /* FPH */ + data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */ + + most_submit_mbo(mbo); +} + +/** + * poison_channel - poison buffers of a channel + * @iface: pointer to the interface the channel to be poisoned belongs to + * @channel_id: corresponding channel ID + * + * Destroy a channel and complete all the buffers in both started_list & + * pending_list. Return 0 on success, negative on failure. + */ +static int poison_channel(struct most_interface *most_iface, int ch_idx) +{ + struct dim2_hdm *dev = iface_to_hdm(most_iface); + struct hdm_channel *hdm_ch = dev->hch + ch_idx; + unsigned long flags; + u8 hal_ret; + int ret = 0; + + BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); + + if (!hdm_ch->is_initialized) + return -EPERM; + + tasklet_disable(&dim2_tasklet); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = dim_destroy_channel(&hdm_ch->ch); + hdm_ch->is_initialized = false; + if (ch_idx == dev->atx_idx) + dev->atx_idx = -1; + spin_unlock_irqrestore(&dim_lock, flags); + tasklet_enable(&dim2_tasklet); + if (hal_ret != DIM_NO_ERROR) { + pr_err("HAL Failed to close channel %s\n", hdm_ch->name); + ret = -EFAULT; + } + + complete_all_mbos(&hdm_ch->started_list); + complete_all_mbos(&hdm_ch->pending_list); + + return ret; +} + +/* + * dim2_probe - dim2 probe handler + * @pdev: platform device structure + * + * Register the dim2 interface with mostcore and initialize it. + * Return 0 on success, negative on failure. + */ +static int dim2_probe(struct platform_device *pdev) +{ + struct dim2_hdm *dev; + struct resource *res; + int ret, i; + struct kobject *kobj; + int irq; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->atx_idx = -1; + + platform_set_drvdata(pdev, dev); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dev->io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->io_base)) + return PTR_ERR(dev->io_base); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq); + return irq; + } + + ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0, + "dim2_ahb0_int", dev); + if (ret) { + dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq); + return ret; + } + + irq = platform_get_irq(pdev, 1); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq); + return irq; + } + + ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0, + "dim2_mlb_int", dev); + if (ret) { + dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq); + return ret; + } + + init_waitqueue_head(&dev->netinfo_waitq); + dev->deliver_netinfo = 0; + dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev, + "dim2_netinfo"); + if (IS_ERR(dev->netinfo_task)) + return PTR_ERR(dev->netinfo_task); + + for (i = 0; i < DMA_CHANNELS; i++) { + struct most_channel_capability *cap = dev->capabilities + i; + struct hdm_channel *hdm_ch = dev->hch + i; + + INIT_LIST_HEAD(&hdm_ch->pending_list); + INIT_LIST_HEAD(&hdm_ch->started_list); + hdm_ch->is_initialized = false; + snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2); + + cap->name_suffix = hdm_ch->name; + cap->direction = MOST_CH_RX | MOST_CH_TX; + cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | + MOST_CH_ISOC | MOST_CH_SYNC; + cap->num_buffers_packet = MAX_BUFFERS_PACKET; + cap->buffer_size_packet = MAX_BUF_SIZE_PACKET; + cap->num_buffers_streaming = MAX_BUFFERS_STREAMING; + cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING; + } + + { + const char *fmt; + + if (sizeof(res->start) == sizeof(long long)) + fmt = "dim2-%016llx"; + else if (sizeof(res->start) == sizeof(long)) + fmt = "dim2-%016lx"; + else + fmt = "dim2-%016x"; + + snprintf(dev->name, sizeof(dev->name), fmt, res->start); + } + + dev->most_iface.interface = ITYPE_MEDIALB_DIM2; + dev->most_iface.description = dev->name; + dev->most_iface.num_channels = DMA_CHANNELS; + dev->most_iface.channel_vector = dev->capabilities; + dev->most_iface.configure = configure_channel; + dev->most_iface.enqueue = enqueue; + dev->most_iface.poison_channel = poison_channel; + dev->most_iface.request_netinfo = request_netinfo; + + kobj = most_register_interface(&dev->most_iface); + if (IS_ERR(kobj)) { + ret = PTR_ERR(kobj); + dev_err(&pdev->dev, "failed to register MOST interface\n"); + goto err_stop_thread; + } + + ret = dim2_sysfs_probe(&dev->bus, kobj); + if (ret) + goto err_unreg_iface; + + ret = startup_dim(pdev); + if (ret) { + dev_err(&pdev->dev, "failed to initialize DIM2\n"); + goto err_destroy_bus; + } + + return 0; + +err_destroy_bus: + dim2_sysfs_destroy(&dev->bus); +err_unreg_iface: + most_deregister_interface(&dev->most_iface); +err_stop_thread: + kthread_stop(dev->netinfo_task); + + return ret; +} + +/** + * dim2_remove - dim2 remove handler + * @pdev: platform device structure + * + * Unregister the interface from mostcore + */ +static int dim2_remove(struct platform_device *pdev) +{ + struct dim2_hdm *dev = platform_get_drvdata(pdev); + struct dim2_platform_data *pdata = pdev->dev.platform_data; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + dim_shutdown(); + spin_unlock_irqrestore(&dim_lock, flags); + + if (pdata && pdata->destroy) + pdata->destroy(pdata); + + dim2_sysfs_destroy(&dev->bus); + most_deregister_interface(&dev->most_iface); + kthread_stop(dev->netinfo_task); + + /* + * break link to local platform_device_id struct + * to prevent crash by unload platform device module + */ + pdev->id_entry = NULL; + + return 0; +} + +static const struct platform_device_id dim2_id[] = { + { "medialb_dim2" }, + { }, /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(platform, dim2_id); + +static struct platform_driver dim2_driver = { + .probe = dim2_probe, + .remove = dim2_remove, + .id_table = dim2_id, + .driver = { + .name = "hdm_dim2", + }, +}; + +module_platform_driver(dim2_driver); + +MODULE_AUTHOR("Jain Roy Ambi "); +MODULE_AUTHOR("Andrey Shvetsov "); +MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/most/dim2/dim2.h b/drivers/staging/most/dim2/dim2.h new file mode 100644 index 000000000000..6a9fc51a2eb4 --- /dev/null +++ b/drivers/staging/most/dim2/dim2.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * dim2.h - MediaLB DIM2 HDM Header + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +#ifndef DIM2_HDM_H +#define DIM2_HDM_H + +struct device; + +/* platform dependent data for dim2 interface */ +struct dim2_platform_data { + int (*init)(struct dim2_platform_data *pd, void __iomem *io_base, + int clk_speed); + void (*destroy)(struct dim2_platform_data *pd); + void *priv; +}; + +#endif /* DIM2_HDM_H */ diff --git a/drivers/staging/most/dim2/errors.h b/drivers/staging/most/dim2/errors.h new file mode 100644 index 000000000000..3487510fbd2f --- /dev/null +++ b/drivers/staging/most/dim2/errors.h @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * errors.h - Definitions of errors for DIM2 HAL API + * (MediaLB, Device Interface Macro IP, OS62420) + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +#ifndef _MOST_DIM_ERRORS_H +#define _MOST_DIM_ERRORS_H + +/** + * MOST DIM errors. + */ +enum dim_errors_t { + /** Not an error */ + DIM_NO_ERROR = 0, + + /** Bad base address for DIM2 IP */ + DIM_INIT_ERR_DIM_ADDR = 0x10, + + /**< Bad MediaLB clock */ + DIM_INIT_ERR_MLB_CLOCK, + + /** Bad channel address */ + DIM_INIT_ERR_CHANNEL_ADDRESS, + + /** Out of DBR memory */ + DIM_INIT_ERR_OUT_OF_MEMORY, + + /** DIM API is called while DIM is not initialized successfully */ + DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20, + + /** + * Configuration does not respect hardware limitations + * for isochronous or synchronous channels + */ + DIM_ERR_BAD_CONFIG, + + /** + * Buffer size does not respect hardware limitations + * for isochronous or synchronous channels + */ + DIM_ERR_BAD_BUFFER_SIZE, + + DIM_ERR_UNDERFLOW, + + DIM_ERR_OVERFLOW, +}; + +#endif /* _MOST_DIM_ERRORS_H */ diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c new file mode 100644 index 000000000000..17c04e1c5e62 --- /dev/null +++ b/drivers/staging/most/dim2/hal.c @@ -0,0 +1,979 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * hal.c - DIM2 HAL implementation + * (MediaLB, Device Interface Macro IP, OS62420) + * + * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG + */ + +/* Author: Andrey Shvetsov */ + +#include "hal.h" +#include "errors.h" +#include "reg.h" +#include +#include + +/* + * Size factor for isochronous DBR buffer. + * Minimal value is 3. + */ +#define ISOC_DBR_FACTOR 3u + +/* + * Number of 32-bit units for DBR map. + * + * 1: block size is 512, max allocation is 16K + * 2: block size is 256, max allocation is 8K + * 4: block size is 128, max allocation is 4K + * 8: block size is 64, max allocation is 2K + * + * Min allocated space is block size. + * Max possible allocated space is 32 blocks. + */ +#define DBR_MAP_SIZE 2 + +/* -------------------------------------------------------------------------- */ +/* not configurable area */ + +#define CDT 0x00 +#define ADT 0x40 +#define MLB_CAT 0x80 +#define AHB_CAT 0x88 + +#define DBR_SIZE (16 * 1024) /* specified by IP */ +#define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE) + +#define ROUND_UP_TO(x, d) (DIV_ROUND_UP(x, (d)) * (d)) + +/* -------------------------------------------------------------------------- */ +/* generic helper functions and macros */ + +static inline u32 bit_mask(u8 position) +{ + return (u32)1 << position; +} + +static inline bool dim_on_error(u8 error_id, const char *error_message) +{ + dimcb_on_error(error_id, error_message); + return false; +} + +/* -------------------------------------------------------------------------- */ +/* types and local variables */ + +struct async_tx_dbr { + u8 ch_addr; + u16 rpc; + u16 wpc; + u16 rest_size; + u16 sz_queue[CDT0_RPC_MASK + 1]; +}; + +struct lld_global_vars_t { + bool dim_is_initialized; + bool mcm_is_initialized; + struct dim2_regs __iomem *dim2; /* DIM2 core base address */ + struct async_tx_dbr atx_dbr; + u32 fcnt; + u32 dbr_map[DBR_MAP_SIZE]; +}; + +static struct lld_global_vars_t g = { false }; + +/* -------------------------------------------------------------------------- */ + +static int dbr_get_mask_size(u16 size) +{ + int i; + + for (i = 0; i < 6; i++) + if (size <= (DBR_BLOCK_SIZE << i)) + return 1 << i; + return 0; +} + +/** + * Allocates DBR memory. + * @param size Allocating memory size. + * @return Offset in DBR memory by success or DBR_SIZE if out of memory. + */ +static int alloc_dbr(u16 size) +{ + int mask_size; + int i, block_idx = 0; + + if (size <= 0) + return DBR_SIZE; /* out of memory */ + + mask_size = dbr_get_mask_size(size); + if (mask_size == 0) + return DBR_SIZE; /* out of memory */ + + for (i = 0; i < DBR_MAP_SIZE; i++) { + u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE); + u32 mask = ~((~(u32)0) << blocks); + + do { + if ((g.dbr_map[i] & mask) == 0) { + g.dbr_map[i] |= mask; + return block_idx * DBR_BLOCK_SIZE; + } + block_idx += mask_size; + /* do shift left with 2 steps in case mask_size == 32 */ + mask <<= mask_size - 1; + } while ((mask <<= 1) != 0); + } + + return DBR_SIZE; /* out of memory */ +} + +static void free_dbr(int offs, int size) +{ + int block_idx = offs / DBR_BLOCK_SIZE; + u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE); + u32 mask = ~((~(u32)0) << blocks); + + mask <<= block_idx % 32; + g.dbr_map[block_idx / 32] &= ~mask; +} + +/* -------------------------------------------------------------------------- */ + +static void dim2_transfer_madr(u32 val) +{ + dimcb_io_write(&g.dim2->MADR, val); + + /* wait for transfer completion */ + while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) + continue; + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ +} + +static void dim2_clear_dbr(u16 addr, u16 size) +{ + enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 }; + + u16 const end_addr = addr + size; + u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT); + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + dimcb_io_write(&g.dim2->MDAT0, 0); + + for (; addr < end_addr; addr++) + dim2_transfer_madr(cmd | addr); +} + +static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) +{ + dim2_transfer_madr(ctr_addr); + + return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx); +} + +static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) +{ + enum { MADR_WNR_BIT = 31 }; + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + + if (mask[0] != 0) + dimcb_io_write(&g.dim2->MDAT0, value[0]); + if (mask[1] != 0) + dimcb_io_write(&g.dim2->MDAT1, value[1]); + if (mask[2] != 0) + dimcb_io_write(&g.dim2->MDAT2, value[2]); + if (mask[3] != 0) + dimcb_io_write(&g.dim2->MDAT3, value[3]); + + dimcb_io_write(&g.dim2->MDWE0, mask[0]); + dimcb_io_write(&g.dim2->MDWE1, mask[1]); + dimcb_io_write(&g.dim2->MDWE2, mask[2]); + dimcb_io_write(&g.dim2->MDWE3, mask[3]); + + dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr); +} + +static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value) +{ + u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + + dim2_write_ctr_mask(ctr_addr, mask, value); +} + +static inline void dim2_clear_ctr(u32 ctr_addr) +{ + u32 const value[4] = { 0, 0, 0, 0 }; + + dim2_write_ctr(ctr_addr, value); +} + +static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type, + bool read_not_write) +{ + bool isoc_fce = ch_type == CAT_CT_VAL_ISOC; + bool sync_mfe = ch_type == CAT_CT_VAL_SYNC; + u16 const cat = + (read_not_write << CAT_RNW_BIT) | + (ch_type << CAT_CT_SHIFT) | + (ch_addr << CAT_CL_SHIFT) | + (isoc_fce << CAT_FCE_BIT) | + (sync_mfe << CAT_MFE_BIT) | + (false << CAT_MT_BIT) | + (true << CAT_CE_BIT); + u8 const ctr_addr = cat_base + ch_addr / 8; + u8 const idx = (ch_addr % 8) / 2; + u8 const shift = (ch_addr % 2) * 16; + u32 mask[4] = { 0, 0, 0, 0 }; + u32 value[4] = { 0, 0, 0, 0 }; + + mask[idx] = (u32)0xFFFF << shift; + value[idx] = cat << shift; + dim2_write_ctr_mask(ctr_addr, mask, value); +} + +static void dim2_clear_cat(u8 cat_base, u8 ch_addr) +{ + u8 const ctr_addr = cat_base + ch_addr / 8; + u8 const idx = (ch_addr % 8) / 2; + u8 const shift = (ch_addr % 2) * 16; + u32 mask[4] = { 0, 0, 0, 0 }; + u32 value[4] = { 0, 0, 0, 0 }; + + mask[idx] = (u32)0xFFFF << shift; + dim2_write_ctr_mask(ctr_addr, mask, value); +} + +static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size, + u16 packet_length) +{ + u32 cdt[4] = { 0, 0, 0, 0 }; + + if (packet_length) + cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT); + + cdt[3] = + ((hw_buffer_size - 1) << CDT3_BD_SHIFT) | + (dbr_address << CDT3_BA_SHIFT); + dim2_write_ctr(CDT + ch_addr, cdt); +} + +static u16 dim2_rpc(u8 ch_addr) +{ + u32 cdt0 = dim2_read_ctr(CDT + ch_addr, 0); + + return (cdt0 >> CDT0_RPC_SHIFT) & CDT0_RPC_MASK; +} + +static void dim2_clear_cdt(u8 ch_addr) +{ + u32 cdt[4] = { 0, 0, 0, 0 }; + + dim2_write_ctr(CDT + ch_addr, cdt); +} + +static void dim2_configure_adt(u8 ch_addr) +{ + u32 adt[4] = { 0, 0, 0, 0 }; + + adt[0] = + (true << ADT0_CE_BIT) | + (true << ADT0_LE_BIT) | + (0 << ADT0_PG_BIT); + + dim2_write_ctr(ADT + ch_addr, adt); +} + +static void dim2_clear_adt(u8 ch_addr) +{ + u32 adt[4] = { 0, 0, 0, 0 }; + + dim2_write_ctr(ADT + ch_addr, adt); +} + +static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr, + u16 buffer_size) +{ + u8 const shift = idx * 16; + + u32 mask[4] = { 0, 0, 0, 0 }; + u32 adt[4] = { 0, 0, 0, 0 }; + + mask[1] = + bit_mask(ADT1_PS_BIT + shift) | + bit_mask(ADT1_RDY_BIT + shift) | + (ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift)); + adt[1] = + (true << (ADT1_PS_BIT + shift)) | + (true << (ADT1_RDY_BIT + shift)) | + ((buffer_size - 1) << (ADT1_BD_SHIFT + shift)); + + mask[idx + 2] = 0xFFFFFFFF; + adt[idx + 2] = buf_addr; + + dim2_write_ctr_mask(ADT + ch_addr, mask, adt); +} + +static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr, + u16 buffer_size) +{ + u8 const shift = idx * 16; + + u32 mask[4] = { 0, 0, 0, 0 }; + u32 adt[4] = { 0, 0, 0, 0 }; + + mask[1] = + bit_mask(ADT1_RDY_BIT + shift) | + (ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift)); + adt[1] = + (true << (ADT1_RDY_BIT + shift)) | + ((buffer_size - 1) << (ADT1_BD_SHIFT + shift)); + + mask[idx + 2] = 0xFFFFFFFF; + adt[idx + 2] = buf_addr; + + dim2_write_ctr_mask(ADT + ch_addr, mask, adt); +} + +static void dim2_clear_ctram(void) +{ + u32 ctr_addr; + + for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++) + dim2_clear_ctr(ctr_addr); +} + +static void dim2_configure_channel( + u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size, + u16 packet_length) +{ + dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length); + dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0); + + dim2_configure_adt(ch_addr); + dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1); + + /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ + dimcb_io_write(&g.dim2->ACMR0, + dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr)); +} + +static void dim2_clear_channel(u8 ch_addr) +{ + /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ + dimcb_io_write(&g.dim2->ACMR0, + dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); + + dim2_clear_cat(AHB_CAT, ch_addr); + dim2_clear_adt(ch_addr); + + dim2_clear_cat(MLB_CAT, ch_addr); + dim2_clear_cdt(ch_addr); + + /* clear channel status bit */ + dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); +} + +/* -------------------------------------------------------------------------- */ +/* trace async tx dbr fill state */ + +static inline u16 norm_pc(u16 pc) +{ + return pc & CDT0_RPC_MASK; +} + +static void dbrcnt_init(u8 ch_addr, u16 dbr_size) +{ + g.atx_dbr.rest_size = dbr_size; + g.atx_dbr.rpc = dim2_rpc(ch_addr); + g.atx_dbr.wpc = g.atx_dbr.rpc; +} + +static void dbrcnt_enq(int buf_sz) +{ + g.atx_dbr.rest_size -= buf_sz; + g.atx_dbr.sz_queue[norm_pc(g.atx_dbr.wpc)] = buf_sz; + g.atx_dbr.wpc++; +} + +u16 dim_dbr_space(struct dim_channel *ch) +{ + u16 cur_rpc; + struct async_tx_dbr *dbr = &g.atx_dbr; + + if (ch->addr != dbr->ch_addr) + return 0xFFFF; + + cur_rpc = dim2_rpc(ch->addr); + + while (norm_pc(dbr->rpc) != cur_rpc) { + dbr->rest_size += dbr->sz_queue[norm_pc(dbr->rpc)]; + dbr->rpc++; + } + + if ((u16)(dbr->wpc - dbr->rpc) >= CDT0_RPC_MASK) + return 0; + + return dbr->rest_size; +} + +/* -------------------------------------------------------------------------- */ +/* channel state helpers */ + +static void state_init(struct int_ch_state *state) +{ + state->request_counter = 0; + state->service_counter = 0; + + state->idx1 = 0; + state->idx2 = 0; + state->level = 0; +} + +/* -------------------------------------------------------------------------- */ +/* macro helper functions */ + +static inline bool check_channel_address(u32 ch_address) +{ + return ch_address > 0 && (ch_address % 2) == 0 && + (ch_address / 2) <= (u32)CAT_CL_MASK; +} + +static inline bool check_packet_length(u32 packet_length) +{ + u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR; + + if (packet_length <= 0) + return false; /* too small */ + + if (packet_length > max_size) + return false; /* too big */ + + if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK) + return false; /* too big */ + + return true; +} + +static inline bool check_bytes_per_frame(u32 bytes_per_frame) +{ + u16 const bd_factor = g.fcnt + 2; + u16 const max_size = ((u16)CDT3_BD_MASK + 1u) >> bd_factor; + + if (bytes_per_frame <= 0) + return false; /* too small */ + + if (bytes_per_frame > max_size) + return false; /* too big */ + + return true; +} + +static inline u16 norm_ctrl_async_buffer_size(u16 buf_size) +{ + u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u; + + if (buf_size > max_size) + return max_size; + + return buf_size; +} + +static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length) +{ + u16 n; + u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; + + if (buf_size > max_size) + buf_size = max_size; + + n = buf_size / packet_length; + + if (n < 2u) + return 0; /* too small buffer for given packet_length */ + + return packet_length * n; +} + +static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) +{ + u16 n; + u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; + u32 const unit = bytes_per_frame << g.fcnt; + + if (buf_size > max_size) + buf_size = max_size; + + n = buf_size / unit; + + if (n < 1u) + return 0; /* too small buffer for given bytes_per_frame */ + + return unit * n; +} + +static void dim2_cleanup(void) +{ + /* disable MediaLB */ + dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT); + + dim2_clear_ctram(); + + /* disable mlb_int interrupt */ + dimcb_io_write(&g.dim2->MIEN, 0); + + /* clear status for all dma channels */ + dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF); + dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); + + /* mask interrupts for all channels */ + dimcb_io_write(&g.dim2->ACMR0, 0); + dimcb_io_write(&g.dim2->ACMR1, 0); +} + +static void dim2_initialize(bool enable_6pin, u8 mlb_clock) +{ + dim2_cleanup(); + + /* configure and enable MediaLB */ + dimcb_io_write(&g.dim2->MLBC0, + enable_6pin << MLBC0_MLBPEN_BIT | + mlb_clock << MLBC0_MLBCLK_SHIFT | + g.fcnt << MLBC0_FCNT_SHIFT | + true << MLBC0_MLBEN_BIT); + + /* activate all HBI channels */ + dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF); + dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); + + /* enable HBI */ + dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); + + /* configure DMA */ + dimcb_io_write(&g.dim2->ACTL, + ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | + true << ACTL_SCE_BIT); +} + +static bool dim2_is_mlb_locked(void) +{ + u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT); + u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) | + bit_mask(MLBC1_LOCKERR_BIT); + u32 const c1 = dimcb_io_read(&g.dim2->MLBC1); + u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; + + dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask); + return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 && + (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0; +} + +/* -------------------------------------------------------------------------- */ +/* channel help routines */ + +static inline bool service_channel(u8 ch_addr, u8 idx) +{ + u8 const shift = idx * 16; + u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1); + u32 mask[4] = { 0, 0, 0, 0 }; + u32 adt_w[4] = { 0, 0, 0, 0 }; + + if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0) + return false; + + mask[1] = + bit_mask(ADT1_DNE_BIT + shift) | + bit_mask(ADT1_ERR_BIT + shift) | + bit_mask(ADT1_RDY_BIT + shift); + dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); + + /* clear channel status bit */ + dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); + + return true; +} + +/* -------------------------------------------------------------------------- */ +/* channel init routines */ + +static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length) +{ + state_init(&ch->state); + + ch->addr = ch_addr; + + ch->packet_length = packet_length; + ch->bytes_per_frame = 0; + ch->done_sw_buffers_number = 0; +} + +static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame) +{ + state_init(&ch->state); + + ch->addr = ch_addr; + + ch->packet_length = 0; + ch->bytes_per_frame = bytes_per_frame; + ch->done_sw_buffers_number = 0; +} + +static void channel_init(struct dim_channel *ch, u8 ch_addr) +{ + state_init(&ch->state); + + ch->addr = ch_addr; + + ch->packet_length = 0; + ch->bytes_per_frame = 0; + ch->done_sw_buffers_number = 0; +} + +/* returns true if channel interrupt state is cleared */ +static bool channel_service_interrupt(struct dim_channel *ch) +{ + struct int_ch_state *const state = &ch->state; + + if (!service_channel(ch->addr, state->idx2)) + return false; + + state->idx2 ^= 1; + state->request_counter++; + return true; +} + +static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) +{ + struct int_ch_state *const state = &ch->state; + + if (buf_size <= 0) + return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size"); + + if (ch->packet_length == 0 && ch->bytes_per_frame == 0 && + buf_size != norm_ctrl_async_buffer_size(buf_size)) + return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, + "Bad control/async buffer size"); + + if (ch->packet_length && + buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length)) + return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, + "Bad isochronous buffer size"); + + if (ch->bytes_per_frame && + buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame)) + return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, + "Bad synchronous buffer size"); + + if (state->level >= 2u) + return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow"); + + ++state->level; + + if (ch->addr == g.atx_dbr.ch_addr) + dbrcnt_enq(buf_size); + + if (ch->packet_length || ch->bytes_per_frame) + dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size); + else + dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr, + buf_size); + state->idx1 ^= 1; + + return true; +} + +static u8 channel_service(struct dim_channel *ch) +{ + struct int_ch_state *const state = &ch->state; + + if (state->service_counter != state->request_counter) { + state->service_counter++; + if (state->level == 0) + return DIM_ERR_UNDERFLOW; + + --state->level; + ch->done_sw_buffers_number++; + } + + return DIM_NO_ERROR; +} + +static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number) +{ + if (buffers_number > ch->done_sw_buffers_number) + return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow"); + + ch->done_sw_buffers_number -= buffers_number; + return true; +} + +/* -------------------------------------------------------------------------- */ +/* API */ + +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock, + u32 fcnt) +{ + g.dim_is_initialized = false; + + if (!dim_base_address) + return DIM_INIT_ERR_DIM_ADDR; + + /* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */ + /* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */ + if (mlb_clock >= 8) + return DIM_INIT_ERR_MLB_CLOCK; + + if (fcnt > MLBC0_FCNT_MAX_VAL) + return DIM_INIT_ERR_MLB_CLOCK; + + g.dim2 = dim_base_address; + g.fcnt = fcnt; + g.dbr_map[0] = 0; + g.dbr_map[1] = 0; + + dim2_initialize(mlb_clock >= 3, mlb_clock); + + g.dim_is_initialized = true; + + return DIM_NO_ERROR; +} + +void dim_shutdown(void) +{ + g.dim_is_initialized = false; + dim2_cleanup(); +} + +bool dim_get_lock_state(void) +{ + return dim2_is_mlb_locked(); +} + +static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, + u16 ch_address, u16 hw_buffer_size) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + if (!check_channel_address(ch_address)) + return DIM_INIT_ERR_CHANNEL_ADDRESS; + + ch->dbr_size = ROUND_UP_TO(hw_buffer_size, DBR_BLOCK_SIZE); + ch->dbr_addr = alloc_dbr(ch->dbr_size); + if (ch->dbr_addr >= DBR_SIZE) + return DIM_INIT_ERR_OUT_OF_MEMORY; + + channel_init(ch, ch_address / 2); + + dim2_configure_channel(ch->addr, type, is_tx, + ch->dbr_addr, ch->dbr_size, 0); + + return DIM_NO_ERROR; +} + +void dim_service_mlb_int_irq(void) +{ + dimcb_io_write(&g.dim2->MS0, 0); + dimcb_io_write(&g.dim2->MS1, 0); +} + +u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) +{ + return norm_ctrl_async_buffer_size(buf_size); +} + +/** + * Retrieves maximal possible correct buffer size for isochronous data type + * conform to given packet length and not bigger than given buffer size. + * + * Returns non-zero correct buffer size or zero by error. + */ +u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length) +{ + if (!check_packet_length(packet_length)) + return 0; + + return norm_isoc_buffer_size(buf_size, packet_length); +} + +/** + * Retrieves maximal possible correct buffer size for synchronous data type + * conform to given bytes per frame and not bigger than given buffer size. + * + * Returns non-zero correct buffer size or zero by error. + */ +u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) +{ + if (!check_bytes_per_frame(bytes_per_frame)) + return 0; + + return norm_sync_buffer_size(buf_size, bytes_per_frame); +} + +u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 max_buffer_size) +{ + return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address, + max_buffer_size); +} + +u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 max_buffer_size) +{ + u8 ret = init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address, + max_buffer_size); + + if (is_tx && !g.atx_dbr.ch_addr) { + g.atx_dbr.ch_addr = ch->addr; + dbrcnt_init(ch->addr, ch->dbr_size); + dimcb_io_write(&g.dim2->MIEN, bit_mask(20)); + } + + return ret; +} + +u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 packet_length) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + if (!check_channel_address(ch_address)) + return DIM_INIT_ERR_CHANNEL_ADDRESS; + + if (!check_packet_length(packet_length)) + return DIM_ERR_BAD_CONFIG; + + ch->dbr_size = packet_length * ISOC_DBR_FACTOR; + ch->dbr_addr = alloc_dbr(ch->dbr_size); + if (ch->dbr_addr >= DBR_SIZE) + return DIM_INIT_ERR_OUT_OF_MEMORY; + + isoc_init(ch, ch_address / 2, packet_length); + + dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr, + ch->dbr_size, packet_length); + + return DIM_NO_ERROR; +} + +u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 bytes_per_frame) +{ + u16 bd_factor = g.fcnt + 2; + + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + if (!check_channel_address(ch_address)) + return DIM_INIT_ERR_CHANNEL_ADDRESS; + + if (!check_bytes_per_frame(bytes_per_frame)) + return DIM_ERR_BAD_CONFIG; + + ch->dbr_size = bytes_per_frame << bd_factor; + ch->dbr_addr = alloc_dbr(ch->dbr_size); + if (ch->dbr_addr >= DBR_SIZE) + return DIM_INIT_ERR_OUT_OF_MEMORY; + + sync_init(ch, ch_address / 2, bytes_per_frame); + + dim2_clear_dbr(ch->dbr_addr, ch->dbr_size); + dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx, + ch->dbr_addr, ch->dbr_size, 0); + + return DIM_NO_ERROR; +} + +u8 dim_destroy_channel(struct dim_channel *ch) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + if (ch->addr == g.atx_dbr.ch_addr) { + dimcb_io_write(&g.dim2->MIEN, 0); + g.atx_dbr.ch_addr = 0; + } + + dim2_clear_channel(ch->addr); + if (ch->dbr_addr < DBR_SIZE) + free_dbr(ch->dbr_addr, ch->dbr_size); + ch->dbr_addr = DBR_SIZE; + + return DIM_NO_ERROR; +} + +void dim_service_ahb_int_irq(struct dim_channel *const *channels) +{ + bool state_changed; + + if (!g.dim_is_initialized) { + dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, + "DIM is not initialized"); + return; + } + + if (!channels) { + dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels"); + return; + } + + /* + * Use while-loop and a flag to make sure the age is changed back at + * least once, otherwise the interrupt may never come if CPU generates + * interrupt on changing age. + * This cycle runs not more than number of channels, because + * channel_service_interrupt() routine doesn't start the channel again. + */ + do { + struct dim_channel *const *ch = channels; + + state_changed = false; + + while (*ch) { + state_changed |= channel_service_interrupt(*ch); + ++ch; + } + } while (state_changed); +} + +u8 dim_service_channel(struct dim_channel *ch) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + return channel_service(ch); +} + +struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch, + struct dim_ch_state_t *state_ptr) +{ + if (!ch || !state_ptr) + return NULL; + + state_ptr->ready = ch->state.level < 2; + state_ptr->done_buffers = ch->done_sw_buffers_number; + + return state_ptr; +} + +bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, + u16 buffer_size) +{ + if (!ch) + return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, + "Bad channel"); + + return channel_start(ch, buffer_addr, buffer_size); +} + +bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number) +{ + if (!ch) + return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, + "Bad channel"); + + return channel_detach_buffers(ch, buffers_number); +} diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h new file mode 100644 index 000000000000..e04a5350f134 --- /dev/null +++ b/drivers/staging/most/dim2/hal.h @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * hal.h - DIM2 HAL interface + * (MediaLB, Device Interface Macro IP, OS62420) + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +#ifndef _DIM2_HAL_H +#define _DIM2_HAL_H + +#include +#include "reg.h" + +/* + * The values below are specified in the hardware specification. + * So, they should not be changed until the hardware specification changes. + */ +enum mlb_clk_speed { + CLK_256FS = 0, + CLK_512FS = 1, + CLK_1024FS = 2, + CLK_2048FS = 3, + CLK_3072FS = 4, + CLK_4096FS = 5, + CLK_6144FS = 6, + CLK_8192FS = 7, +}; + +struct dim_ch_state_t { + bool ready; /* Shows readiness to enqueue next buffer */ + u16 done_buffers; /* Number of completed buffers */ +}; + +struct int_ch_state { + /* changed only in interrupt context */ + volatile int request_counter; + + /* changed only in task context */ + volatile int service_counter; + + u8 idx1; + u8 idx2; + u8 level; /* [0..2], buffering level */ +}; + +struct dim_channel { + struct int_ch_state state; + u8 addr; + u16 dbr_addr; + u16 dbr_size; + u16 packet_length; /*< Isochronous packet length in bytes. */ + u16 bytes_per_frame; /*< Synchronous bytes per frame. */ + u16 done_sw_buffers_number; /*< Done software buffers number. */ +}; + +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock, + u32 fcnt); + +void dim_shutdown(void); + +bool dim_get_lock_state(void); + +u16 dim_norm_ctrl_async_buffer_size(u16 buf_size); + +u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length); + +u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame); + +u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 max_buffer_size); + +u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 max_buffer_size); + +u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 packet_length); + +u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 bytes_per_frame); + +u8 dim_destroy_channel(struct dim_channel *ch); + +void dim_service_mlb_int_irq(void); + +void dim_service_ahb_int_irq(struct dim_channel *const *channels); + +u8 dim_service_channel(struct dim_channel *ch); + +struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch, + struct dim_ch_state_t *state_ptr); + +u16 dim_dbr_space(struct dim_channel *ch); + +bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, + u16 buffer_size); + +bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); + +u32 dimcb_io_read(u32 __iomem *ptr32); + +void dimcb_io_write(u32 __iomem *ptr32, u32 value); + +void dimcb_on_error(u8 error_id, const char *error_message); + +#endif /* _DIM2_HAL_H */ diff --git a/drivers/staging/most/dim2/reg.h b/drivers/staging/most/dim2/reg.h new file mode 100644 index 000000000000..69cbf78239f1 --- /dev/null +++ b/drivers/staging/most/dim2/reg.h @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * reg.h - Definitions for registers of DIM2 + * (MediaLB, Device Interface Macro IP, OS62420) + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +#ifndef DIM2_OS62420_H +#define DIM2_OS62420_H + +#include + +struct dim2_regs { + /* 0x00 */ u32 MLBC0; + /* 0x01 */ u32 rsvd0[1]; + /* 0x02 */ u32 MLBPC0; + /* 0x03 */ u32 MS0; + /* 0x04 */ u32 rsvd1[1]; + /* 0x05 */ u32 MS1; + /* 0x06 */ u32 rsvd2[2]; + /* 0x08 */ u32 MSS; + /* 0x09 */ u32 MSD; + /* 0x0A */ u32 rsvd3[1]; + /* 0x0B */ u32 MIEN; + /* 0x0C */ u32 rsvd4[1]; + /* 0x0D */ u32 MLBPC2; + /* 0x0E */ u32 MLBPC1; + /* 0x0F */ u32 MLBC1; + /* 0x10 */ u32 rsvd5[0x10]; + /* 0x20 */ u32 HCTL; + /* 0x21 */ u32 rsvd6[1]; + /* 0x22 */ u32 HCMR0; + /* 0x23 */ u32 HCMR1; + /* 0x24 */ u32 HCER0; + /* 0x25 */ u32 HCER1; + /* 0x26 */ u32 HCBR0; + /* 0x27 */ u32 HCBR1; + /* 0x28 */ u32 rsvd7[8]; + /* 0x30 */ u32 MDAT0; + /* 0x31 */ u32 MDAT1; + /* 0x32 */ u32 MDAT2; + /* 0x33 */ u32 MDAT3; + /* 0x34 */ u32 MDWE0; + /* 0x35 */ u32 MDWE1; + /* 0x36 */ u32 MDWE2; + /* 0x37 */ u32 MDWE3; + /* 0x38 */ u32 MCTL; + /* 0x39 */ u32 MADR; + /* 0x3A */ u32 rsvd8[0xB6]; + /* 0xF0 */ u32 ACTL; + /* 0xF1 */ u32 rsvd9[3]; + /* 0xF4 */ u32 ACSR0; + /* 0xF5 */ u32 ACSR1; + /* 0xF6 */ u32 ACMR0; + /* 0xF7 */ u32 ACMR1; +}; + +#define DIM2_MASK(n) (~((~(u32)0) << (n))) + +enum { + MLBC0_MLBLK_BIT = 7, + + MLBC0_MLBPEN_BIT = 5, + + MLBC0_MLBCLK_SHIFT = 2, + MLBC0_MLBCLK_VAL_256FS = 0, + MLBC0_MLBCLK_VAL_512FS = 1, + MLBC0_MLBCLK_VAL_1024FS = 2, + MLBC0_MLBCLK_VAL_2048FS = 3, + + MLBC0_FCNT_SHIFT = 15, + MLBC0_FCNT_MASK = 7, + MLBC0_FCNT_MAX_VAL = 6, + + MLBC0_MLBEN_BIT = 0, + + MIEN_CTX_BREAK_BIT = 29, + MIEN_CTX_PE_BIT = 28, + MIEN_CTX_DONE_BIT = 27, + + MIEN_CRX_BREAK_BIT = 26, + MIEN_CRX_PE_BIT = 25, + MIEN_CRX_DONE_BIT = 24, + + MIEN_ATX_BREAK_BIT = 22, + MIEN_ATX_PE_BIT = 21, + MIEN_ATX_DONE_BIT = 20, + + MIEN_ARX_BREAK_BIT = 19, + MIEN_ARX_PE_BIT = 18, + MIEN_ARX_DONE_BIT = 17, + + MIEN_SYNC_PE_BIT = 16, + + MIEN_ISOC_BUFO_BIT = 1, + MIEN_ISOC_PE_BIT = 0, + + MLBC1_NDA_SHIFT = 8, + MLBC1_NDA_MASK = 0xFF, + + MLBC1_CLKMERR_BIT = 7, + MLBC1_LOCKERR_BIT = 6, + + ACTL_DMA_MODE_BIT = 2, + ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0, + ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1, + ACTL_SCE_BIT = 0, + + HCTL_EN_BIT = 15 +}; + +enum { + CDT0_RPC_SHIFT = 16 + 11, + CDT0_RPC_MASK = DIM2_MASK(5), + + CDT1_BS_ISOC_SHIFT = 0, + CDT1_BS_ISOC_MASK = DIM2_MASK(9), + + CDT3_BD_SHIFT = 0, + CDT3_BD_MASK = DIM2_MASK(12), + CDT3_BD_ISOC_MASK = DIM2_MASK(13), + CDT3_BA_SHIFT = 16, + + ADT0_CE_BIT = 15, + ADT0_LE_BIT = 14, + ADT0_PG_BIT = 13, + + ADT1_RDY_BIT = 15, + ADT1_DNE_BIT = 14, + ADT1_ERR_BIT = 13, + ADT1_PS_BIT = 12, + ADT1_MEP_BIT = 11, + ADT1_BD_SHIFT = 0, + ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11), + ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13), + + CAT_FCE_BIT = 14, + CAT_MFE_BIT = 14, + + CAT_MT_BIT = 13, + + CAT_RNW_BIT = 12, + + CAT_CE_BIT = 11, + + CAT_CT_SHIFT = 8, + CAT_CT_VAL_SYNC = 0, + CAT_CT_VAL_CONTROL = 1, + CAT_CT_VAL_ASYNC = 2, + CAT_CT_VAL_ISOC = 3, + + CAT_CL_SHIFT = 0, + CAT_CL_MASK = DIM2_MASK(6) +}; + +#endif /* DIM2_OS62420_H */ diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c new file mode 100644 index 000000000000..ec1f4cecf9e7 --- /dev/null +++ b/drivers/staging/most/dim2/sysfs.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sysfs.c - MediaLB sysfs information + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +/* Author: Andrey Shvetsov */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include "sysfs.h" + +struct bus_attr { + struct attribute attr; + ssize_t (*show)(struct medialb_bus *bus, char *buf); + ssize_t (*store)(struct medialb_bus *bus, const char *buf, + size_t count); +}; + +static ssize_t state_show(struct medialb_bus *bus, char *buf) +{ + bool state = dim2_sysfs_get_state_cb(); + + return sprintf(buf, "%s\n", state ? "locked" : ""); +} + +static struct bus_attr state_attr = __ATTR_RO(state); + +static struct attribute *bus_default_attrs[] = { + &state_attr.attr, + NULL, +}; + +static const struct attribute_group bus_attr_group = { + .attrs = bus_default_attrs, +}; + +static void bus_kobj_release(struct kobject *kobj) +{ +} + +static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct medialb_bus *bus = + container_of(kobj, struct medialb_bus, kobj_group); + struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); + + if (!xattr->show) + return -EIO; + + return xattr->show(bus, buf); +} + +static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + struct medialb_bus *bus = + container_of(kobj, struct medialb_bus, kobj_group); + struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); + + if (!xattr->store) + return -EIO; + + return xattr->store(bus, buf, count); +} + +static struct sysfs_ops const bus_kobj_sysfs_ops = { + .show = bus_kobj_attr_show, + .store = bus_kobj_attr_store, +}; + +static struct kobj_type bus_ktype = { + .release = bus_kobj_release, + .sysfs_ops = &bus_kobj_sysfs_ops, +}; + +int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj) +{ + int err; + + kobject_init(&bus->kobj_group, &bus_ktype); + err = kobject_add(&bus->kobj_group, parent_kobj, "bus"); + if (err) { + pr_err("kobject_add() failed: %d\n", err); + goto err_kobject_add; + } + + err = sysfs_create_group(&bus->kobj_group, &bus_attr_group); + if (err) { + pr_err("sysfs_create_group() failed: %d\n", err); + goto err_create_group; + } + + return 0; + +err_create_group: + kobject_put(&bus->kobj_group); + +err_kobject_add: + return err; +} + +void dim2_sysfs_destroy(struct medialb_bus *bus) +{ + kobject_put(&bus->kobj_group); +} diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h new file mode 100644 index 000000000000..a33ebd8b45f5 --- /dev/null +++ b/drivers/staging/most/dim2/sysfs.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sysfs.h - MediaLB sysfs information + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +/* Author: Andrey Shvetsov */ + +#ifndef DIM2_SYSFS_H +#define DIM2_SYSFS_H + +#include + +struct medialb_bus { + struct kobject kobj_group; +}; + +struct dim2_hdm; + +int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj); +void dim2_sysfs_destroy(struct medialb_bus *bus); + +/* + * callback, + * must deliver MediaLB state as true if locked or false if unlocked + */ +bool dim2_sysfs_get_state_cb(void); + +#endif /* DIM2_SYSFS_H */ diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig deleted file mode 100644 index 663bfebff674..000000000000 --- a/drivers/staging/most/hdm-dim2/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# -# MediaLB configuration -# - -config HDM_DIM2 - tristate "DIM2 HDM" - depends on HAS_IOMEM - - ---help--- - Say Y here if you want to connect via MediaLB to network transceiver. - This device driver is platform dependent and needs an additional - platform driver to be installed. For more information contact - maintainer of this driver. - - To compile this driver as a module, choose M here: the - module will be called hdm_dim2. diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h deleted file mode 100644 index 8b90196076d5..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_errors.h +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dim2_errors.h - Definitions of errors for DIM2 HAL API - * (MediaLB, Device Interface Macro IP, OS62420) - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - */ - -#ifndef _MOST_DIM_ERRORS_H -#define _MOST_DIM_ERRORS_H - -/** - * MOST DIM errors. - */ -enum dim_errors_t { - /** Not an error */ - DIM_NO_ERROR = 0, - - /** Bad base address for DIM2 IP */ - DIM_INIT_ERR_DIM_ADDR = 0x10, - - /**< Bad MediaLB clock */ - DIM_INIT_ERR_MLB_CLOCK, - - /** Bad channel address */ - DIM_INIT_ERR_CHANNEL_ADDRESS, - - /** Out of DBR memory */ - DIM_INIT_ERR_OUT_OF_MEMORY, - - /** DIM API is called while DIM is not initialized successfully */ - DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20, - - /** - * Configuration does not respect hardware limitations - * for isochronous or synchronous channels - */ - DIM_ERR_BAD_CONFIG, - - /** - * Buffer size does not respect hardware limitations - * for isochronous or synchronous channels - */ - DIM_ERR_BAD_BUFFER_SIZE, - - DIM_ERR_UNDERFLOW, - - DIM_ERR_OVERFLOW, -}; - -#endif /* _MOST_DIM_ERRORS_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c deleted file mode 100644 index f98ac935729c..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ /dev/null @@ -1,979 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dim2_hal.c - DIM2 HAL implementation - * (MediaLB, Device Interface Macro IP, OS62420) - * - * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG - */ - -/* Author: Andrey Shvetsov */ - -#include "dim2_hal.h" -#include "dim2_errors.h" -#include "dim2_reg.h" -#include -#include - -/* - * Size factor for isochronous DBR buffer. - * Minimal value is 3. - */ -#define ISOC_DBR_FACTOR 3u - -/* - * Number of 32-bit units for DBR map. - * - * 1: block size is 512, max allocation is 16K - * 2: block size is 256, max allocation is 8K - * 4: block size is 128, max allocation is 4K - * 8: block size is 64, max allocation is 2K - * - * Min allocated space is block size. - * Max possible allocated space is 32 blocks. - */ -#define DBR_MAP_SIZE 2 - -/* -------------------------------------------------------------------------- */ -/* not configurable area */ - -#define CDT 0x00 -#define ADT 0x40 -#define MLB_CAT 0x80 -#define AHB_CAT 0x88 - -#define DBR_SIZE (16 * 1024) /* specified by IP */ -#define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE) - -#define ROUND_UP_TO(x, d) (DIV_ROUND_UP(x, (d)) * (d)) - -/* -------------------------------------------------------------------------- */ -/* generic helper functions and macros */ - -static inline u32 bit_mask(u8 position) -{ - return (u32)1 << position; -} - -static inline bool dim_on_error(u8 error_id, const char *error_message) -{ - dimcb_on_error(error_id, error_message); - return false; -} - -/* -------------------------------------------------------------------------- */ -/* types and local variables */ - -struct async_tx_dbr { - u8 ch_addr; - u16 rpc; - u16 wpc; - u16 rest_size; - u16 sz_queue[CDT0_RPC_MASK + 1]; -}; - -struct lld_global_vars_t { - bool dim_is_initialized; - bool mcm_is_initialized; - struct dim2_regs __iomem *dim2; /* DIM2 core base address */ - struct async_tx_dbr atx_dbr; - u32 fcnt; - u32 dbr_map[DBR_MAP_SIZE]; -}; - -static struct lld_global_vars_t g = { false }; - -/* -------------------------------------------------------------------------- */ - -static int dbr_get_mask_size(u16 size) -{ - int i; - - for (i = 0; i < 6; i++) - if (size <= (DBR_BLOCK_SIZE << i)) - return 1 << i; - return 0; -} - -/** - * Allocates DBR memory. - * @param size Allocating memory size. - * @return Offset in DBR memory by success or DBR_SIZE if out of memory. - */ -static int alloc_dbr(u16 size) -{ - int mask_size; - int i, block_idx = 0; - - if (size <= 0) - return DBR_SIZE; /* out of memory */ - - mask_size = dbr_get_mask_size(size); - if (mask_size == 0) - return DBR_SIZE; /* out of memory */ - - for (i = 0; i < DBR_MAP_SIZE; i++) { - u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE); - u32 mask = ~((~(u32)0) << blocks); - - do { - if ((g.dbr_map[i] & mask) == 0) { - g.dbr_map[i] |= mask; - return block_idx * DBR_BLOCK_SIZE; - } - block_idx += mask_size; - /* do shift left with 2 steps in case mask_size == 32 */ - mask <<= mask_size - 1; - } while ((mask <<= 1) != 0); - } - - return DBR_SIZE; /* out of memory */ -} - -static void free_dbr(int offs, int size) -{ - int block_idx = offs / DBR_BLOCK_SIZE; - u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE); - u32 mask = ~((~(u32)0) << blocks); - - mask <<= block_idx % 32; - g.dbr_map[block_idx / 32] &= ~mask; -} - -/* -------------------------------------------------------------------------- */ - -static void dim2_transfer_madr(u32 val) -{ - dimcb_io_write(&g.dim2->MADR, val); - - /* wait for transfer completion */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) - continue; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ -} - -static void dim2_clear_dbr(u16 addr, u16 size) -{ - enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 }; - - u16 const end_addr = addr + size; - u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT); - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ - dimcb_io_write(&g.dim2->MDAT0, 0); - - for (; addr < end_addr; addr++) - dim2_transfer_madr(cmd | addr); -} - -static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) -{ - dim2_transfer_madr(ctr_addr); - - return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx); -} - -static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) -{ - enum { MADR_WNR_BIT = 31 }; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ - - if (mask[0] != 0) - dimcb_io_write(&g.dim2->MDAT0, value[0]); - if (mask[1] != 0) - dimcb_io_write(&g.dim2->MDAT1, value[1]); - if (mask[2] != 0) - dimcb_io_write(&g.dim2->MDAT2, value[2]); - if (mask[3] != 0) - dimcb_io_write(&g.dim2->MDAT3, value[3]); - - dimcb_io_write(&g.dim2->MDWE0, mask[0]); - dimcb_io_write(&g.dim2->MDWE1, mask[1]); - dimcb_io_write(&g.dim2->MDWE2, mask[2]); - dimcb_io_write(&g.dim2->MDWE3, mask[3]); - - dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr); -} - -static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value) -{ - u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; - - dim2_write_ctr_mask(ctr_addr, mask, value); -} - -static inline void dim2_clear_ctr(u32 ctr_addr) -{ - u32 const value[4] = { 0, 0, 0, 0 }; - - dim2_write_ctr(ctr_addr, value); -} - -static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type, - bool read_not_write) -{ - bool isoc_fce = ch_type == CAT_CT_VAL_ISOC; - bool sync_mfe = ch_type == CAT_CT_VAL_SYNC; - u16 const cat = - (read_not_write << CAT_RNW_BIT) | - (ch_type << CAT_CT_SHIFT) | - (ch_addr << CAT_CL_SHIFT) | - (isoc_fce << CAT_FCE_BIT) | - (sync_mfe << CAT_MFE_BIT) | - (false << CAT_MT_BIT) | - (true << CAT_CE_BIT); - u8 const ctr_addr = cat_base + ch_addr / 8; - u8 const idx = (ch_addr % 8) / 2; - u8 const shift = (ch_addr % 2) * 16; - u32 mask[4] = { 0, 0, 0, 0 }; - u32 value[4] = { 0, 0, 0, 0 }; - - mask[idx] = (u32)0xFFFF << shift; - value[idx] = cat << shift; - dim2_write_ctr_mask(ctr_addr, mask, value); -} - -static void dim2_clear_cat(u8 cat_base, u8 ch_addr) -{ - u8 const ctr_addr = cat_base + ch_addr / 8; - u8 const idx = (ch_addr % 8) / 2; - u8 const shift = (ch_addr % 2) * 16; - u32 mask[4] = { 0, 0, 0, 0 }; - u32 value[4] = { 0, 0, 0, 0 }; - - mask[idx] = (u32)0xFFFF << shift; - dim2_write_ctr_mask(ctr_addr, mask, value); -} - -static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size, - u16 packet_length) -{ - u32 cdt[4] = { 0, 0, 0, 0 }; - - if (packet_length) - cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT); - - cdt[3] = - ((hw_buffer_size - 1) << CDT3_BD_SHIFT) | - (dbr_address << CDT3_BA_SHIFT); - dim2_write_ctr(CDT + ch_addr, cdt); -} - -static u16 dim2_rpc(u8 ch_addr) -{ - u32 cdt0 = dim2_read_ctr(CDT + ch_addr, 0); - - return (cdt0 >> CDT0_RPC_SHIFT) & CDT0_RPC_MASK; -} - -static void dim2_clear_cdt(u8 ch_addr) -{ - u32 cdt[4] = { 0, 0, 0, 0 }; - - dim2_write_ctr(CDT + ch_addr, cdt); -} - -static void dim2_configure_adt(u8 ch_addr) -{ - u32 adt[4] = { 0, 0, 0, 0 }; - - adt[0] = - (true << ADT0_CE_BIT) | - (true << ADT0_LE_BIT) | - (0 << ADT0_PG_BIT); - - dim2_write_ctr(ADT + ch_addr, adt); -} - -static void dim2_clear_adt(u8 ch_addr) -{ - u32 adt[4] = { 0, 0, 0, 0 }; - - dim2_write_ctr(ADT + ch_addr, adt); -} - -static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr, - u16 buffer_size) -{ - u8 const shift = idx * 16; - - u32 mask[4] = { 0, 0, 0, 0 }; - u32 adt[4] = { 0, 0, 0, 0 }; - - mask[1] = - bit_mask(ADT1_PS_BIT + shift) | - bit_mask(ADT1_RDY_BIT + shift) | - (ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift)); - adt[1] = - (true << (ADT1_PS_BIT + shift)) | - (true << (ADT1_RDY_BIT + shift)) | - ((buffer_size - 1) << (ADT1_BD_SHIFT + shift)); - - mask[idx + 2] = 0xFFFFFFFF; - adt[idx + 2] = buf_addr; - - dim2_write_ctr_mask(ADT + ch_addr, mask, adt); -} - -static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr, - u16 buffer_size) -{ - u8 const shift = idx * 16; - - u32 mask[4] = { 0, 0, 0, 0 }; - u32 adt[4] = { 0, 0, 0, 0 }; - - mask[1] = - bit_mask(ADT1_RDY_BIT + shift) | - (ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift)); - adt[1] = - (true << (ADT1_RDY_BIT + shift)) | - ((buffer_size - 1) << (ADT1_BD_SHIFT + shift)); - - mask[idx + 2] = 0xFFFFFFFF; - adt[idx + 2] = buf_addr; - - dim2_write_ctr_mask(ADT + ch_addr, mask, adt); -} - -static void dim2_clear_ctram(void) -{ - u32 ctr_addr; - - for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++) - dim2_clear_ctr(ctr_addr); -} - -static void dim2_configure_channel( - u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size, - u16 packet_length) -{ - dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length); - dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0); - - dim2_configure_adt(ch_addr); - dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1); - - /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr)); -} - -static void dim2_clear_channel(u8 ch_addr) -{ - /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); - - dim2_clear_cat(AHB_CAT, ch_addr); - dim2_clear_adt(ch_addr); - - dim2_clear_cat(MLB_CAT, ch_addr); - dim2_clear_cdt(ch_addr); - - /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); -} - -/* -------------------------------------------------------------------------- */ -/* trace async tx dbr fill state */ - -static inline u16 norm_pc(u16 pc) -{ - return pc & CDT0_RPC_MASK; -} - -static void dbrcnt_init(u8 ch_addr, u16 dbr_size) -{ - g.atx_dbr.rest_size = dbr_size; - g.atx_dbr.rpc = dim2_rpc(ch_addr); - g.atx_dbr.wpc = g.atx_dbr.rpc; -} - -static void dbrcnt_enq(int buf_sz) -{ - g.atx_dbr.rest_size -= buf_sz; - g.atx_dbr.sz_queue[norm_pc(g.atx_dbr.wpc)] = buf_sz; - g.atx_dbr.wpc++; -} - -u16 dim_dbr_space(struct dim_channel *ch) -{ - u16 cur_rpc; - struct async_tx_dbr *dbr = &g.atx_dbr; - - if (ch->addr != dbr->ch_addr) - return 0xFFFF; - - cur_rpc = dim2_rpc(ch->addr); - - while (norm_pc(dbr->rpc) != cur_rpc) { - dbr->rest_size += dbr->sz_queue[norm_pc(dbr->rpc)]; - dbr->rpc++; - } - - if ((u16)(dbr->wpc - dbr->rpc) >= CDT0_RPC_MASK) - return 0; - - return dbr->rest_size; -} - -/* -------------------------------------------------------------------------- */ -/* channel state helpers */ - -static void state_init(struct int_ch_state *state) -{ - state->request_counter = 0; - state->service_counter = 0; - - state->idx1 = 0; - state->idx2 = 0; - state->level = 0; -} - -/* -------------------------------------------------------------------------- */ -/* macro helper functions */ - -static inline bool check_channel_address(u32 ch_address) -{ - return ch_address > 0 && (ch_address % 2) == 0 && - (ch_address / 2) <= (u32)CAT_CL_MASK; -} - -static inline bool check_packet_length(u32 packet_length) -{ - u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR; - - if (packet_length <= 0) - return false; /* too small */ - - if (packet_length > max_size) - return false; /* too big */ - - if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK) - return false; /* too big */ - - return true; -} - -static inline bool check_bytes_per_frame(u32 bytes_per_frame) -{ - u16 const bd_factor = g.fcnt + 2; - u16 const max_size = ((u16)CDT3_BD_MASK + 1u) >> bd_factor; - - if (bytes_per_frame <= 0) - return false; /* too small */ - - if (bytes_per_frame > max_size) - return false; /* too big */ - - return true; -} - -static inline u16 norm_ctrl_async_buffer_size(u16 buf_size) -{ - u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u; - - if (buf_size > max_size) - return max_size; - - return buf_size; -} - -static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length) -{ - u16 n; - u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; - - if (buf_size > max_size) - buf_size = max_size; - - n = buf_size / packet_length; - - if (n < 2u) - return 0; /* too small buffer for given packet_length */ - - return packet_length * n; -} - -static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) -{ - u16 n; - u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; - u32 const unit = bytes_per_frame << g.fcnt; - - if (buf_size > max_size) - buf_size = max_size; - - n = buf_size / unit; - - if (n < 1u) - return 0; /* too small buffer for given bytes_per_frame */ - - return unit * n; -} - -static void dim2_cleanup(void) -{ - /* disable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT); - - dim2_clear_ctram(); - - /* disable mlb_int interrupt */ - dimcb_io_write(&g.dim2->MIEN, 0); - - /* clear status for all dma channels */ - dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); - - /* mask interrupts for all channels */ - dimcb_io_write(&g.dim2->ACMR0, 0); - dimcb_io_write(&g.dim2->ACMR1, 0); -} - -static void dim2_initialize(bool enable_6pin, u8 mlb_clock) -{ - dim2_cleanup(); - - /* configure and enable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, - enable_6pin << MLBC0_MLBPEN_BIT | - mlb_clock << MLBC0_MLBCLK_SHIFT | - g.fcnt << MLBC0_FCNT_SHIFT | - true << MLBC0_MLBEN_BIT); - - /* activate all HBI channels */ - dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); - - /* enable HBI */ - dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); - - /* configure DMA */ - dimcb_io_write(&g.dim2->ACTL, - ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | - true << ACTL_SCE_BIT); -} - -static bool dim2_is_mlb_locked(void) -{ - u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT); - u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) | - bit_mask(MLBC1_LOCKERR_BIT); - u32 const c1 = dimcb_io_read(&g.dim2->MLBC1); - u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; - - dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask); - return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 && - (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0; -} - -/* -------------------------------------------------------------------------- */ -/* channel help routines */ - -static inline bool service_channel(u8 ch_addr, u8 idx) -{ - u8 const shift = idx * 16; - u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1); - u32 mask[4] = { 0, 0, 0, 0 }; - u32 adt_w[4] = { 0, 0, 0, 0 }; - - if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0) - return false; - - mask[1] = - bit_mask(ADT1_DNE_BIT + shift) | - bit_mask(ADT1_ERR_BIT + shift) | - bit_mask(ADT1_RDY_BIT + shift); - dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); - - /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); - - return true; -} - -/* -------------------------------------------------------------------------- */ -/* channel init routines */ - -static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length) -{ - state_init(&ch->state); - - ch->addr = ch_addr; - - ch->packet_length = packet_length; - ch->bytes_per_frame = 0; - ch->done_sw_buffers_number = 0; -} - -static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame) -{ - state_init(&ch->state); - - ch->addr = ch_addr; - - ch->packet_length = 0; - ch->bytes_per_frame = bytes_per_frame; - ch->done_sw_buffers_number = 0; -} - -static void channel_init(struct dim_channel *ch, u8 ch_addr) -{ - state_init(&ch->state); - - ch->addr = ch_addr; - - ch->packet_length = 0; - ch->bytes_per_frame = 0; - ch->done_sw_buffers_number = 0; -} - -/* returns true if channel interrupt state is cleared */ -static bool channel_service_interrupt(struct dim_channel *ch) -{ - struct int_ch_state *const state = &ch->state; - - if (!service_channel(ch->addr, state->idx2)) - return false; - - state->idx2 ^= 1; - state->request_counter++; - return true; -} - -static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) -{ - struct int_ch_state *const state = &ch->state; - - if (buf_size <= 0) - return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size"); - - if (ch->packet_length == 0 && ch->bytes_per_frame == 0 && - buf_size != norm_ctrl_async_buffer_size(buf_size)) - return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, - "Bad control/async buffer size"); - - if (ch->packet_length && - buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length)) - return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, - "Bad isochronous buffer size"); - - if (ch->bytes_per_frame && - buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame)) - return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, - "Bad synchronous buffer size"); - - if (state->level >= 2u) - return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow"); - - ++state->level; - - if (ch->addr == g.atx_dbr.ch_addr) - dbrcnt_enq(buf_size); - - if (ch->packet_length || ch->bytes_per_frame) - dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size); - else - dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr, - buf_size); - state->idx1 ^= 1; - - return true; -} - -static u8 channel_service(struct dim_channel *ch) -{ - struct int_ch_state *const state = &ch->state; - - if (state->service_counter != state->request_counter) { - state->service_counter++; - if (state->level == 0) - return DIM_ERR_UNDERFLOW; - - --state->level; - ch->done_sw_buffers_number++; - } - - return DIM_NO_ERROR; -} - -static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number) -{ - if (buffers_number > ch->done_sw_buffers_number) - return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow"); - - ch->done_sw_buffers_number -= buffers_number; - return true; -} - -/* -------------------------------------------------------------------------- */ -/* API */ - -u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock, - u32 fcnt) -{ - g.dim_is_initialized = false; - - if (!dim_base_address) - return DIM_INIT_ERR_DIM_ADDR; - - /* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */ - /* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */ - if (mlb_clock >= 8) - return DIM_INIT_ERR_MLB_CLOCK; - - if (fcnt > MLBC0_FCNT_MAX_VAL) - return DIM_INIT_ERR_MLB_CLOCK; - - g.dim2 = dim_base_address; - g.fcnt = fcnt; - g.dbr_map[0] = 0; - g.dbr_map[1] = 0; - - dim2_initialize(mlb_clock >= 3, mlb_clock); - - g.dim_is_initialized = true; - - return DIM_NO_ERROR; -} - -void dim_shutdown(void) -{ - g.dim_is_initialized = false; - dim2_cleanup(); -} - -bool dim_get_lock_state(void) -{ - return dim2_is_mlb_locked(); -} - -static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, - u16 ch_address, u16 hw_buffer_size) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - if (!check_channel_address(ch_address)) - return DIM_INIT_ERR_CHANNEL_ADDRESS; - - ch->dbr_size = ROUND_UP_TO(hw_buffer_size, DBR_BLOCK_SIZE); - ch->dbr_addr = alloc_dbr(ch->dbr_size); - if (ch->dbr_addr >= DBR_SIZE) - return DIM_INIT_ERR_OUT_OF_MEMORY; - - channel_init(ch, ch_address / 2); - - dim2_configure_channel(ch->addr, type, is_tx, - ch->dbr_addr, ch->dbr_size, 0); - - return DIM_NO_ERROR; -} - -void dim_service_mlb_int_irq(void) -{ - dimcb_io_write(&g.dim2->MS0, 0); - dimcb_io_write(&g.dim2->MS1, 0); -} - -u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) -{ - return norm_ctrl_async_buffer_size(buf_size); -} - -/** - * Retrieves maximal possible correct buffer size for isochronous data type - * conform to given packet length and not bigger than given buffer size. - * - * Returns non-zero correct buffer size or zero by error. - */ -u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length) -{ - if (!check_packet_length(packet_length)) - return 0; - - return norm_isoc_buffer_size(buf_size, packet_length); -} - -/** - * Retrieves maximal possible correct buffer size for synchronous data type - * conform to given bytes per frame and not bigger than given buffer size. - * - * Returns non-zero correct buffer size or zero by error. - */ -u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) -{ - if (!check_bytes_per_frame(bytes_per_frame)) - return 0; - - return norm_sync_buffer_size(buf_size, bytes_per_frame); -} - -u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 max_buffer_size) -{ - return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address, - max_buffer_size); -} - -u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 max_buffer_size) -{ - u8 ret = init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address, - max_buffer_size); - - if (is_tx && !g.atx_dbr.ch_addr) { - g.atx_dbr.ch_addr = ch->addr; - dbrcnt_init(ch->addr, ch->dbr_size); - dimcb_io_write(&g.dim2->MIEN, bit_mask(20)); - } - - return ret; -} - -u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 packet_length) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - if (!check_channel_address(ch_address)) - return DIM_INIT_ERR_CHANNEL_ADDRESS; - - if (!check_packet_length(packet_length)) - return DIM_ERR_BAD_CONFIG; - - ch->dbr_size = packet_length * ISOC_DBR_FACTOR; - ch->dbr_addr = alloc_dbr(ch->dbr_size); - if (ch->dbr_addr >= DBR_SIZE) - return DIM_INIT_ERR_OUT_OF_MEMORY; - - isoc_init(ch, ch_address / 2, packet_length); - - dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr, - ch->dbr_size, packet_length); - - return DIM_NO_ERROR; -} - -u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 bytes_per_frame) -{ - u16 bd_factor = g.fcnt + 2; - - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - if (!check_channel_address(ch_address)) - return DIM_INIT_ERR_CHANNEL_ADDRESS; - - if (!check_bytes_per_frame(bytes_per_frame)) - return DIM_ERR_BAD_CONFIG; - - ch->dbr_size = bytes_per_frame << bd_factor; - ch->dbr_addr = alloc_dbr(ch->dbr_size); - if (ch->dbr_addr >= DBR_SIZE) - return DIM_INIT_ERR_OUT_OF_MEMORY; - - sync_init(ch, ch_address / 2, bytes_per_frame); - - dim2_clear_dbr(ch->dbr_addr, ch->dbr_size); - dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx, - ch->dbr_addr, ch->dbr_size, 0); - - return DIM_NO_ERROR; -} - -u8 dim_destroy_channel(struct dim_channel *ch) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - if (ch->addr == g.atx_dbr.ch_addr) { - dimcb_io_write(&g.dim2->MIEN, 0); - g.atx_dbr.ch_addr = 0; - } - - dim2_clear_channel(ch->addr); - if (ch->dbr_addr < DBR_SIZE) - free_dbr(ch->dbr_addr, ch->dbr_size); - ch->dbr_addr = DBR_SIZE; - - return DIM_NO_ERROR; -} - -void dim_service_ahb_int_irq(struct dim_channel *const *channels) -{ - bool state_changed; - - if (!g.dim_is_initialized) { - dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, - "DIM is not initialized"); - return; - } - - if (!channels) { - dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels"); - return; - } - - /* - * Use while-loop and a flag to make sure the age is changed back at - * least once, otherwise the interrupt may never come if CPU generates - * interrupt on changing age. - * This cycle runs not more than number of channels, because - * channel_service_interrupt() routine doesn't start the channel again. - */ - do { - struct dim_channel *const *ch = channels; - - state_changed = false; - - while (*ch) { - state_changed |= channel_service_interrupt(*ch); - ++ch; - } - } while (state_changed); -} - -u8 dim_service_channel(struct dim_channel *ch) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - return channel_service(ch); -} - -struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch, - struct dim_ch_state_t *state_ptr) -{ - if (!ch || !state_ptr) - return NULL; - - state_ptr->ready = ch->state.level < 2; - state_ptr->done_buffers = ch->done_sw_buffers_number; - - return state_ptr; -} - -bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, - u16 buffer_size) -{ - if (!ch) - return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, - "Bad channel"); - - return channel_start(ch, buffer_addr, buffer_size); -} - -bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number) -{ - if (!ch) - return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, - "Bad channel"); - - return channel_detach_buffers(ch, buffers_number); -} diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h deleted file mode 100644 index fce9ae96121b..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dim2_hal.h - DIM2 HAL interface - * (MediaLB, Device Interface Macro IP, OS62420) - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - */ - -#ifndef _DIM2_HAL_H -#define _DIM2_HAL_H - -#include -#include "dim2_reg.h" - -/* - * The values below are specified in the hardware specification. - * So, they should not be changed until the hardware specification changes. - */ -enum mlb_clk_speed { - CLK_256FS = 0, - CLK_512FS = 1, - CLK_1024FS = 2, - CLK_2048FS = 3, - CLK_3072FS = 4, - CLK_4096FS = 5, - CLK_6144FS = 6, - CLK_8192FS = 7, -}; - -struct dim_ch_state_t { - bool ready; /* Shows readiness to enqueue next buffer */ - u16 done_buffers; /* Number of completed buffers */ -}; - -struct int_ch_state { - /* changed only in interrupt context */ - volatile int request_counter; - - /* changed only in task context */ - volatile int service_counter; - - u8 idx1; - u8 idx2; - u8 level; /* [0..2], buffering level */ -}; - -struct dim_channel { - struct int_ch_state state; - u8 addr; - u16 dbr_addr; - u16 dbr_size; - u16 packet_length; /*< Isochronous packet length in bytes. */ - u16 bytes_per_frame; /*< Synchronous bytes per frame. */ - u16 done_sw_buffers_number; /*< Done software buffers number. */ -}; - -u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock, - u32 fcnt); - -void dim_shutdown(void); - -bool dim_get_lock_state(void); - -u16 dim_norm_ctrl_async_buffer_size(u16 buf_size); - -u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length); - -u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame); - -u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 max_buffer_size); - -u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 max_buffer_size); - -u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 packet_length); - -u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 bytes_per_frame); - -u8 dim_destroy_channel(struct dim_channel *ch); - -void dim_service_mlb_int_irq(void); - -void dim_service_ahb_int_irq(struct dim_channel *const *channels); - -u8 dim_service_channel(struct dim_channel *ch); - -struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch, - struct dim_ch_state_t *state_ptr); - -u16 dim_dbr_space(struct dim_channel *ch); - -bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, - u16 buffer_size); - -bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); - -u32 dimcb_io_read(u32 __iomem *ptr32); - -void dimcb_io_write(u32 __iomem *ptr32, u32 value); - -void dimcb_on_error(u8 error_id, const char *error_message); - -#endif /* _DIM2_HAL_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c deleted file mode 100644 index fedd2d06742a..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ /dev/null @@ -1,912 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module - * - * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "most/core.h" -#include "dim2_hal.h" -#include "dim2_hdm.h" -#include "dim2_errors.h" -#include "dim2_sysfs.h" - -#define DMA_CHANNELS (32 - 1) /* channel 0 is a system channel */ - -#define MAX_BUFFERS_PACKET 32 -#define MAX_BUFFERS_STREAMING 32 -#define MAX_BUF_SIZE_PACKET 2048 -#define MAX_BUF_SIZE_STREAMING (8 * 1024) - -/* command line parameter to select clock speed */ -static char *clock_speed; -module_param(clock_speed, charp, 0000); -MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed"); - -/* - * The parameter representing the number of frames per sub-buffer for - * synchronous channels. Valid values: [0 .. 6]. - * - * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per - * sub-buffer 1, 2, 4, 8, 16, 32, 64. - */ -static u8 fcnt = 4; /* (1 << fcnt) frames per subbuffer */ -module_param(fcnt, byte, 0000); -MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2"); - -static DEFINE_SPINLOCK(dim_lock); - -static void dim2_tasklet_fn(unsigned long data); -static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0); - -/** - * struct hdm_channel - private structure to keep channel specific data - * @is_initialized: identifier to know whether the channel is initialized - * @ch: HAL specific channel data - * @pending_list: list to keep MBO's before starting transfer - * @started_list: list to keep MBO's after starting transfer - * @direction: channel direction (TX or RX) - * @data_type: channel data type - */ -struct hdm_channel { - char name[sizeof "caNNN"]; - bool is_initialized; - struct dim_channel ch; - struct list_head pending_list; /* before dim_enqueue_buffer() */ - struct list_head started_list; /* after dim_enqueue_buffer() */ - enum most_channel_direction direction; - enum most_channel_data_type data_type; -}; - -/** - * struct dim2_hdm - private structure to keep interface specific data - * @hch: an array of channel specific data - * @most_iface: most interface structure - * @capabilities: an array of channel capability data - * @io_base: I/O register base address - * @clk_speed: user selectable (through command line parameter) clock speed - * @netinfo_task: thread to deliver network status - * @netinfo_waitq: waitq for the thread to sleep - * @deliver_netinfo: to identify whether network status received - * @mac_addrs: INIC mac address - * @link_state: network link state - * @atx_idx: index of async tx channel - */ -struct dim2_hdm { - struct hdm_channel hch[DMA_CHANNELS]; - struct most_channel_capability capabilities[DMA_CHANNELS]; - struct most_interface most_iface; - char name[16 + sizeof "dim2-"]; - void __iomem *io_base; - int clk_speed; - struct task_struct *netinfo_task; - wait_queue_head_t netinfo_waitq; - int deliver_netinfo; - unsigned char mac_addrs[6]; - unsigned char link_state; - int atx_idx; - struct medialb_bus bus; - void (*on_netinfo)(struct most_interface *, - unsigned char, unsigned char *); -}; - -#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface) - -/* Macro to identify a network status message */ -#define PACKET_IS_NET_INFO(p) \ - (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ - ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) - -bool dim2_sysfs_get_state_cb(void) -{ - bool state; - unsigned long flags; - - spin_lock_irqsave(&dim_lock, flags); - state = dim_get_lock_state(); - spin_unlock_irqrestore(&dim_lock, flags); - - return state; -} - -/** - * dimcb_io_read - callback from HAL to read an I/O register - * @ptr32: register address - */ -u32 dimcb_io_read(u32 __iomem *ptr32) -{ - return readl(ptr32); -} - -/** - * dimcb_io_write - callback from HAL to write value to an I/O register - * @ptr32: register address - * @value: value to write - */ -void dimcb_io_write(u32 __iomem *ptr32, u32 value) -{ - writel(value, ptr32); -} - -/** - * dimcb_on_error - callback from HAL to report miscommunication between - * HDM and HAL - * @error_id: Error ID - * @error_message: Error message. Some text in a free format - */ -void dimcb_on_error(u8 error_id, const char *error_message) -{ - pr_err("dimcb_on_error: error_id - %d, error_message - %s\n", error_id, - error_message); -} - -/** - * startup_dim - initialize the dim2 interface - * @pdev: platform device - * - * Get the value of command line parameter "clock_speed" if given or use the - * default value, enable the clock and PLL, and initialize the dim2 interface. - */ -static int startup_dim(struct platform_device *pdev) -{ - struct dim2_hdm *dev = platform_get_drvdata(pdev); - struct dim2_platform_data *pdata = pdev->dev.platform_data; - u8 hal_ret; - - dev->clk_speed = -1; - - if (clock_speed) { - if (!strcmp(clock_speed, "256fs")) - dev->clk_speed = CLK_256FS; - else if (!strcmp(clock_speed, "512fs")) - dev->clk_speed = CLK_512FS; - else if (!strcmp(clock_speed, "1024fs")) - dev->clk_speed = CLK_1024FS; - else if (!strcmp(clock_speed, "2048fs")) - dev->clk_speed = CLK_2048FS; - else if (!strcmp(clock_speed, "3072fs")) - dev->clk_speed = CLK_3072FS; - else if (!strcmp(clock_speed, "4096fs")) - dev->clk_speed = CLK_4096FS; - else if (!strcmp(clock_speed, "6144fs")) - dev->clk_speed = CLK_6144FS; - else if (!strcmp(clock_speed, "8192fs")) - dev->clk_speed = CLK_8192FS; - } - - if (dev->clk_speed == -1) { - pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n"); - dev->clk_speed = CLK_3072FS; - } else { - pr_info("Selected clock speed: %s\n", clock_speed); - } - if (pdata && pdata->init) { - int ret = pdata->init(pdata, dev->io_base, dev->clk_speed); - - if (ret) - return ret; - } - - pr_info("sync: num of frames per sub-buffer: %u\n", fcnt); - hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); - if (hal_ret != DIM_NO_ERROR) { - pr_err("dim_startup failed: %d\n", hal_ret); - if (pdata && pdata->destroy) - pdata->destroy(pdata); - return -ENODEV; - } - - return 0; -} - -/** - * try_start_dim_transfer - try to transfer a buffer on a channel - * @hdm_ch: channel specific data - * - * Transfer a buffer from pending_list if the channel is ready - */ -static int try_start_dim_transfer(struct hdm_channel *hdm_ch) -{ - u16 buf_size; - struct list_head *head = &hdm_ch->pending_list; - struct mbo *mbo; - unsigned long flags; - struct dim_ch_state_t st; - - BUG_ON(!hdm_ch); - BUG_ON(!hdm_ch->is_initialized); - - spin_lock_irqsave(&dim_lock, flags); - if (list_empty(head)) { - spin_unlock_irqrestore(&dim_lock, flags); - return -EAGAIN; - } - - if (!dim_get_channel_state(&hdm_ch->ch, &st)->ready) { - spin_unlock_irqrestore(&dim_lock, flags); - return -EAGAIN; - } - - mbo = list_first_entry(head, struct mbo, list); - buf_size = mbo->buffer_length; - - if (dim_dbr_space(&hdm_ch->ch) < buf_size) { - spin_unlock_irqrestore(&dim_lock, flags); - return -EAGAIN; - } - - BUG_ON(mbo->bus_address == 0); - if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) { - list_del(head->next); - spin_unlock_irqrestore(&dim_lock, flags); - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - mbo->complete(mbo); - return -EFAULT; - } - - list_move_tail(head->next, &hdm_ch->started_list); - spin_unlock_irqrestore(&dim_lock, flags); - - return 0; -} - -/** - * deliver_netinfo_thread - thread to deliver network status to mostcore - * @data: private data - * - * Wait for network status and deliver it to mostcore once it is received - */ -static int deliver_netinfo_thread(void *data) -{ - struct dim2_hdm *dev = data; - - while (!kthread_should_stop()) { - wait_event_interruptible(dev->netinfo_waitq, - dev->deliver_netinfo || - kthread_should_stop()); - - if (dev->deliver_netinfo) { - dev->deliver_netinfo--; - if (dev->on_netinfo) { - dev->on_netinfo(&dev->most_iface, - dev->link_state, - dev->mac_addrs); - } - } - } - - return 0; -} - -/** - * retrieve_netinfo - retrieve network status from received buffer - * @dev: private data - * @mbo: received MBO - * - * Parse the message in buffer and get node address, link state, MAC address. - * Wake up a thread to deliver this status to mostcore - */ -static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo) -{ - u8 *data = mbo->virt_address; - - pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]); - dev->link_state = data[18]; - pr_info("NIState: %d\n", dev->link_state); - memcpy(dev->mac_addrs, data + 19, 6); - dev->deliver_netinfo++; - wake_up_interruptible(&dev->netinfo_waitq); -} - -/** - * service_done_flag - handle completed buffers - * @dev: private data - * @ch_idx: channel index - * - * Return back the completed buffers to mostcore, using completion callback - */ -static void service_done_flag(struct dim2_hdm *dev, int ch_idx) -{ - struct hdm_channel *hdm_ch = dev->hch + ch_idx; - struct dim_ch_state_t st; - struct list_head *head; - struct mbo *mbo; - int done_buffers; - unsigned long flags; - u8 *data; - - BUG_ON(!hdm_ch); - BUG_ON(!hdm_ch->is_initialized); - - spin_lock_irqsave(&dim_lock, flags); - - done_buffers = dim_get_channel_state(&hdm_ch->ch, &st)->done_buffers; - if (!done_buffers) { - spin_unlock_irqrestore(&dim_lock, flags); - return; - } - - if (!dim_detach_buffers(&hdm_ch->ch, done_buffers)) { - spin_unlock_irqrestore(&dim_lock, flags); - return; - } - spin_unlock_irqrestore(&dim_lock, flags); - - head = &hdm_ch->started_list; - - while (done_buffers) { - spin_lock_irqsave(&dim_lock, flags); - if (list_empty(head)) { - spin_unlock_irqrestore(&dim_lock, flags); - pr_crit("hard error: started_mbo list is empty whereas DIM2 has sent buffers\n"); - break; - } - - mbo = list_first_entry(head, struct mbo, list); - list_del(head->next); - spin_unlock_irqrestore(&dim_lock, flags); - - data = mbo->virt_address; - - if (hdm_ch->data_type == MOST_CH_ASYNC && - hdm_ch->direction == MOST_CH_RX && - PACKET_IS_NET_INFO(data)) { - retrieve_netinfo(dev, mbo); - - spin_lock_irqsave(&dim_lock, flags); - list_add_tail(&mbo->list, &hdm_ch->pending_list); - spin_unlock_irqrestore(&dim_lock, flags); - } else { - if (hdm_ch->data_type == MOST_CH_CONTROL || - hdm_ch->data_type == MOST_CH_ASYNC) { - u32 const data_size = - (u32)data[0] * 256 + data[1] + 2; - - mbo->processed_length = - min_t(u32, data_size, - mbo->buffer_length); - } else { - mbo->processed_length = mbo->buffer_length; - } - mbo->status = MBO_SUCCESS; - mbo->complete(mbo); - } - - done_buffers--; - } -} - -static struct dim_channel **get_active_channels(struct dim2_hdm *dev, - struct dim_channel **buffer) -{ - int idx = 0; - int ch_idx; - - for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) { - if (dev->hch[ch_idx].is_initialized) - buffer[idx++] = &dev->hch[ch_idx].ch; - } - buffer[idx++] = NULL; - - return buffer; -} - -static irqreturn_t dim2_mlb_isr(int irq, void *_dev) -{ - struct dim2_hdm *dev = _dev; - unsigned long flags; - - spin_lock_irqsave(&dim_lock, flags); - dim_service_mlb_int_irq(); - spin_unlock_irqrestore(&dim_lock, flags); - - if (dev->atx_idx >= 0 && dev->hch[dev->atx_idx].is_initialized) - while (!try_start_dim_transfer(dev->hch + dev->atx_idx)) - continue; - - return IRQ_HANDLED; -} - -/** - * dim2_tasklet_fn - tasklet function - * @data: private data - * - * Service each initialized channel, if needed - */ -static void dim2_tasklet_fn(unsigned long data) -{ - struct dim2_hdm *dev = (struct dim2_hdm *)data; - unsigned long flags; - int ch_idx; - - for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) { - if (!dev->hch[ch_idx].is_initialized) - continue; - - spin_lock_irqsave(&dim_lock, flags); - dim_service_channel(&dev->hch[ch_idx].ch); - spin_unlock_irqrestore(&dim_lock, flags); - - service_done_flag(dev, ch_idx); - while (!try_start_dim_transfer(dev->hch + ch_idx)) - continue; - } -} - -/** - * dim2_ahb_isr - interrupt service routine - * @irq: irq number - * @_dev: private data - * - * Acknowledge the interrupt and schedule a tasklet to service channels. - * Return IRQ_HANDLED. - */ -static irqreturn_t dim2_ahb_isr(int irq, void *_dev) -{ - struct dim2_hdm *dev = _dev; - struct dim_channel *buffer[DMA_CHANNELS + 1]; - unsigned long flags; - - spin_lock_irqsave(&dim_lock, flags); - dim_service_ahb_int_irq(get_active_channels(dev, buffer)); - spin_unlock_irqrestore(&dim_lock, flags); - - dim2_tasklet.data = (unsigned long)dev; - tasklet_schedule(&dim2_tasklet); - return IRQ_HANDLED; -} - -/** - * complete_all_mbos - complete MBO's in a list - * @head: list head - * - * Delete all the entries in list and return back MBO's to mostcore using - * completion call back. - */ -static void complete_all_mbos(struct list_head *head) -{ - unsigned long flags; - struct mbo *mbo; - - for (;;) { - spin_lock_irqsave(&dim_lock, flags); - if (list_empty(head)) { - spin_unlock_irqrestore(&dim_lock, flags); - break; - } - - mbo = list_first_entry(head, struct mbo, list); - list_del(head->next); - spin_unlock_irqrestore(&dim_lock, flags); - - mbo->processed_length = 0; - mbo->status = MBO_E_CLOSE; - mbo->complete(mbo); - } -} - -/** - * configure_channel - initialize a channel - * @iface: interface the channel belongs to - * @channel: channel to be configured - * @channel_config: structure that holds the configuration information - * - * Receives configuration information from mostcore and initialize - * the corresponding channel. Return 0 on success, negative on failure. - */ -static int configure_channel(struct most_interface *most_iface, int ch_idx, - struct most_channel_config *ccfg) -{ - struct dim2_hdm *dev = iface_to_hdm(most_iface); - bool const is_tx = ccfg->direction == MOST_CH_TX; - u16 const sub_size = ccfg->subbuffer_size; - u16 const buf_size = ccfg->buffer_size; - u16 new_size; - unsigned long flags; - u8 hal_ret; - int const ch_addr = ch_idx * 2 + 2; - struct hdm_channel *const hdm_ch = dev->hch + ch_idx; - - BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); - - if (hdm_ch->is_initialized) - return -EPERM; - - switch (ccfg->data_type) { - case MOST_CH_CONTROL: - new_size = dim_norm_ctrl_async_buffer_size(buf_size); - if (new_size == 0) { - pr_err("%s: too small buffer size\n", hdm_ch->name); - return -EINVAL; - } - ccfg->buffer_size = new_size; - if (new_size != buf_size) - pr_warn("%s: fixed buffer size (%d -> %d)\n", - hdm_ch->name, buf_size, new_size); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr, - is_tx ? new_size * 2 : new_size); - break; - case MOST_CH_ASYNC: - new_size = dim_norm_ctrl_async_buffer_size(buf_size); - if (new_size == 0) { - pr_err("%s: too small buffer size\n", hdm_ch->name); - return -EINVAL; - } - ccfg->buffer_size = new_size; - if (new_size != buf_size) - pr_warn("%s: fixed buffer size (%d -> %d)\n", - hdm_ch->name, buf_size, new_size); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, - is_tx ? new_size * 2 : new_size); - break; - case MOST_CH_ISOC: - new_size = dim_norm_isoc_buffer_size(buf_size, sub_size); - if (new_size == 0) { - pr_err("%s: invalid sub-buffer size or too small buffer size\n", - hdm_ch->name); - return -EINVAL; - } - ccfg->buffer_size = new_size; - if (new_size != buf_size) - pr_warn("%s: fixed buffer size (%d -> %d)\n", - hdm_ch->name, buf_size, new_size); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_isoc(&hdm_ch->ch, is_tx, ch_addr, sub_size); - break; - case MOST_CH_SYNC: - new_size = dim_norm_sync_buffer_size(buf_size, sub_size); - if (new_size == 0) { - pr_err("%s: invalid sub-buffer size or too small buffer size\n", - hdm_ch->name); - return -EINVAL; - } - ccfg->buffer_size = new_size; - if (new_size != buf_size) - pr_warn("%s: fixed buffer size (%d -> %d)\n", - hdm_ch->name, buf_size, new_size); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_sync(&hdm_ch->ch, is_tx, ch_addr, sub_size); - break; - default: - pr_err("%s: configure failed, bad channel type: %d\n", - hdm_ch->name, ccfg->data_type); - return -EINVAL; - } - - if (hal_ret != DIM_NO_ERROR) { - spin_unlock_irqrestore(&dim_lock, flags); - pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n", - hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx); - return -ENODEV; - } - - hdm_ch->data_type = ccfg->data_type; - hdm_ch->direction = ccfg->direction; - hdm_ch->is_initialized = true; - - if (hdm_ch->data_type == MOST_CH_ASYNC && - hdm_ch->direction == MOST_CH_TX && - dev->atx_idx < 0) - dev->atx_idx = ch_idx; - - spin_unlock_irqrestore(&dim_lock, flags); - - return 0; -} - -/** - * enqueue - enqueue a buffer for data transfer - * @iface: intended interface - * @channel: ID of the channel the buffer is intended for - * @mbo: pointer to the buffer object - * - * Push the buffer into pending_list and try to transfer one buffer from - * pending_list. Return 0 on success, negative on failure. - */ -static int enqueue(struct most_interface *most_iface, int ch_idx, - struct mbo *mbo) -{ - struct dim2_hdm *dev = iface_to_hdm(most_iface); - struct hdm_channel *hdm_ch = dev->hch + ch_idx; - unsigned long flags; - - BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); - - if (!hdm_ch->is_initialized) - return -EPERM; - - if (mbo->bus_address == 0) - return -EFAULT; - - spin_lock_irqsave(&dim_lock, flags); - list_add_tail(&mbo->list, &hdm_ch->pending_list); - spin_unlock_irqrestore(&dim_lock, flags); - - (void)try_start_dim_transfer(hdm_ch); - - return 0; -} - -/** - * request_netinfo - triggers retrieving of network info - * @iface: pointer to the interface - * @channel_id: corresponding channel ID - * - * Send a command to INIC which triggers retrieving of network info by means of - * "Message exchange over MDP/MEP". Return 0 on success, negative on failure. - */ -static void request_netinfo(struct most_interface *most_iface, int ch_idx, - void (*on_netinfo)(struct most_interface *, - unsigned char, unsigned char *)) -{ - struct dim2_hdm *dev = iface_to_hdm(most_iface); - struct mbo *mbo; - u8 *data; - - dev->on_netinfo = on_netinfo; - if (!on_netinfo) - return; - - if (dev->atx_idx < 0) { - pr_err("Async Tx Not initialized\n"); - return; - } - - mbo = most_get_mbo(&dev->most_iface, dev->atx_idx, NULL); - if (!mbo) - return; - - mbo->buffer_length = 5; - - data = mbo->virt_address; - - data[0] = 0x00; /* PML High byte */ - data[1] = 0x03; /* PML Low byte */ - data[2] = 0x02; /* PMHL */ - data[3] = 0x08; /* FPH */ - data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */ - - most_submit_mbo(mbo); -} - -/** - * poison_channel - poison buffers of a channel - * @iface: pointer to the interface the channel to be poisoned belongs to - * @channel_id: corresponding channel ID - * - * Destroy a channel and complete all the buffers in both started_list & - * pending_list. Return 0 on success, negative on failure. - */ -static int poison_channel(struct most_interface *most_iface, int ch_idx) -{ - struct dim2_hdm *dev = iface_to_hdm(most_iface); - struct hdm_channel *hdm_ch = dev->hch + ch_idx; - unsigned long flags; - u8 hal_ret; - int ret = 0; - - BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); - - if (!hdm_ch->is_initialized) - return -EPERM; - - tasklet_disable(&dim2_tasklet); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_destroy_channel(&hdm_ch->ch); - hdm_ch->is_initialized = false; - if (ch_idx == dev->atx_idx) - dev->atx_idx = -1; - spin_unlock_irqrestore(&dim_lock, flags); - tasklet_enable(&dim2_tasklet); - if (hal_ret != DIM_NO_ERROR) { - pr_err("HAL Failed to close channel %s\n", hdm_ch->name); - ret = -EFAULT; - } - - complete_all_mbos(&hdm_ch->started_list); - complete_all_mbos(&hdm_ch->pending_list); - - return ret; -} - -/* - * dim2_probe - dim2 probe handler - * @pdev: platform device structure - * - * Register the dim2 interface with mostcore and initialize it. - * Return 0 on success, negative on failure. - */ -static int dim2_probe(struct platform_device *pdev) -{ - struct dim2_hdm *dev; - struct resource *res; - int ret, i; - struct kobject *kobj; - int irq; - - dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - dev->atx_idx = -1; - - platform_set_drvdata(pdev, dev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->io_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(dev->io_base)) - return PTR_ERR(dev->io_base); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq); - return irq; - } - - ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0, - "dim2_ahb0_int", dev); - if (ret) { - dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq); - return ret; - } - - irq = platform_get_irq(pdev, 1); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq); - return irq; - } - - ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0, - "dim2_mlb_int", dev); - if (ret) { - dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq); - return ret; - } - - init_waitqueue_head(&dev->netinfo_waitq); - dev->deliver_netinfo = 0; - dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev, - "dim2_netinfo"); - if (IS_ERR(dev->netinfo_task)) - return PTR_ERR(dev->netinfo_task); - - for (i = 0; i < DMA_CHANNELS; i++) { - struct most_channel_capability *cap = dev->capabilities + i; - struct hdm_channel *hdm_ch = dev->hch + i; - - INIT_LIST_HEAD(&hdm_ch->pending_list); - INIT_LIST_HEAD(&hdm_ch->started_list); - hdm_ch->is_initialized = false; - snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2); - - cap->name_suffix = hdm_ch->name; - cap->direction = MOST_CH_RX | MOST_CH_TX; - cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | - MOST_CH_ISOC | MOST_CH_SYNC; - cap->num_buffers_packet = MAX_BUFFERS_PACKET; - cap->buffer_size_packet = MAX_BUF_SIZE_PACKET; - cap->num_buffers_streaming = MAX_BUFFERS_STREAMING; - cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING; - } - - { - const char *fmt; - - if (sizeof(res->start) == sizeof(long long)) - fmt = "dim2-%016llx"; - else if (sizeof(res->start) == sizeof(long)) - fmt = "dim2-%016lx"; - else - fmt = "dim2-%016x"; - - snprintf(dev->name, sizeof(dev->name), fmt, res->start); - } - - dev->most_iface.interface = ITYPE_MEDIALB_DIM2; - dev->most_iface.description = dev->name; - dev->most_iface.num_channels = DMA_CHANNELS; - dev->most_iface.channel_vector = dev->capabilities; - dev->most_iface.configure = configure_channel; - dev->most_iface.enqueue = enqueue; - dev->most_iface.poison_channel = poison_channel; - dev->most_iface.request_netinfo = request_netinfo; - - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { - ret = PTR_ERR(kobj); - dev_err(&pdev->dev, "failed to register MOST interface\n"); - goto err_stop_thread; - } - - ret = dim2_sysfs_probe(&dev->bus, kobj); - if (ret) - goto err_unreg_iface; - - ret = startup_dim(pdev); - if (ret) { - dev_err(&pdev->dev, "failed to initialize DIM2\n"); - goto err_destroy_bus; - } - - return 0; - -err_destroy_bus: - dim2_sysfs_destroy(&dev->bus); -err_unreg_iface: - most_deregister_interface(&dev->most_iface); -err_stop_thread: - kthread_stop(dev->netinfo_task); - - return ret; -} - -/** - * dim2_remove - dim2 remove handler - * @pdev: platform device structure - * - * Unregister the interface from mostcore - */ -static int dim2_remove(struct platform_device *pdev) -{ - struct dim2_hdm *dev = platform_get_drvdata(pdev); - struct dim2_platform_data *pdata = pdev->dev.platform_data; - unsigned long flags; - - spin_lock_irqsave(&dim_lock, flags); - dim_shutdown(); - spin_unlock_irqrestore(&dim_lock, flags); - - if (pdata && pdata->destroy) - pdata->destroy(pdata); - - dim2_sysfs_destroy(&dev->bus); - most_deregister_interface(&dev->most_iface); - kthread_stop(dev->netinfo_task); - - /* - * break link to local platform_device_id struct - * to prevent crash by unload platform device module - */ - pdev->id_entry = NULL; - - return 0; -} - -static const struct platform_device_id dim2_id[] = { - { "medialb_dim2" }, - { }, /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(platform, dim2_id); - -static struct platform_driver dim2_driver = { - .probe = dim2_probe, - .remove = dim2_remove, - .id_table = dim2_id, - .driver = { - .name = "hdm_dim2", - }, -}; - -module_platform_driver(dim2_driver); - -MODULE_AUTHOR("Jain Roy Ambi "); -MODULE_AUTHOR("Andrey Shvetsov "); -MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h deleted file mode 100644 index 5f380b648bd7..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dim2_hdm.h - MediaLB DIM2 HDM Header - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - */ - -#ifndef DIM2_HDM_H -#define DIM2_HDM_H - -struct device; - -/* platform dependent data for dim2 interface */ -struct dim2_platform_data { - int (*init)(struct dim2_platform_data *pd, void __iomem *io_base, - int clk_speed); - void (*destroy)(struct dim2_platform_data *pd); - void *priv; -}; - -#endif /* DIM2_HDM_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h deleted file mode 100644 index 2b2fca4f6451..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_reg.h +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dim2_reg.h - Definitions for registers of DIM2 - * (MediaLB, Device Interface Macro IP, OS62420) - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - */ - -#ifndef DIM2_OS62420_H -#define DIM2_OS62420_H - -#include - -struct dim2_regs { - /* 0x00 */ u32 MLBC0; - /* 0x01 */ u32 rsvd0[1]; - /* 0x02 */ u32 MLBPC0; - /* 0x03 */ u32 MS0; - /* 0x04 */ u32 rsvd1[1]; - /* 0x05 */ u32 MS1; - /* 0x06 */ u32 rsvd2[2]; - /* 0x08 */ u32 MSS; - /* 0x09 */ u32 MSD; - /* 0x0A */ u32 rsvd3[1]; - /* 0x0B */ u32 MIEN; - /* 0x0C */ u32 rsvd4[1]; - /* 0x0D */ u32 MLBPC2; - /* 0x0E */ u32 MLBPC1; - /* 0x0F */ u32 MLBC1; - /* 0x10 */ u32 rsvd5[0x10]; - /* 0x20 */ u32 HCTL; - /* 0x21 */ u32 rsvd6[1]; - /* 0x22 */ u32 HCMR0; - /* 0x23 */ u32 HCMR1; - /* 0x24 */ u32 HCER0; - /* 0x25 */ u32 HCER1; - /* 0x26 */ u32 HCBR0; - /* 0x27 */ u32 HCBR1; - /* 0x28 */ u32 rsvd7[8]; - /* 0x30 */ u32 MDAT0; - /* 0x31 */ u32 MDAT1; - /* 0x32 */ u32 MDAT2; - /* 0x33 */ u32 MDAT3; - /* 0x34 */ u32 MDWE0; - /* 0x35 */ u32 MDWE1; - /* 0x36 */ u32 MDWE2; - /* 0x37 */ u32 MDWE3; - /* 0x38 */ u32 MCTL; - /* 0x39 */ u32 MADR; - /* 0x3A */ u32 rsvd8[0xB6]; - /* 0xF0 */ u32 ACTL; - /* 0xF1 */ u32 rsvd9[3]; - /* 0xF4 */ u32 ACSR0; - /* 0xF5 */ u32 ACSR1; - /* 0xF6 */ u32 ACMR0; - /* 0xF7 */ u32 ACMR1; -}; - -#define DIM2_MASK(n) (~((~(u32)0) << (n))) - -enum { - MLBC0_MLBLK_BIT = 7, - - MLBC0_MLBPEN_BIT = 5, - - MLBC0_MLBCLK_SHIFT = 2, - MLBC0_MLBCLK_VAL_256FS = 0, - MLBC0_MLBCLK_VAL_512FS = 1, - MLBC0_MLBCLK_VAL_1024FS = 2, - MLBC0_MLBCLK_VAL_2048FS = 3, - - MLBC0_FCNT_SHIFT = 15, - MLBC0_FCNT_MASK = 7, - MLBC0_FCNT_MAX_VAL = 6, - - MLBC0_MLBEN_BIT = 0, - - MIEN_CTX_BREAK_BIT = 29, - MIEN_CTX_PE_BIT = 28, - MIEN_CTX_DONE_BIT = 27, - - MIEN_CRX_BREAK_BIT = 26, - MIEN_CRX_PE_BIT = 25, - MIEN_CRX_DONE_BIT = 24, - - MIEN_ATX_BREAK_BIT = 22, - MIEN_ATX_PE_BIT = 21, - MIEN_ATX_DONE_BIT = 20, - - MIEN_ARX_BREAK_BIT = 19, - MIEN_ARX_PE_BIT = 18, - MIEN_ARX_DONE_BIT = 17, - - MIEN_SYNC_PE_BIT = 16, - - MIEN_ISOC_BUFO_BIT = 1, - MIEN_ISOC_PE_BIT = 0, - - MLBC1_NDA_SHIFT = 8, - MLBC1_NDA_MASK = 0xFF, - - MLBC1_CLKMERR_BIT = 7, - MLBC1_LOCKERR_BIT = 6, - - ACTL_DMA_MODE_BIT = 2, - ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0, - ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1, - ACTL_SCE_BIT = 0, - - HCTL_EN_BIT = 15 -}; - -enum { - CDT0_RPC_SHIFT = 16 + 11, - CDT0_RPC_MASK = DIM2_MASK(5), - - CDT1_BS_ISOC_SHIFT = 0, - CDT1_BS_ISOC_MASK = DIM2_MASK(9), - - CDT3_BD_SHIFT = 0, - CDT3_BD_MASK = DIM2_MASK(12), - CDT3_BD_ISOC_MASK = DIM2_MASK(13), - CDT3_BA_SHIFT = 16, - - ADT0_CE_BIT = 15, - ADT0_LE_BIT = 14, - ADT0_PG_BIT = 13, - - ADT1_RDY_BIT = 15, - ADT1_DNE_BIT = 14, - ADT1_ERR_BIT = 13, - ADT1_PS_BIT = 12, - ADT1_MEP_BIT = 11, - ADT1_BD_SHIFT = 0, - ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11), - ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13), - - CAT_FCE_BIT = 14, - CAT_MFE_BIT = 14, - - CAT_MT_BIT = 13, - - CAT_RNW_BIT = 12, - - CAT_CE_BIT = 11, - - CAT_CT_SHIFT = 8, - CAT_CT_VAL_SYNC = 0, - CAT_CT_VAL_CONTROL = 1, - CAT_CT_VAL_ASYNC = 2, - CAT_CT_VAL_ISOC = 3, - - CAT_CL_SHIFT = 0, - CAT_CL_MASK = DIM2_MASK(6) -}; - -#endif /* DIM2_OS62420_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c deleted file mode 100644 index 3a2ad355cab1..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.c +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dim2_sysfs.c - MediaLB sysfs information - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - */ - -/* Author: Andrey Shvetsov */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include "dim2_sysfs.h" - -struct bus_attr { - struct attribute attr; - ssize_t (*show)(struct medialb_bus *bus, char *buf); - ssize_t (*store)(struct medialb_bus *bus, const char *buf, - size_t count); -}; - -static ssize_t state_show(struct medialb_bus *bus, char *buf) -{ - bool state = dim2_sysfs_get_state_cb(); - - return sprintf(buf, "%s\n", state ? "locked" : ""); -} - -static struct bus_attr state_attr = __ATTR_RO(state); - -static struct attribute *bus_default_attrs[] = { - &state_attr.attr, - NULL, -}; - -static const struct attribute_group bus_attr_group = { - .attrs = bus_default_attrs, -}; - -static void bus_kobj_release(struct kobject *kobj) -{ -} - -static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->show) - return -EIO; - - return xattr->show(bus, buf); -} - -static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->store) - return -EIO; - - return xattr->store(bus, buf, count); -} - -static struct sysfs_ops const bus_kobj_sysfs_ops = { - .show = bus_kobj_attr_show, - .store = bus_kobj_attr_store, -}; - -static struct kobj_type bus_ktype = { - .release = bus_kobj_release, - .sysfs_ops = &bus_kobj_sysfs_ops, -}; - -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj) -{ - int err; - - kobject_init(&bus->kobj_group, &bus_ktype); - err = kobject_add(&bus->kobj_group, parent_kobj, "bus"); - if (err) { - pr_err("kobject_add() failed: %d\n", err); - goto err_kobject_add; - } - - err = sysfs_create_group(&bus->kobj_group, &bus_attr_group); - if (err) { - pr_err("sysfs_create_group() failed: %d\n", err); - goto err_create_group; - } - - return 0; - -err_create_group: - kobject_put(&bus->kobj_group); - -err_kobject_add: - return err; -} - -void dim2_sysfs_destroy(struct medialb_bus *bus) -{ - kobject_put(&bus->kobj_group); -} diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h deleted file mode 100644 index e46dc4ba3946..000000000000 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.h +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dim2_sysfs.h - MediaLB sysfs information - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - */ - -/* Author: Andrey Shvetsov */ - -#ifndef DIM2_SYSFS_H -#define DIM2_SYSFS_H - -#include - -struct medialb_bus { - struct kobject kobj_group; -}; - -struct dim2_hdm; - -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj); -void dim2_sysfs_destroy(struct medialb_bus *bus); - -/* - * callback, - * must deliver MediaLB state as true if locked or false if unlocked - */ -bool dim2_sysfs_get_state_cb(void); - -#endif /* DIM2_SYSFS_H */ -- cgit v1.2.3 From 9c7201bfd94e30cfabfa86d31e7b698a1a007d94 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:39 +0100 Subject: staging: most: net: rename module This patch renames the folder and the source file of the networking module. It is needed to clean up the directory layout of the driver. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Kconfig | 2 +- drivers/staging/most/aim-network/Kconfig | 13 - drivers/staging/most/aim-network/networking.c | 561 -------------------------- drivers/staging/most/net/Kconfig | 13 + drivers/staging/most/net/Makefile | 4 + drivers/staging/most/net/net.c | 561 ++++++++++++++++++++++++++ 6 files changed, 579 insertions(+), 575 deletions(-) delete mode 100644 drivers/staging/most/aim-network/Kconfig delete mode 100644 drivers/staging/most/aim-network/networking.c create mode 100644 drivers/staging/most/net/Kconfig create mode 100644 drivers/staging/most/net/Makefile create mode 100644 drivers/staging/most/net/net.c (limited to 'drivers') diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 88a415b8d07a..68a9c89db22a 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -19,7 +19,7 @@ if MOST source "drivers/staging/most/cdev/Kconfig" -source "drivers/staging/most/aim-network/Kconfig" +source "drivers/staging/most/net/Kconfig" source "drivers/staging/most/aim-sound/Kconfig" diff --git a/drivers/staging/most/aim-network/Kconfig b/drivers/staging/most/aim-network/Kconfig deleted file mode 100644 index 4c66b24cf73c..000000000000 --- a/drivers/staging/most/aim-network/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# -# MOST Networking configuration -# - -config AIM_NETWORK - tristate "Networking AIM" - depends on NET - - ---help--- - Say Y here if you want to commumicate via a networking device. - - To compile this driver as a module, choose M here: the - module will be called aim_network. diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c deleted file mode 100644 index 5e082d7d0e82..000000000000 --- a/drivers/staging/most/aim-network/networking.c +++ /dev/null @@ -1,561 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Networking AIM - Networking Application Interface Module for MostCore - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include "most/core.h" - -#define MEP_HDR_LEN 8 -#define MDP_HDR_LEN 16 -#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN) - -#define PMHL 5 - -#define PMS_TELID_UNSEGM_MAMAC 0x0A -#define PMS_FIFONO_MDP 0x01 -#define PMS_FIFONO_MEP 0x04 -#define PMS_MSGTYPE_DATA 0x04 -#define PMS_DEF_PRIO 0 -#define MEP_DEF_RETRY 15 - -#define PMS_FIFONO_MASK 0x07 -#define PMS_FIFONO_SHIFT 3 -#define PMS_RETRY_SHIFT 4 -#define PMS_TELID_MASK 0x0F -#define PMS_TELID_SHIFT 4 - -#define HB(value) ((u8)((u16)(value) >> 8)) -#define LB(value) ((u8)(value)) - -#define EXTRACT_BIT_SET(bitset_name, value) \ - (((value) >> bitset_name##_SHIFT) & bitset_name##_MASK) - -#define PMS_IS_MEP(buf, len) \ - ((len) > MEP_HDR_LEN && \ - EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP) - -#define PMS_IS_MAMAC(buf, len) \ - ((len) > MDP_HDR_LEN && \ - EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \ - EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC) - -struct net_dev_channel { - bool linked; - int ch_id; -}; - -struct net_dev_context { - struct most_interface *iface; - bool is_mamac; - struct net_device *dev; - struct net_dev_channel rx; - struct net_dev_channel tx; - struct list_head list; -}; - -static struct list_head net_devices = LIST_HEAD_INIT(net_devices); -static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ -static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */ -static struct most_aim aim; - -static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) -{ - u8 *buff = mbo->virt_address; - const u8 broadcast[] = { 0x03, 0xFF }; - const u8 *dest_addr = skb->data + 4; - const u8 *eth_type = skb->data + 12; - unsigned int payload_len = skb->len - ETH_HLEN; - unsigned int mdp_len = payload_len + MDP_HDR_LEN; - - if (mbo->buffer_length < mdp_len) { - pr_err("drop: too small buffer! (%d for %d)\n", - mbo->buffer_length, mdp_len); - return -EINVAL; - } - - if (skb->len < ETH_HLEN) { - pr_err("drop: too small packet! (%d)\n", skb->len); - return -EINVAL; - } - - if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF) - dest_addr = broadcast; - - *buff++ = HB(mdp_len - 2); - *buff++ = LB(mdp_len - 2); - - *buff++ = PMHL; - *buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA; - *buff++ = PMS_DEF_PRIO; - *buff++ = dest_addr[0]; - *buff++ = dest_addr[1]; - *buff++ = 0x00; - - *buff++ = HB(payload_len + 6); - *buff++ = LB(payload_len + 6); - - /* end of FPH here */ - - *buff++ = eth_type[0]; - *buff++ = eth_type[1]; - *buff++ = 0; - *buff++ = 0; - - *buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len); - *buff++ = LB(payload_len); - - memcpy(buff, skb->data + ETH_HLEN, payload_len); - mbo->buffer_length = mdp_len; - return 0; -} - -static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo) -{ - u8 *buff = mbo->virt_address; - unsigned int mep_len = skb->len + MEP_HDR_LEN; - - if (mbo->buffer_length < mep_len) { - pr_err("drop: too small buffer! (%d for %d)\n", - mbo->buffer_length, mep_len); - return -EINVAL; - } - - *buff++ = HB(mep_len - 2); - *buff++ = LB(mep_len - 2); - - *buff++ = PMHL; - *buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA; - *buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO; - *buff++ = 0; - *buff++ = 0; - *buff++ = 0; - - memcpy(buff, skb->data, skb->len); - mbo->buffer_length = mep_len; - return 0; -} - -static int most_nd_set_mac_address(struct net_device *dev, void *p) -{ - struct net_dev_context *nd = netdev_priv(dev); - int err = eth_mac_addr(dev, p); - - if (err) - return err; - - nd->is_mamac = - (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 && - dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0); - - /* - * Set default MTU for the given packet type. - * It is still possible to change MTU using ip tools afterwards. - */ - dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN; - - return 0; -} - -static void on_netinfo(struct most_interface *iface, - unsigned char link_stat, unsigned char *mac_addr); - -static int most_nd_open(struct net_device *dev) -{ - struct net_dev_context *nd = netdev_priv(dev); - int ret = 0; - - mutex_lock(&probe_disc_mt); - - if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) { - netdev_err(dev, "most_start_channel() failed\n"); - ret = -EBUSY; - goto unlock; - } - - if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) { - netdev_err(dev, "most_start_channel() failed\n"); - most_stop_channel(nd->iface, nd->rx.ch_id, &aim); - ret = -EBUSY; - goto unlock; - } - - netif_carrier_off(dev); - if (is_valid_ether_addr(dev->dev_addr)) - netif_dormant_off(dev); - else - netif_dormant_on(dev); - netif_wake_queue(dev); - if (nd->iface->request_netinfo) - nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo); - -unlock: - mutex_unlock(&probe_disc_mt); - return ret; -} - -static int most_nd_stop(struct net_device *dev) -{ - struct net_dev_context *nd = netdev_priv(dev); - - netif_stop_queue(dev); - if (nd->iface->request_netinfo) - nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL); - most_stop_channel(nd->iface, nd->rx.ch_id, &aim); - most_stop_channel(nd->iface, nd->tx.ch_id, &aim); - - return 0; -} - -static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct net_dev_context *nd = netdev_priv(dev); - struct mbo *mbo; - int ret; - - mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim); - - if (!mbo) { - netif_stop_queue(dev); - dev->stats.tx_fifo_errors++; - return NETDEV_TX_BUSY; - } - - if (nd->is_mamac) - ret = skb_to_mamac(skb, mbo); - else - ret = skb_to_mep(skb, mbo); - - if (ret) { - most_put_mbo(mbo); - dev->stats.tx_dropped++; - kfree_skb(skb); - return NETDEV_TX_OK; - } - - most_submit_mbo(mbo); - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - kfree_skb(skb); - return NETDEV_TX_OK; -} - -static const struct net_device_ops most_nd_ops = { - .ndo_open = most_nd_open, - .ndo_stop = most_nd_stop, - .ndo_start_xmit = most_nd_start_xmit, - .ndo_set_mac_address = most_nd_set_mac_address, -}; - -static void most_nd_setup(struct net_device *dev) -{ - ether_setup(dev); - dev->netdev_ops = &most_nd_ops; -} - -static struct net_dev_context *get_net_dev(struct most_interface *iface) -{ - struct net_dev_context *nd; - - list_for_each_entry(nd, &net_devices, list) - if (nd->iface == iface) - return nd; - return NULL; -} - -static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) -{ - struct net_dev_context *nd; - unsigned long flags; - - spin_lock_irqsave(&list_lock, flags); - nd = get_net_dev(iface); - if (nd && nd->rx.linked && nd->tx.linked) - dev_hold(nd->dev); - else - nd = NULL; - spin_unlock_irqrestore(&list_lock, flags); - return nd; -} - -static int aim_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, - struct kobject *parent, char *name) -{ - struct net_dev_context *nd; - struct net_dev_channel *ch; - struct net_device *dev; - unsigned long flags; - int ret = 0; - - if (!iface) - return -EINVAL; - - if (ccfg->data_type != MOST_CH_ASYNC) - return -EINVAL; - - mutex_lock(&probe_disc_mt); - nd = get_net_dev(iface); - if (!nd) { - dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d", - NET_NAME_UNKNOWN, most_nd_setup); - if (!dev) { - ret = -ENOMEM; - goto unlock; - } - - nd = netdev_priv(dev); - nd->iface = iface; - nd->dev = dev; - - spin_lock_irqsave(&list_lock, flags); - list_add(&nd->list, &net_devices); - spin_unlock_irqrestore(&list_lock, flags); - - ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx; - } else { - ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx; - if (ch->linked) { - pr_err("direction is allocated\n"); - ret = -EINVAL; - goto unlock; - } - - if (register_netdev(nd->dev)) { - pr_err("register_netdev() failed\n"); - ret = -EINVAL; - goto unlock; - } - } - ch->ch_id = channel_idx; - ch->linked = true; - -unlock: - mutex_unlock(&probe_disc_mt); - return ret; -} - -static int aim_disconnect_channel(struct most_interface *iface, - int channel_idx) -{ - struct net_dev_context *nd; - struct net_dev_channel *ch; - unsigned long flags; - int ret = 0; - - mutex_lock(&probe_disc_mt); - nd = get_net_dev(iface); - if (!nd) { - ret = -EINVAL; - goto unlock; - } - - if (nd->rx.linked && channel_idx == nd->rx.ch_id) { - ch = &nd->rx; - } else if (nd->tx.linked && channel_idx == nd->tx.ch_id) { - ch = &nd->tx; - } else { - ret = -EINVAL; - goto unlock; - } - - if (nd->rx.linked && nd->tx.linked) { - spin_lock_irqsave(&list_lock, flags); - ch->linked = false; - spin_unlock_irqrestore(&list_lock, flags); - - /* - * do not call most_stop_channel() here, because channels are - * going to be closed in ndo_stop() after unregister_netdev() - */ - unregister_netdev(nd->dev); - } else { - spin_lock_irqsave(&list_lock, flags); - list_del(&nd->list); - spin_unlock_irqrestore(&list_lock, flags); - - free_netdev(nd->dev); - } - -unlock: - mutex_unlock(&probe_disc_mt); - return ret; -} - -static int aim_resume_tx_channel(struct most_interface *iface, - int channel_idx) -{ - struct net_dev_context *nd; - - nd = get_net_dev_hold(iface); - if (!nd) - return 0; - - if (nd->tx.ch_id != channel_idx) - goto put_nd; - - netif_wake_queue(nd->dev); - -put_nd: - dev_put(nd->dev); - return 0; -} - -static int aim_rx_data(struct mbo *mbo) -{ - const u32 zero = 0; - struct net_dev_context *nd; - char *buf = mbo->virt_address; - u32 len = mbo->processed_length; - struct sk_buff *skb; - struct net_device *dev; - unsigned int skb_len; - int ret = 0; - - nd = get_net_dev_hold(mbo->ifp); - if (!nd) - return -EIO; - - if (nd->rx.ch_id != mbo->hdm_channel_id) { - ret = -EIO; - goto put_nd; - } - - dev = nd->dev; - - if (nd->is_mamac) { - if (!PMS_IS_MAMAC(buf, len)) { - ret = -EIO; - goto put_nd; - } - - skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2); - } else { - if (!PMS_IS_MEP(buf, len)) { - ret = -EIO; - goto put_nd; - } - - skb = dev_alloc_skb(len - MEP_HDR_LEN); - } - - if (!skb) { - dev->stats.rx_dropped++; - pr_err_once("drop packet: no memory for skb\n"); - goto out; - } - - skb->dev = dev; - - if (nd->is_mamac) { - /* dest */ - ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr); - - /* src */ - skb_put_data(skb, &zero, 4); - skb_put_data(skb, buf + 5, 2); - - /* eth type */ - skb_put_data(skb, buf + 10, 2); - - buf += MDP_HDR_LEN; - len -= MDP_HDR_LEN; - } else { - buf += MEP_HDR_LEN; - len -= MEP_HDR_LEN; - } - - skb_put_data(skb, buf, len); - skb->protocol = eth_type_trans(skb, dev); - skb_len = skb->len; - if (netif_rx(skb) == NET_RX_SUCCESS) { - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb_len; - } else { - dev->stats.rx_dropped++; - } - -out: - most_put_mbo(mbo); - -put_nd: - dev_put(nd->dev); - return ret; -} - -static struct most_aim aim = { - .name = "networking", - .probe_channel = aim_probe_channel, - .disconnect_channel = aim_disconnect_channel, - .tx_completion = aim_resume_tx_channel, - .rx_completion = aim_rx_data, -}; - -static int __init most_net_init(void) -{ - spin_lock_init(&list_lock); - mutex_init(&probe_disc_mt); - return most_register_aim(&aim); -} - -static void __exit most_net_exit(void) -{ - most_deregister_aim(&aim); -} - -/** - * on_netinfo - callback for HDM to be informed about HW's MAC - * @param iface - most interface instance - * @param link_stat - link status - * @param mac_addr - MAC address - */ -static void on_netinfo(struct most_interface *iface, - unsigned char link_stat, unsigned char *mac_addr) -{ - struct net_dev_context *nd; - struct net_device *dev; - const u8 *m = mac_addr; - - nd = get_net_dev_hold(iface); - if (!nd) - return; - - dev = nd->dev; - - if (link_stat) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - - if (m && is_valid_ether_addr(m)) { - if (!is_valid_ether_addr(dev->dev_addr)) { - netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n", - m[0], m[1], m[2], m[3], m[4], m[5]); - ether_addr_copy(dev->dev_addr, m); - netif_dormant_off(dev); - } else if (!ether_addr_equal(dev->dev_addr, m)) { - netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n", - m[0], m[1], m[2], m[3], m[4], m[5]); - } - } - - dev_put(nd->dev); -} - -module_init(most_net_init); -module_exit(most_net_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Andrey Shvetsov "); -MODULE_DESCRIPTION("Networking Application Interface Module for MostCore"); diff --git a/drivers/staging/most/net/Kconfig b/drivers/staging/most/net/Kconfig new file mode 100644 index 000000000000..795330ba94ef --- /dev/null +++ b/drivers/staging/most/net/Kconfig @@ -0,0 +1,13 @@ +# +# MOST Networking configuration +# + +config MOST_NET + tristate "Net" + depends on NET + + ---help--- + Say Y here if you want to commumicate via a networking device. + + To compile this driver as a module, choose M here: the + module will be called most_net. diff --git a/drivers/staging/most/net/Makefile b/drivers/staging/most/net/Makefile new file mode 100644 index 000000000000..54500aa77be8 --- /dev/null +++ b/drivers/staging/most/net/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_NET) += most_net.o + +most_net-objs := net.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c new file mode 100644 index 000000000000..3cbd403aa516 --- /dev/null +++ b/drivers/staging/most/net/net.c @@ -0,0 +1,561 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Networking AIM - Networking Application Interface Module for MostCore + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include "most/core.h" + +#define MEP_HDR_LEN 8 +#define MDP_HDR_LEN 16 +#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN) + +#define PMHL 5 + +#define PMS_TELID_UNSEGM_MAMAC 0x0A +#define PMS_FIFONO_MDP 0x01 +#define PMS_FIFONO_MEP 0x04 +#define PMS_MSGTYPE_DATA 0x04 +#define PMS_DEF_PRIO 0 +#define MEP_DEF_RETRY 15 + +#define PMS_FIFONO_MASK 0x07 +#define PMS_FIFONO_SHIFT 3 +#define PMS_RETRY_SHIFT 4 +#define PMS_TELID_MASK 0x0F +#define PMS_TELID_SHIFT 4 + +#define HB(value) ((u8)((u16)(value) >> 8)) +#define LB(value) ((u8)(value)) + +#define EXTRACT_BIT_SET(bitset_name, value) \ + (((value) >> bitset_name##_SHIFT) & bitset_name##_MASK) + +#define PMS_IS_MEP(buf, len) \ + ((len) > MEP_HDR_LEN && \ + EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP) + +#define PMS_IS_MAMAC(buf, len) \ + ((len) > MDP_HDR_LEN && \ + EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \ + EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC) + +struct net_dev_channel { + bool linked; + int ch_id; +}; + +struct net_dev_context { + struct most_interface *iface; + bool is_mamac; + struct net_device *dev; + struct net_dev_channel rx; + struct net_dev_channel tx; + struct list_head list; +}; + +static struct list_head net_devices = LIST_HEAD_INIT(net_devices); +static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ +static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */ +static struct most_aim aim; + +static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) +{ + u8 *buff = mbo->virt_address; + const u8 broadcast[] = { 0x03, 0xFF }; + const u8 *dest_addr = skb->data + 4; + const u8 *eth_type = skb->data + 12; + unsigned int payload_len = skb->len - ETH_HLEN; + unsigned int mdp_len = payload_len + MDP_HDR_LEN; + + if (mbo->buffer_length < mdp_len) { + pr_err("drop: too small buffer! (%d for %d)\n", + mbo->buffer_length, mdp_len); + return -EINVAL; + } + + if (skb->len < ETH_HLEN) { + pr_err("drop: too small packet! (%d)\n", skb->len); + return -EINVAL; + } + + if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF) + dest_addr = broadcast; + + *buff++ = HB(mdp_len - 2); + *buff++ = LB(mdp_len - 2); + + *buff++ = PMHL; + *buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA; + *buff++ = PMS_DEF_PRIO; + *buff++ = dest_addr[0]; + *buff++ = dest_addr[1]; + *buff++ = 0x00; + + *buff++ = HB(payload_len + 6); + *buff++ = LB(payload_len + 6); + + /* end of FPH here */ + + *buff++ = eth_type[0]; + *buff++ = eth_type[1]; + *buff++ = 0; + *buff++ = 0; + + *buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len); + *buff++ = LB(payload_len); + + memcpy(buff, skb->data + ETH_HLEN, payload_len); + mbo->buffer_length = mdp_len; + return 0; +} + +static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo) +{ + u8 *buff = mbo->virt_address; + unsigned int mep_len = skb->len + MEP_HDR_LEN; + + if (mbo->buffer_length < mep_len) { + pr_err("drop: too small buffer! (%d for %d)\n", + mbo->buffer_length, mep_len); + return -EINVAL; + } + + *buff++ = HB(mep_len - 2); + *buff++ = LB(mep_len - 2); + + *buff++ = PMHL; + *buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA; + *buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO; + *buff++ = 0; + *buff++ = 0; + *buff++ = 0; + + memcpy(buff, skb->data, skb->len); + mbo->buffer_length = mep_len; + return 0; +} + +static int most_nd_set_mac_address(struct net_device *dev, void *p) +{ + struct net_dev_context *nd = netdev_priv(dev); + int err = eth_mac_addr(dev, p); + + if (err) + return err; + + nd->is_mamac = + (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 && + dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0); + + /* + * Set default MTU for the given packet type. + * It is still possible to change MTU using ip tools afterwards. + */ + dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN; + + return 0; +} + +static void on_netinfo(struct most_interface *iface, + unsigned char link_stat, unsigned char *mac_addr); + +static int most_nd_open(struct net_device *dev) +{ + struct net_dev_context *nd = netdev_priv(dev); + int ret = 0; + + mutex_lock(&probe_disc_mt); + + if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) { + netdev_err(dev, "most_start_channel() failed\n"); + ret = -EBUSY; + goto unlock; + } + + if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) { + netdev_err(dev, "most_start_channel() failed\n"); + most_stop_channel(nd->iface, nd->rx.ch_id, &aim); + ret = -EBUSY; + goto unlock; + } + + netif_carrier_off(dev); + if (is_valid_ether_addr(dev->dev_addr)) + netif_dormant_off(dev); + else + netif_dormant_on(dev); + netif_wake_queue(dev); + if (nd->iface->request_netinfo) + nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo); + +unlock: + mutex_unlock(&probe_disc_mt); + return ret; +} + +static int most_nd_stop(struct net_device *dev) +{ + struct net_dev_context *nd = netdev_priv(dev); + + netif_stop_queue(dev); + if (nd->iface->request_netinfo) + nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL); + most_stop_channel(nd->iface, nd->rx.ch_id, &aim); + most_stop_channel(nd->iface, nd->tx.ch_id, &aim); + + return 0; +} + +static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct net_dev_context *nd = netdev_priv(dev); + struct mbo *mbo; + int ret; + + mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim); + + if (!mbo) { + netif_stop_queue(dev); + dev->stats.tx_fifo_errors++; + return NETDEV_TX_BUSY; + } + + if (nd->is_mamac) + ret = skb_to_mamac(skb, mbo); + else + ret = skb_to_mep(skb, mbo); + + if (ret) { + most_put_mbo(mbo); + dev->stats.tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; + } + + most_submit_mbo(mbo); + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static const struct net_device_ops most_nd_ops = { + .ndo_open = most_nd_open, + .ndo_stop = most_nd_stop, + .ndo_start_xmit = most_nd_start_xmit, + .ndo_set_mac_address = most_nd_set_mac_address, +}; + +static void most_nd_setup(struct net_device *dev) +{ + ether_setup(dev); + dev->netdev_ops = &most_nd_ops; +} + +static struct net_dev_context *get_net_dev(struct most_interface *iface) +{ + struct net_dev_context *nd; + + list_for_each_entry(nd, &net_devices, list) + if (nd->iface == iface) + return nd; + return NULL; +} + +static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) +{ + struct net_dev_context *nd; + unsigned long flags; + + spin_lock_irqsave(&list_lock, flags); + nd = get_net_dev(iface); + if (nd && nd->rx.linked && nd->tx.linked) + dev_hold(nd->dev); + else + nd = NULL; + spin_unlock_irqrestore(&list_lock, flags); + return nd; +} + +static int aim_probe_channel(struct most_interface *iface, int channel_idx, + struct most_channel_config *ccfg, + struct kobject *parent, char *name) +{ + struct net_dev_context *nd; + struct net_dev_channel *ch; + struct net_device *dev; + unsigned long flags; + int ret = 0; + + if (!iface) + return -EINVAL; + + if (ccfg->data_type != MOST_CH_ASYNC) + return -EINVAL; + + mutex_lock(&probe_disc_mt); + nd = get_net_dev(iface); + if (!nd) { + dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d", + NET_NAME_UNKNOWN, most_nd_setup); + if (!dev) { + ret = -ENOMEM; + goto unlock; + } + + nd = netdev_priv(dev); + nd->iface = iface; + nd->dev = dev; + + spin_lock_irqsave(&list_lock, flags); + list_add(&nd->list, &net_devices); + spin_unlock_irqrestore(&list_lock, flags); + + ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx; + } else { + ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx; + if (ch->linked) { + pr_err("direction is allocated\n"); + ret = -EINVAL; + goto unlock; + } + + if (register_netdev(nd->dev)) { + pr_err("register_netdev() failed\n"); + ret = -EINVAL; + goto unlock; + } + } + ch->ch_id = channel_idx; + ch->linked = true; + +unlock: + mutex_unlock(&probe_disc_mt); + return ret; +} + +static int aim_disconnect_channel(struct most_interface *iface, + int channel_idx) +{ + struct net_dev_context *nd; + struct net_dev_channel *ch; + unsigned long flags; + int ret = 0; + + mutex_lock(&probe_disc_mt); + nd = get_net_dev(iface); + if (!nd) { + ret = -EINVAL; + goto unlock; + } + + if (nd->rx.linked && channel_idx == nd->rx.ch_id) { + ch = &nd->rx; + } else if (nd->tx.linked && channel_idx == nd->tx.ch_id) { + ch = &nd->tx; + } else { + ret = -EINVAL; + goto unlock; + } + + if (nd->rx.linked && nd->tx.linked) { + spin_lock_irqsave(&list_lock, flags); + ch->linked = false; + spin_unlock_irqrestore(&list_lock, flags); + + /* + * do not call most_stop_channel() here, because channels are + * going to be closed in ndo_stop() after unregister_netdev() + */ + unregister_netdev(nd->dev); + } else { + spin_lock_irqsave(&list_lock, flags); + list_del(&nd->list); + spin_unlock_irqrestore(&list_lock, flags); + + free_netdev(nd->dev); + } + +unlock: + mutex_unlock(&probe_disc_mt); + return ret; +} + +static int aim_resume_tx_channel(struct most_interface *iface, + int channel_idx) +{ + struct net_dev_context *nd; + + nd = get_net_dev_hold(iface); + if (!nd) + return 0; + + if (nd->tx.ch_id != channel_idx) + goto put_nd; + + netif_wake_queue(nd->dev); + +put_nd: + dev_put(nd->dev); + return 0; +} + +static int aim_rx_data(struct mbo *mbo) +{ + const u32 zero = 0; + struct net_dev_context *nd; + char *buf = mbo->virt_address; + u32 len = mbo->processed_length; + struct sk_buff *skb; + struct net_device *dev; + unsigned int skb_len; + int ret = 0; + + nd = get_net_dev_hold(mbo->ifp); + if (!nd) + return -EIO; + + if (nd->rx.ch_id != mbo->hdm_channel_id) { + ret = -EIO; + goto put_nd; + } + + dev = nd->dev; + + if (nd->is_mamac) { + if (!PMS_IS_MAMAC(buf, len)) { + ret = -EIO; + goto put_nd; + } + + skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2); + } else { + if (!PMS_IS_MEP(buf, len)) { + ret = -EIO; + goto put_nd; + } + + skb = dev_alloc_skb(len - MEP_HDR_LEN); + } + + if (!skb) { + dev->stats.rx_dropped++; + pr_err_once("drop packet: no memory for skb\n"); + goto out; + } + + skb->dev = dev; + + if (nd->is_mamac) { + /* dest */ + ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr); + + /* src */ + skb_put_data(skb, &zero, 4); + skb_put_data(skb, buf + 5, 2); + + /* eth type */ + skb_put_data(skb, buf + 10, 2); + + buf += MDP_HDR_LEN; + len -= MDP_HDR_LEN; + } else { + buf += MEP_HDR_LEN; + len -= MEP_HDR_LEN; + } + + skb_put_data(skb, buf, len); + skb->protocol = eth_type_trans(skb, dev); + skb_len = skb->len; + if (netif_rx(skb) == NET_RX_SUCCESS) { + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb_len; + } else { + dev->stats.rx_dropped++; + } + +out: + most_put_mbo(mbo); + +put_nd: + dev_put(nd->dev); + return ret; +} + +static struct most_aim aim = { + .name = "net", + .probe_channel = aim_probe_channel, + .disconnect_channel = aim_disconnect_channel, + .tx_completion = aim_resume_tx_channel, + .rx_completion = aim_rx_data, +}; + +static int __init most_net_init(void) +{ + spin_lock_init(&list_lock); + mutex_init(&probe_disc_mt); + return most_register_aim(&aim); +} + +static void __exit most_net_exit(void) +{ + most_deregister_aim(&aim); +} + +/** + * on_netinfo - callback for HDM to be informed about HW's MAC + * @param iface - most interface instance + * @param link_stat - link status + * @param mac_addr - MAC address + */ +static void on_netinfo(struct most_interface *iface, + unsigned char link_stat, unsigned char *mac_addr) +{ + struct net_dev_context *nd; + struct net_device *dev; + const u8 *m = mac_addr; + + nd = get_net_dev_hold(iface); + if (!nd) + return; + + dev = nd->dev; + + if (link_stat) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + + if (m && is_valid_ether_addr(m)) { + if (!is_valid_ether_addr(dev->dev_addr)) { + netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n", + m[0], m[1], m[2], m[3], m[4], m[5]); + ether_addr_copy(dev->dev_addr, m); + netif_dormant_off(dev); + } else if (!ether_addr_equal(dev->dev_addr, m)) { + netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n", + m[0], m[1], m[2], m[3], m[4], m[5]); + } + } + + dev_put(nd->dev); +} + +module_init(most_net_init); +module_exit(most_net_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Andrey Shvetsov "); +MODULE_DESCRIPTION("Networking Application Interface Module for MostCore"); -- cgit v1.2.3 From 88c975497da8a16e07dc6ac2e5d51b187014fe42 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:40 +0100 Subject: staging: most: sound: rename module This patch renames the folder of the sound module. It is needed to clean up the directory layout of the driver. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Kconfig | 2 +- drivers/staging/most/aim-sound/Kconfig | 13 - drivers/staging/most/aim-sound/sound.c | 759 --------------------------------- drivers/staging/most/sound/Kconfig | 13 + drivers/staging/most/sound/Makefile | 4 + drivers/staging/most/sound/sound.c | 759 +++++++++++++++++++++++++++++++++ 6 files changed, 777 insertions(+), 773 deletions(-) delete mode 100644 drivers/staging/most/aim-sound/Kconfig delete mode 100644 drivers/staging/most/aim-sound/sound.c create mode 100644 drivers/staging/most/sound/Kconfig create mode 100644 drivers/staging/most/sound/Makefile create mode 100644 drivers/staging/most/sound/sound.c (limited to 'drivers') diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 68a9c89db22a..3f127116476c 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -21,7 +21,7 @@ source "drivers/staging/most/cdev/Kconfig" source "drivers/staging/most/net/Kconfig" -source "drivers/staging/most/aim-sound/Kconfig" +source "drivers/staging/most/sound/Kconfig" source "drivers/staging/most/aim-v4l2/Kconfig" diff --git a/drivers/staging/most/aim-sound/Kconfig b/drivers/staging/most/aim-sound/Kconfig deleted file mode 100644 index 3194c219ff14..000000000000 --- a/drivers/staging/most/aim-sound/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# -# MOST ALSA configuration -# - -config AIM_SOUND - tristate "ALSA AIM" - depends on SND - select SND_PCM - ---help--- - Say Y here if you want to commumicate via ALSA/sound devices. - - To compile this driver as a module, choose M here: the - module will be called aim_sound. diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c deleted file mode 100644 index 5826f710c925..000000000000 --- a/drivers/staging/most/aim-sound/sound.c +++ /dev/null @@ -1,759 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * sound.c - Audio Application Interface Module for Mostcore - * - * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "sound" - -static struct list_head dev_list; -static struct most_aim audio_aim; - -/** - * struct channel - private structure to keep channel specific data - * @substream: stores the substream structure - * @iface: interface for which the channel belongs to - * @cfg: channel configuration - * @card: registered sound card - * @list: list for private use - * @id: channel index - * @period_pos: current period position (ring buffer) - * @buffer_pos: current buffer position (ring buffer) - * @is_stream_running: identifies whether a stream is running or not - * @opened: set when the stream is opened - * @playback_task: playback thread - * @playback_waitq: waitq used by playback thread - */ -struct channel { - struct snd_pcm_substream *substream; - struct snd_pcm_hardware pcm_hardware; - struct most_interface *iface; - struct most_channel_config *cfg; - struct snd_card *card; - struct list_head list; - int id; - unsigned int period_pos; - unsigned int buffer_pos; - bool is_stream_running; - - struct task_struct *playback_task; - wait_queue_head_t playback_waitq; - - void (*copy_fn)(void *alsa, void *most, unsigned int bytes); -}; - -#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \ - SNDRV_PCM_INFO_MMAP_VALID | \ - SNDRV_PCM_INFO_BATCH | \ - SNDRV_PCM_INFO_INTERLEAVED | \ - SNDRV_PCM_INFO_BLOCK_TRANSFER) - -#define swap16(val) ( \ - (((u16)(val) << 8) & (u16)0xFF00) | \ - (((u16)(val) >> 8) & (u16)0x00FF)) - -#define swap32(val) ( \ - (((u32)(val) << 24) & (u32)0xFF000000) | \ - (((u32)(val) << 8) & (u32)0x00FF0000) | \ - (((u32)(val) >> 8) & (u32)0x0000FF00) | \ - (((u32)(val) >> 24) & (u32)0x000000FF)) - -static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes) -{ - unsigned int i = 0; - - while (i < (bytes / 2)) { - dest[i] = swap16(source[i]); - i++; - } -} - -static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes) -{ - unsigned int i = 0; - - while (i < bytes - 2) { - dest[i] = source[i + 2]; - dest[i + 1] = source[i + 1]; - dest[i + 2] = source[i]; - i += 3; - } -} - -static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes) -{ - unsigned int i = 0; - - while (i < bytes / 4) { - dest[i] = swap32(source[i]); - i++; - } -} - -static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes) -{ - memcpy(most, alsa, bytes); -} - -static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes) -{ - swap_copy16(most, alsa, bytes); -} - -static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes) -{ - swap_copy24(most, alsa, bytes); -} - -static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes) -{ - swap_copy32(most, alsa, bytes); -} - -static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes) -{ - memcpy(alsa, most, bytes); -} - -static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes) -{ - swap_copy16(alsa, most, bytes); -} - -static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes) -{ - swap_copy24(alsa, most, bytes); -} - -static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes) -{ - swap_copy32(alsa, most, bytes); -} - -/** - * get_channel - get pointer to channel - * @iface: interface structure - * @channel_id: channel ID - * - * This traverses the channel list and returns the channel matching the - * ID and interface. - * - * Returns pointer to channel on success or NULL otherwise. - */ -static struct channel *get_channel(struct most_interface *iface, - int channel_id) -{ - struct channel *channel, *tmp; - - list_for_each_entry_safe(channel, tmp, &dev_list, list) { - if ((channel->iface == iface) && (channel->id == channel_id)) - return channel; - } - - return NULL; -} - -/** - * copy_data - implements data copying function - * @channel: channel - * @mbo: MBO from core - * - * Copy data from/to ring buffer to/from MBO and update the buffer position - */ -static bool copy_data(struct channel *channel, struct mbo *mbo) -{ - struct snd_pcm_runtime *const runtime = channel->substream->runtime; - unsigned int const frame_bytes = channel->cfg->subbuffer_size; - unsigned int const buffer_size = runtime->buffer_size; - unsigned int frames; - unsigned int fr0; - - if (channel->cfg->direction & MOST_CH_RX) - frames = mbo->processed_length / frame_bytes; - else - frames = mbo->buffer_length / frame_bytes; - fr0 = min(buffer_size - channel->buffer_pos, frames); - - channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes, - mbo->virt_address, - fr0 * frame_bytes); - - if (frames > fr0) { - /* wrap around at end of ring buffer */ - channel->copy_fn(runtime->dma_area, - mbo->virt_address + fr0 * frame_bytes, - (frames - fr0) * frame_bytes); - } - - channel->buffer_pos += frames; - if (channel->buffer_pos >= buffer_size) - channel->buffer_pos -= buffer_size; - channel->period_pos += frames; - if (channel->period_pos >= runtime->period_size) { - channel->period_pos -= runtime->period_size; - return true; - } - - return false; -} - -/** - * playback_thread - function implements the playback thread - * @data: private data - * - * Thread which does the playback functionality in a loop. It waits for a free - * MBO from mostcore for a particular channel and copy the data from ring buffer - * to MBO. Submit the MBO back to mostcore, after copying the data. - * - * Returns 0 on success or error code otherwise. - */ -static int playback_thread(void *data) -{ - struct channel *const channel = data; - - while (!kthread_should_stop()) { - struct mbo *mbo = NULL; - bool period_elapsed = false; - - wait_event_interruptible( - channel->playback_waitq, - kthread_should_stop() || - (channel->is_stream_running && - (mbo = most_get_mbo(channel->iface, channel->id, - &audio_aim)))); - if (!mbo) - continue; - - if (channel->is_stream_running) - period_elapsed = copy_data(channel, mbo); - else - memset(mbo->virt_address, 0, mbo->buffer_length); - - most_submit_mbo(mbo); - if (period_elapsed) - snd_pcm_period_elapsed(channel->substream); - } - - return 0; -} - -/** - * pcm_open - implements open callback function for PCM middle layer - * @substream: pointer to ALSA PCM substream - * - * This is called when a PCM substream is opened. At least, the function should - * initialize the runtime->hw record. - * - * Returns 0 on success or error code otherwise. - */ -static int pcm_open(struct snd_pcm_substream *substream) -{ - struct channel *channel = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - struct most_channel_config *cfg = channel->cfg; - - channel->substream = substream; - - if (cfg->direction == MOST_CH_TX) { - channel->playback_task = kthread_run(playback_thread, channel, - "most_audio_playback"); - if (IS_ERR(channel->playback_task)) { - pr_err("Couldn't start thread\n"); - return PTR_ERR(channel->playback_task); - } - } - - if (most_start_channel(channel->iface, channel->id, &audio_aim)) { - pr_err("most_start_channel() failed!\n"); - if (cfg->direction == MOST_CH_TX) - kthread_stop(channel->playback_task); - return -EBUSY; - } - - runtime->hw = channel->pcm_hardware; - return 0; -} - -/** - * pcm_close - implements close callback function for PCM middle layer - * @substream: sub-stream pointer - * - * Obviously, this is called when a PCM substream is closed. Any private - * instance for a PCM substream allocated in the open callback will be - * released here. - * - * Returns 0 on success or error code otherwise. - */ -static int pcm_close(struct snd_pcm_substream *substream) -{ - struct channel *channel = substream->private_data; - - if (channel->cfg->direction == MOST_CH_TX) - kthread_stop(channel->playback_task); - most_stop_channel(channel->iface, channel->id, &audio_aim); - - return 0; -} - -/** - * pcm_hw_params - implements hw_params callback function for PCM middle layer - * @substream: sub-stream pointer - * @hw_params: contains the hardware parameters set by the application - * - * This is called when the hardware parameters is set by the application, that - * is, once when the buffer size, the period size, the format, etc. are defined - * for the PCM substream. Many hardware setups should be done is this callback, - * including the allocation of buffers. - * - * Returns 0 on success or error code otherwise. - */ -static int pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct channel *channel = substream->private_data; - - if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) || - (params_channels(hw_params) < channel->pcm_hardware.channels_min)) { - pr_err("Requested number of channels not supported.\n"); - return -EINVAL; - } - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); -} - -/** - * pcm_hw_free - implements hw_free callback function for PCM middle layer - * @substream: substream pointer - * - * This is called to release the resources allocated via hw_params. - * This function will be always called before the close callback is called. - * - * Returns 0 on success or error code otherwise. - */ -static int pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -/** - * pcm_prepare - implements prepare callback function for PCM middle layer - * @substream: substream pointer - * - * This callback is called when the PCM is "prepared". Format rate, sample rate, - * etc., can be set here. This callback can be called many times at each setup. - * - * Returns 0 on success or error code otherwise. - */ -static int pcm_prepare(struct snd_pcm_substream *substream) -{ - struct channel *channel = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - struct most_channel_config *cfg = channel->cfg; - int width = snd_pcm_format_physical_width(runtime->format); - - channel->copy_fn = NULL; - - if (cfg->direction == MOST_CH_TX) { - if (snd_pcm_format_big_endian(runtime->format) || width == 8) - channel->copy_fn = alsa_to_most_memcpy; - else if (width == 16) - channel->copy_fn = alsa_to_most_copy16; - else if (width == 24) - channel->copy_fn = alsa_to_most_copy24; - else if (width == 32) - channel->copy_fn = alsa_to_most_copy32; - } else { - if (snd_pcm_format_big_endian(runtime->format) || width == 8) - channel->copy_fn = most_to_alsa_memcpy; - else if (width == 16) - channel->copy_fn = most_to_alsa_copy16; - else if (width == 24) - channel->copy_fn = most_to_alsa_copy24; - else if (width == 32) - channel->copy_fn = most_to_alsa_copy32; - } - - if (!channel->copy_fn) { - pr_err("unsupported format\n"); - return -EINVAL; - } - - channel->period_pos = 0; - channel->buffer_pos = 0; - - return 0; -} - -/** - * pcm_trigger - implements trigger callback function for PCM middle layer - * @substream: substream pointer - * @cmd: action to perform - * - * This is called when the PCM is started, stopped or paused. The action will be - * specified in the second argument, SNDRV_PCM_TRIGGER_XXX - * - * Returns 0 on success or error code otherwise. - */ -static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct channel *channel = substream->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - channel->is_stream_running = true; - wake_up_interruptible(&channel->playback_waitq); - return 0; - - case SNDRV_PCM_TRIGGER_STOP: - channel->is_stream_running = false; - return 0; - - default: - pr_info("%s(), invalid\n", __func__); - return -EINVAL; - } - return 0; -} - -/** - * pcm_pointer - implements pointer callback function for PCM middle layer - * @substream: substream pointer - * - * This callback is called when the PCM middle layer inquires the current - * hardware position on the buffer. The position must be returned in frames, - * ranging from 0 to buffer_size-1. - */ -static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) -{ - struct channel *channel = substream->private_data; - - return channel->buffer_pos; -} - -/** - * Initialization of struct snd_pcm_ops - */ -static const struct snd_pcm_ops pcm_ops = { - .open = pcm_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static int split_arg_list(char *buf, char **card_name, char **pcm_format) -{ - *card_name = strsep(&buf, "."); - if (!*card_name) - return -EIO; - *pcm_format = strsep(&buf, ".\n"); - if (!*pcm_format) - return -EIO; - return 0; -} - -static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw, - char *pcm_format, - struct most_channel_config *cfg) -{ - pcm_hw->info = MOST_PCM_INFO; - pcm_hw->rates = SNDRV_PCM_RATE_48000; - pcm_hw->rate_min = 48000; - pcm_hw->rate_max = 48000; - pcm_hw->buffer_bytes_max = cfg->num_buffers * cfg->buffer_size; - pcm_hw->period_bytes_min = cfg->buffer_size; - pcm_hw->period_bytes_max = cfg->buffer_size; - pcm_hw->periods_min = 1; - pcm_hw->periods_max = cfg->num_buffers; - - if (!strcmp(pcm_format, "1x8")) { - if (cfg->subbuffer_size != 1) - goto error; - pr_info("PCM format is 8-bit mono\n"); - pcm_hw->channels_min = 1; - pcm_hw->channels_max = 1; - pcm_hw->formats = SNDRV_PCM_FMTBIT_S8; - } else if (!strcmp(pcm_format, "2x16")) { - if (cfg->subbuffer_size != 4) - goto error; - pr_info("PCM format is 16-bit stereo\n"); - pcm_hw->channels_min = 2; - pcm_hw->channels_max = 2; - pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE; - } else if (!strcmp(pcm_format, "2x24")) { - if (cfg->subbuffer_size != 6) - goto error; - pr_info("PCM format is 24-bit stereo\n"); - pcm_hw->channels_min = 2; - pcm_hw->channels_max = 2; - pcm_hw->formats = SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S24_3BE; - } else if (!strcmp(pcm_format, "2x32")) { - if (cfg->subbuffer_size != 8) - goto error; - pr_info("PCM format is 32-bit stereo\n"); - pcm_hw->channels_min = 2; - pcm_hw->channels_max = 2; - pcm_hw->formats = SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE; - } else if (!strcmp(pcm_format, "6x16")) { - if (cfg->subbuffer_size != 12) - goto error; - pr_info("PCM format is 16-bit 5.1 multi channel\n"); - pcm_hw->channels_min = 6; - pcm_hw->channels_max = 6; - pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE; - } else { - pr_err("PCM format %s not supported\n", pcm_format); - return -EIO; - } - return 0; -error: - pr_err("Audio resolution doesn't fit subbuffer size\n"); - return -EINVAL; -} - -/** - * audio_probe_channel - probe function of the driver module - * @iface: pointer to interface instance - * @channel_id: channel index/ID - * @cfg: pointer to actual channel configuration - * @parent: pointer to kobject (needed for sysfs hook-up) - * @arg_list: string that provides the name of the device to be created in /dev - * plus the desired audio resolution - * - * Creates sound card, pcm device, sets pcm ops and registers sound card. - * - * Returns 0 on success or error code otherwise. - */ -static int audio_probe_channel(struct most_interface *iface, int channel_id, - struct most_channel_config *cfg, - struct kobject *parent, char *arg_list) -{ - struct channel *channel; - struct snd_card *card; - struct snd_pcm *pcm; - int playback_count = 0; - int capture_count = 0; - int ret; - int direction; - char *card_name; - char *pcm_format; - - if (!iface) - return -EINVAL; - - if (cfg->data_type != MOST_CH_SYNC) { - pr_err("Incompatible channel type\n"); - return -EINVAL; - } - - if (get_channel(iface, channel_id)) { - pr_err("channel (%s:%d) is already linked\n", - iface->description, channel_id); - return -EINVAL; - } - - if (cfg->direction == MOST_CH_TX) { - playback_count = 1; - direction = SNDRV_PCM_STREAM_PLAYBACK; - } else { - capture_count = 1; - direction = SNDRV_PCM_STREAM_CAPTURE; - } - - ret = split_arg_list(arg_list, &card_name, &pcm_format); - if (ret < 0) { - pr_info("PCM format missing\n"); - return ret; - } - - ret = snd_card_new(NULL, -1, card_name, THIS_MODULE, - sizeof(*channel), &card); - if (ret < 0) - return ret; - - channel = card->private_data; - channel->card = card; - channel->cfg = cfg; - channel->iface = iface; - channel->id = channel_id; - init_waitqueue_head(&channel->playback_waitq); - - ret = audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg); - if (ret) - goto err_free_card; - - snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME); - snprintf(card->shortname, sizeof(card->shortname), "Microchip MOST:%d", - card->number); - snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d", - card->shortname, iface->description, channel_id); - - ret = snd_pcm_new(card, card_name, 0, playback_count, - capture_count, &pcm); - if (ret < 0) - goto err_free_card; - - pcm->private_data = channel; - - snd_pcm_set_ops(pcm, direction, &pcm_ops); - - ret = snd_card_register(card); - if (ret < 0) - goto err_free_card; - - list_add_tail(&channel->list, &dev_list); - - return 0; - -err_free_card: - snd_card_free(card); - return ret; -} - -/** - * audio_disconnect_channel - function to disconnect a channel - * @iface: pointer to interface instance - * @channel_id: channel index - * - * This frees allocated memory and removes the sound card from ALSA - * - * Returns 0 on success or error code otherwise. - */ -static int audio_disconnect_channel(struct most_interface *iface, - int channel_id) -{ - struct channel *channel; - - channel = get_channel(iface, channel_id); - if (!channel) { - pr_err("sound_disconnect_channel(), invalid channel %d\n", - channel_id); - return -EINVAL; - } - - list_del(&channel->list); - snd_card_free(channel->card); - - return 0; -} - -/** - * audio_rx_completion - completion handler for rx channels - * @mbo: pointer to buffer object that has completed - * - * This searches for the channel this MBO belongs to and copy the data from MBO - * to ring buffer - * - * Returns 0 on success or error code otherwise. - */ -static int audio_rx_completion(struct mbo *mbo) -{ - struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id); - bool period_elapsed = false; - - if (!channel) { - pr_err("sound_rx_completion(), invalid channel %d\n", - mbo->hdm_channel_id); - return -EINVAL; - } - - if (channel->is_stream_running) - period_elapsed = copy_data(channel, mbo); - - most_put_mbo(mbo); - - if (period_elapsed) - snd_pcm_period_elapsed(channel->substream); - - return 0; -} - -/** - * audio_tx_completion - completion handler for tx channels - * @iface: pointer to interface instance - * @channel_id: channel index/ID - * - * This searches the channel that belongs to this combination of interface - * pointer and channel ID and wakes a process sitting in the wait queue of - * this channel. - * - * Returns 0 on success or error code otherwise. - */ -static int audio_tx_completion(struct most_interface *iface, int channel_id) -{ - struct channel *channel = get_channel(iface, channel_id); - - if (!channel) { - pr_err("sound_tx_completion(), invalid channel %d\n", - channel_id); - return -EINVAL; - } - - wake_up_interruptible(&channel->playback_waitq); - - return 0; -} - -/** - * Initialization of the struct most_aim - */ -static struct most_aim audio_aim = { - .name = DRIVER_NAME, - .probe_channel = audio_probe_channel, - .disconnect_channel = audio_disconnect_channel, - .rx_completion = audio_rx_completion, - .tx_completion = audio_tx_completion, -}; - -static int __init audio_init(void) -{ - pr_info("init()\n"); - - INIT_LIST_HEAD(&dev_list); - - return most_register_aim(&audio_aim); -} - -static void __exit audio_exit(void) -{ - struct channel *channel, *tmp; - - pr_info("exit()\n"); - - list_for_each_entry_safe(channel, tmp, &dev_list, list) { - list_del(&channel->list); - snd_card_free(channel->card); - } - - most_deregister_aim(&audio_aim); -} - -module_init(audio_init); -module_exit(audio_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Gromm "); -MODULE_DESCRIPTION("Audio Application Interface Module for MostCore"); diff --git a/drivers/staging/most/sound/Kconfig b/drivers/staging/most/sound/Kconfig new file mode 100644 index 000000000000..115262a58a42 --- /dev/null +++ b/drivers/staging/most/sound/Kconfig @@ -0,0 +1,13 @@ +# +# MOST ALSA configuration +# + +config MOST_SOUND + tristate "Sound" + depends on SND + select SND_PCM + ---help--- + Say Y here if you want to commumicate via ALSA/sound devices. + + To compile this driver as a module, choose M here: the + module will be called most_sound. diff --git a/drivers/staging/most/sound/Makefile b/drivers/staging/most/sound/Makefile new file mode 100644 index 000000000000..eee8774e38cb --- /dev/null +++ b/drivers/staging/most/sound/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_SOUND) += most_sound.o + +most_sound-objs := sound.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c new file mode 100644 index 000000000000..5826f710c925 --- /dev/null +++ b/drivers/staging/most/sound/sound.c @@ -0,0 +1,759 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sound.c - Audio Application Interface Module for Mostcore + * + * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "sound" + +static struct list_head dev_list; +static struct most_aim audio_aim; + +/** + * struct channel - private structure to keep channel specific data + * @substream: stores the substream structure + * @iface: interface for which the channel belongs to + * @cfg: channel configuration + * @card: registered sound card + * @list: list for private use + * @id: channel index + * @period_pos: current period position (ring buffer) + * @buffer_pos: current buffer position (ring buffer) + * @is_stream_running: identifies whether a stream is running or not + * @opened: set when the stream is opened + * @playback_task: playback thread + * @playback_waitq: waitq used by playback thread + */ +struct channel { + struct snd_pcm_substream *substream; + struct snd_pcm_hardware pcm_hardware; + struct most_interface *iface; + struct most_channel_config *cfg; + struct snd_card *card; + struct list_head list; + int id; + unsigned int period_pos; + unsigned int buffer_pos; + bool is_stream_running; + + struct task_struct *playback_task; + wait_queue_head_t playback_waitq; + + void (*copy_fn)(void *alsa, void *most, unsigned int bytes); +}; + +#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \ + SNDRV_PCM_INFO_MMAP_VALID | \ + SNDRV_PCM_INFO_BATCH | \ + SNDRV_PCM_INFO_INTERLEAVED | \ + SNDRV_PCM_INFO_BLOCK_TRANSFER) + +#define swap16(val) ( \ + (((u16)(val) << 8) & (u16)0xFF00) | \ + (((u16)(val) >> 8) & (u16)0x00FF)) + +#define swap32(val) ( \ + (((u32)(val) << 24) & (u32)0xFF000000) | \ + (((u32)(val) << 8) & (u32)0x00FF0000) | \ + (((u32)(val) >> 8) & (u32)0x0000FF00) | \ + (((u32)(val) >> 24) & (u32)0x000000FF)) + +static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes) +{ + unsigned int i = 0; + + while (i < (bytes / 2)) { + dest[i] = swap16(source[i]); + i++; + } +} + +static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes) +{ + unsigned int i = 0; + + while (i < bytes - 2) { + dest[i] = source[i + 2]; + dest[i + 1] = source[i + 1]; + dest[i + 2] = source[i]; + i += 3; + } +} + +static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes) +{ + unsigned int i = 0; + + while (i < bytes / 4) { + dest[i] = swap32(source[i]); + i++; + } +} + +static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes) +{ + memcpy(most, alsa, bytes); +} + +static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes) +{ + swap_copy16(most, alsa, bytes); +} + +static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes) +{ + swap_copy24(most, alsa, bytes); +} + +static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes) +{ + swap_copy32(most, alsa, bytes); +} + +static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes) +{ + memcpy(alsa, most, bytes); +} + +static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes) +{ + swap_copy16(alsa, most, bytes); +} + +static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes) +{ + swap_copy24(alsa, most, bytes); +} + +static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes) +{ + swap_copy32(alsa, most, bytes); +} + +/** + * get_channel - get pointer to channel + * @iface: interface structure + * @channel_id: channel ID + * + * This traverses the channel list and returns the channel matching the + * ID and interface. + * + * Returns pointer to channel on success or NULL otherwise. + */ +static struct channel *get_channel(struct most_interface *iface, + int channel_id) +{ + struct channel *channel, *tmp; + + list_for_each_entry_safe(channel, tmp, &dev_list, list) { + if ((channel->iface == iface) && (channel->id == channel_id)) + return channel; + } + + return NULL; +} + +/** + * copy_data - implements data copying function + * @channel: channel + * @mbo: MBO from core + * + * Copy data from/to ring buffer to/from MBO and update the buffer position + */ +static bool copy_data(struct channel *channel, struct mbo *mbo) +{ + struct snd_pcm_runtime *const runtime = channel->substream->runtime; + unsigned int const frame_bytes = channel->cfg->subbuffer_size; + unsigned int const buffer_size = runtime->buffer_size; + unsigned int frames; + unsigned int fr0; + + if (channel->cfg->direction & MOST_CH_RX) + frames = mbo->processed_length / frame_bytes; + else + frames = mbo->buffer_length / frame_bytes; + fr0 = min(buffer_size - channel->buffer_pos, frames); + + channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes, + mbo->virt_address, + fr0 * frame_bytes); + + if (frames > fr0) { + /* wrap around at end of ring buffer */ + channel->copy_fn(runtime->dma_area, + mbo->virt_address + fr0 * frame_bytes, + (frames - fr0) * frame_bytes); + } + + channel->buffer_pos += frames; + if (channel->buffer_pos >= buffer_size) + channel->buffer_pos -= buffer_size; + channel->period_pos += frames; + if (channel->period_pos >= runtime->period_size) { + channel->period_pos -= runtime->period_size; + return true; + } + + return false; +} + +/** + * playback_thread - function implements the playback thread + * @data: private data + * + * Thread which does the playback functionality in a loop. It waits for a free + * MBO from mostcore for a particular channel and copy the data from ring buffer + * to MBO. Submit the MBO back to mostcore, after copying the data. + * + * Returns 0 on success or error code otherwise. + */ +static int playback_thread(void *data) +{ + struct channel *const channel = data; + + while (!kthread_should_stop()) { + struct mbo *mbo = NULL; + bool period_elapsed = false; + + wait_event_interruptible( + channel->playback_waitq, + kthread_should_stop() || + (channel->is_stream_running && + (mbo = most_get_mbo(channel->iface, channel->id, + &audio_aim)))); + if (!mbo) + continue; + + if (channel->is_stream_running) + period_elapsed = copy_data(channel, mbo); + else + memset(mbo->virt_address, 0, mbo->buffer_length); + + most_submit_mbo(mbo); + if (period_elapsed) + snd_pcm_period_elapsed(channel->substream); + } + + return 0; +} + +/** + * pcm_open - implements open callback function for PCM middle layer + * @substream: pointer to ALSA PCM substream + * + * This is called when a PCM substream is opened. At least, the function should + * initialize the runtime->hw record. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_open(struct snd_pcm_substream *substream) +{ + struct channel *channel = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct most_channel_config *cfg = channel->cfg; + + channel->substream = substream; + + if (cfg->direction == MOST_CH_TX) { + channel->playback_task = kthread_run(playback_thread, channel, + "most_audio_playback"); + if (IS_ERR(channel->playback_task)) { + pr_err("Couldn't start thread\n"); + return PTR_ERR(channel->playback_task); + } + } + + if (most_start_channel(channel->iface, channel->id, &audio_aim)) { + pr_err("most_start_channel() failed!\n"); + if (cfg->direction == MOST_CH_TX) + kthread_stop(channel->playback_task); + return -EBUSY; + } + + runtime->hw = channel->pcm_hardware; + return 0; +} + +/** + * pcm_close - implements close callback function for PCM middle layer + * @substream: sub-stream pointer + * + * Obviously, this is called when a PCM substream is closed. Any private + * instance for a PCM substream allocated in the open callback will be + * released here. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_close(struct snd_pcm_substream *substream) +{ + struct channel *channel = substream->private_data; + + if (channel->cfg->direction == MOST_CH_TX) + kthread_stop(channel->playback_task); + most_stop_channel(channel->iface, channel->id, &audio_aim); + + return 0; +} + +/** + * pcm_hw_params - implements hw_params callback function for PCM middle layer + * @substream: sub-stream pointer + * @hw_params: contains the hardware parameters set by the application + * + * This is called when the hardware parameters is set by the application, that + * is, once when the buffer size, the period size, the format, etc. are defined + * for the PCM substream. Many hardware setups should be done is this callback, + * including the allocation of buffers. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct channel *channel = substream->private_data; + + if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) || + (params_channels(hw_params) < channel->pcm_hardware.channels_min)) { + pr_err("Requested number of channels not supported.\n"); + return -EINVAL; + } + return snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); +} + +/** + * pcm_hw_free - implements hw_free callback function for PCM middle layer + * @substream: substream pointer + * + * This is called to release the resources allocated via hw_params. + * This function will be always called before the close callback is called. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_hw_free(struct snd_pcm_substream *substream) +{ + return snd_pcm_lib_free_vmalloc_buffer(substream); +} + +/** + * pcm_prepare - implements prepare callback function for PCM middle layer + * @substream: substream pointer + * + * This callback is called when the PCM is "prepared". Format rate, sample rate, + * etc., can be set here. This callback can be called many times at each setup. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_prepare(struct snd_pcm_substream *substream) +{ + struct channel *channel = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct most_channel_config *cfg = channel->cfg; + int width = snd_pcm_format_physical_width(runtime->format); + + channel->copy_fn = NULL; + + if (cfg->direction == MOST_CH_TX) { + if (snd_pcm_format_big_endian(runtime->format) || width == 8) + channel->copy_fn = alsa_to_most_memcpy; + else if (width == 16) + channel->copy_fn = alsa_to_most_copy16; + else if (width == 24) + channel->copy_fn = alsa_to_most_copy24; + else if (width == 32) + channel->copy_fn = alsa_to_most_copy32; + } else { + if (snd_pcm_format_big_endian(runtime->format) || width == 8) + channel->copy_fn = most_to_alsa_memcpy; + else if (width == 16) + channel->copy_fn = most_to_alsa_copy16; + else if (width == 24) + channel->copy_fn = most_to_alsa_copy24; + else if (width == 32) + channel->copy_fn = most_to_alsa_copy32; + } + + if (!channel->copy_fn) { + pr_err("unsupported format\n"); + return -EINVAL; + } + + channel->period_pos = 0; + channel->buffer_pos = 0; + + return 0; +} + +/** + * pcm_trigger - implements trigger callback function for PCM middle layer + * @substream: substream pointer + * @cmd: action to perform + * + * This is called when the PCM is started, stopped or paused. The action will be + * specified in the second argument, SNDRV_PCM_TRIGGER_XXX + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct channel *channel = substream->private_data; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + channel->is_stream_running = true; + wake_up_interruptible(&channel->playback_waitq); + return 0; + + case SNDRV_PCM_TRIGGER_STOP: + channel->is_stream_running = false; + return 0; + + default: + pr_info("%s(), invalid\n", __func__); + return -EINVAL; + } + return 0; +} + +/** + * pcm_pointer - implements pointer callback function for PCM middle layer + * @substream: substream pointer + * + * This callback is called when the PCM middle layer inquires the current + * hardware position on the buffer. The position must be returned in frames, + * ranging from 0 to buffer_size-1. + */ +static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) +{ + struct channel *channel = substream->private_data; + + return channel->buffer_pos; +} + +/** + * Initialization of struct snd_pcm_ops + */ +static const struct snd_pcm_ops pcm_ops = { + .open = pcm_open, + .close = pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, + .prepare = pcm_prepare, + .trigger = pcm_trigger, + .pointer = pcm_pointer, + .page = snd_pcm_lib_get_vmalloc_page, + .mmap = snd_pcm_lib_mmap_vmalloc, +}; + +static int split_arg_list(char *buf, char **card_name, char **pcm_format) +{ + *card_name = strsep(&buf, "."); + if (!*card_name) + return -EIO; + *pcm_format = strsep(&buf, ".\n"); + if (!*pcm_format) + return -EIO; + return 0; +} + +static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw, + char *pcm_format, + struct most_channel_config *cfg) +{ + pcm_hw->info = MOST_PCM_INFO; + pcm_hw->rates = SNDRV_PCM_RATE_48000; + pcm_hw->rate_min = 48000; + pcm_hw->rate_max = 48000; + pcm_hw->buffer_bytes_max = cfg->num_buffers * cfg->buffer_size; + pcm_hw->period_bytes_min = cfg->buffer_size; + pcm_hw->period_bytes_max = cfg->buffer_size; + pcm_hw->periods_min = 1; + pcm_hw->periods_max = cfg->num_buffers; + + if (!strcmp(pcm_format, "1x8")) { + if (cfg->subbuffer_size != 1) + goto error; + pr_info("PCM format is 8-bit mono\n"); + pcm_hw->channels_min = 1; + pcm_hw->channels_max = 1; + pcm_hw->formats = SNDRV_PCM_FMTBIT_S8; + } else if (!strcmp(pcm_format, "2x16")) { + if (cfg->subbuffer_size != 4) + goto error; + pr_info("PCM format is 16-bit stereo\n"); + pcm_hw->channels_min = 2; + pcm_hw->channels_max = 2; + pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S16_BE; + } else if (!strcmp(pcm_format, "2x24")) { + if (cfg->subbuffer_size != 6) + goto error; + pr_info("PCM format is 24-bit stereo\n"); + pcm_hw->channels_min = 2; + pcm_hw->channels_max = 2; + pcm_hw->formats = SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S24_3BE; + } else if (!strcmp(pcm_format, "2x32")) { + if (cfg->subbuffer_size != 8) + goto error; + pr_info("PCM format is 32-bit stereo\n"); + pcm_hw->channels_min = 2; + pcm_hw->channels_max = 2; + pcm_hw->formats = SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE; + } else if (!strcmp(pcm_format, "6x16")) { + if (cfg->subbuffer_size != 12) + goto error; + pr_info("PCM format is 16-bit 5.1 multi channel\n"); + pcm_hw->channels_min = 6; + pcm_hw->channels_max = 6; + pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S16_BE; + } else { + pr_err("PCM format %s not supported\n", pcm_format); + return -EIO; + } + return 0; +error: + pr_err("Audio resolution doesn't fit subbuffer size\n"); + return -EINVAL; +} + +/** + * audio_probe_channel - probe function of the driver module + * @iface: pointer to interface instance + * @channel_id: channel index/ID + * @cfg: pointer to actual channel configuration + * @parent: pointer to kobject (needed for sysfs hook-up) + * @arg_list: string that provides the name of the device to be created in /dev + * plus the desired audio resolution + * + * Creates sound card, pcm device, sets pcm ops and registers sound card. + * + * Returns 0 on success or error code otherwise. + */ +static int audio_probe_channel(struct most_interface *iface, int channel_id, + struct most_channel_config *cfg, + struct kobject *parent, char *arg_list) +{ + struct channel *channel; + struct snd_card *card; + struct snd_pcm *pcm; + int playback_count = 0; + int capture_count = 0; + int ret; + int direction; + char *card_name; + char *pcm_format; + + if (!iface) + return -EINVAL; + + if (cfg->data_type != MOST_CH_SYNC) { + pr_err("Incompatible channel type\n"); + return -EINVAL; + } + + if (get_channel(iface, channel_id)) { + pr_err("channel (%s:%d) is already linked\n", + iface->description, channel_id); + return -EINVAL; + } + + if (cfg->direction == MOST_CH_TX) { + playback_count = 1; + direction = SNDRV_PCM_STREAM_PLAYBACK; + } else { + capture_count = 1; + direction = SNDRV_PCM_STREAM_CAPTURE; + } + + ret = split_arg_list(arg_list, &card_name, &pcm_format); + if (ret < 0) { + pr_info("PCM format missing\n"); + return ret; + } + + ret = snd_card_new(NULL, -1, card_name, THIS_MODULE, + sizeof(*channel), &card); + if (ret < 0) + return ret; + + channel = card->private_data; + channel->card = card; + channel->cfg = cfg; + channel->iface = iface; + channel->id = channel_id; + init_waitqueue_head(&channel->playback_waitq); + + ret = audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg); + if (ret) + goto err_free_card; + + snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME); + snprintf(card->shortname, sizeof(card->shortname), "Microchip MOST:%d", + card->number); + snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d", + card->shortname, iface->description, channel_id); + + ret = snd_pcm_new(card, card_name, 0, playback_count, + capture_count, &pcm); + if (ret < 0) + goto err_free_card; + + pcm->private_data = channel; + + snd_pcm_set_ops(pcm, direction, &pcm_ops); + + ret = snd_card_register(card); + if (ret < 0) + goto err_free_card; + + list_add_tail(&channel->list, &dev_list); + + return 0; + +err_free_card: + snd_card_free(card); + return ret; +} + +/** + * audio_disconnect_channel - function to disconnect a channel + * @iface: pointer to interface instance + * @channel_id: channel index + * + * This frees allocated memory and removes the sound card from ALSA + * + * Returns 0 on success or error code otherwise. + */ +static int audio_disconnect_channel(struct most_interface *iface, + int channel_id) +{ + struct channel *channel; + + channel = get_channel(iface, channel_id); + if (!channel) { + pr_err("sound_disconnect_channel(), invalid channel %d\n", + channel_id); + return -EINVAL; + } + + list_del(&channel->list); + snd_card_free(channel->card); + + return 0; +} + +/** + * audio_rx_completion - completion handler for rx channels + * @mbo: pointer to buffer object that has completed + * + * This searches for the channel this MBO belongs to and copy the data from MBO + * to ring buffer + * + * Returns 0 on success or error code otherwise. + */ +static int audio_rx_completion(struct mbo *mbo) +{ + struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id); + bool period_elapsed = false; + + if (!channel) { + pr_err("sound_rx_completion(), invalid channel %d\n", + mbo->hdm_channel_id); + return -EINVAL; + } + + if (channel->is_stream_running) + period_elapsed = copy_data(channel, mbo); + + most_put_mbo(mbo); + + if (period_elapsed) + snd_pcm_period_elapsed(channel->substream); + + return 0; +} + +/** + * audio_tx_completion - completion handler for tx channels + * @iface: pointer to interface instance + * @channel_id: channel index/ID + * + * This searches the channel that belongs to this combination of interface + * pointer and channel ID and wakes a process sitting in the wait queue of + * this channel. + * + * Returns 0 on success or error code otherwise. + */ +static int audio_tx_completion(struct most_interface *iface, int channel_id) +{ + struct channel *channel = get_channel(iface, channel_id); + + if (!channel) { + pr_err("sound_tx_completion(), invalid channel %d\n", + channel_id); + return -EINVAL; + } + + wake_up_interruptible(&channel->playback_waitq); + + return 0; +} + +/** + * Initialization of the struct most_aim + */ +static struct most_aim audio_aim = { + .name = DRIVER_NAME, + .probe_channel = audio_probe_channel, + .disconnect_channel = audio_disconnect_channel, + .rx_completion = audio_rx_completion, + .tx_completion = audio_tx_completion, +}; + +static int __init audio_init(void) +{ + pr_info("init()\n"); + + INIT_LIST_HEAD(&dev_list); + + return most_register_aim(&audio_aim); +} + +static void __exit audio_exit(void) +{ + struct channel *channel, *tmp; + + pr_info("exit()\n"); + + list_for_each_entry_safe(channel, tmp, &dev_list, list) { + list_del(&channel->list); + snd_card_free(channel->card); + } + + most_deregister_aim(&audio_aim); +} + +module_init(audio_init); +module_exit(audio_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Gromm "); +MODULE_DESCRIPTION("Audio Application Interface Module for MostCore"); -- cgit v1.2.3 From 6e01fc7775ffb59750f9563f96418fad5886ac16 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:41 +0100 Subject: staging: most: usb: rename module This patch renames the folder of the usb module. It is needed to clean up the directory layout of the driver. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Kconfig | 2 +- drivers/staging/most/hdm-usb/Kconfig | 14 - drivers/staging/most/hdm-usb/hdm_usb.c | 1300 -------------------------------- drivers/staging/most/usb/Kconfig | 13 + drivers/staging/most/usb/Makefile | 4 + drivers/staging/most/usb/usb.c | 1300 ++++++++++++++++++++++++++++++++ 6 files changed, 1318 insertions(+), 1315 deletions(-) delete mode 100644 drivers/staging/most/hdm-usb/Kconfig delete mode 100644 drivers/staging/most/hdm-usb/hdm_usb.c create mode 100644 drivers/staging/most/usb/Kconfig create mode 100644 drivers/staging/most/usb/Makefile create mode 100644 drivers/staging/most/usb/usb.c (limited to 'drivers') diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 3f127116476c..86d4f12596bb 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -29,6 +29,6 @@ source "drivers/staging/most/dim2/Kconfig" source "drivers/staging/most/i2c/Kconfig" -source "drivers/staging/most/hdm-usb/Kconfig" +source "drivers/staging/most/usb/Kconfig" endif diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/hdm-usb/Kconfig deleted file mode 100644 index 487f1f34776c..000000000000 --- a/drivers/staging/most/hdm-usb/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# -# MOST USB configuration -# - -config HDM_USB - tristate "USB HDM" - depends on USB && NET - - ---help--- - Say Y here if you want to connect via USB to network tranceiver. - This device driver depends on the networking AIM. - - To compile this driver as a module, choose M here: the - module will be called hdm_usb. diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c deleted file mode 100644 index f036614a1da6..000000000000 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ /dev/null @@ -1,1300 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * hdm_usb.c - Hardware dependent module for USB - * - * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "most/core.h" - -#define USB_MTU 512 -#define NO_ISOCHRONOUS_URB 0 -#define AV_PACKETS_PER_XACT 2 -#define BUF_CHAIN_SIZE 0xFFFF -#define MAX_NUM_ENDPOINTS 30 -#define MAX_SUFFIX_LEN 10 -#define MAX_STRING_LEN 80 -#define MAX_BUF_SIZE 0xFFFF - -#define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */ -#define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */ -#define USB_DEV_ID_OS81118 0xCF18 /* PID: USB OS81118 */ -#define USB_DEV_ID_OS81119 0xCF19 /* PID: USB OS81119 */ -#define USB_DEV_ID_OS81210 0xCF30 /* PID: USB OS81210 */ -/* DRCI Addresses */ -#define DRCI_REG_NI_STATE 0x0100 -#define DRCI_REG_PACKET_BW 0x0101 -#define DRCI_REG_NODE_ADDR 0x0102 -#define DRCI_REG_NODE_POS 0x0103 -#define DRCI_REG_MEP_FILTER 0x0140 -#define DRCI_REG_HASH_TBL0 0x0141 -#define DRCI_REG_HASH_TBL1 0x0142 -#define DRCI_REG_HASH_TBL2 0x0143 -#define DRCI_REG_HASH_TBL3 0x0144 -#define DRCI_REG_HW_ADDR_HI 0x0145 -#define DRCI_REG_HW_ADDR_MI 0x0146 -#define DRCI_REG_HW_ADDR_LO 0x0147 -#define DRCI_REG_BASE 0x1100 -#define DRCI_COMMAND 0x02 -#define DRCI_READ_REQ 0xA0 -#define DRCI_WRITE_REQ 0xA1 - -/** - * struct most_dci_obj - Direct Communication Interface - * @kobj:position in sysfs - * @usb_device: pointer to the usb device - * @reg_addr: register address for arbitrary DCI access - */ -struct most_dci_obj { - struct kobject kobj; - struct usb_device *usb_device; - u16 reg_addr; -}; - -#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) - -struct most_dev; - -struct clear_hold_work { - struct work_struct ws; - struct most_dev *mdev; - unsigned int channel; - int pipe; -}; - -#define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws) - -/** - * struct most_dev - holds all usb interface specific stuff - * @parent: parent object in sysfs - * @usb_device: pointer to usb device - * @iface: hardware interface - * @cap: channel capabilities - * @conf: channel configuration - * @dci: direct communication interface of hardware - * @ep_address: endpoint address table - * @description: device description - * @suffix: suffix for channel name - * @channel_lock: synchronize channel access - * @padding_active: indicates channel uses padding - * @is_channel_healthy: health status table of each channel - * @busy_urbs: list of anchored items - * @io_mutex: synchronize I/O with disconnect - * @link_stat_timer: timer for link status reports - * @poll_work_obj: work for polling link status - */ -struct most_dev { - struct kobject *parent; - struct usb_device *usb_device; - struct most_interface iface; - struct most_channel_capability *cap; - struct most_channel_config *conf; - struct most_dci_obj *dci; - u8 *ep_address; - char description[MAX_STRING_LEN]; - char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN]; - spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */ - bool padding_active[MAX_NUM_ENDPOINTS]; - bool is_channel_healthy[MAX_NUM_ENDPOINTS]; - struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS]; - struct usb_anchor *busy_urbs; - struct mutex io_mutex; - struct timer_list link_stat_timer; - struct work_struct poll_work_obj; - void (*on_netinfo)(struct most_interface *, unsigned char, - unsigned char *); -}; - -#define to_mdev(d) container_of(d, struct most_dev, iface) -#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj) - -static void wq_clear_halt(struct work_struct *wq_obj); -static void wq_netinfo(struct work_struct *wq_obj); - -/** - * drci_rd_reg - read a DCI register - * @dev: usb device - * @reg: register address - * @buf: buffer to store data - * - * This is reads data from INIC's direct register communication interface - */ -static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf) -{ - int retval; - __le16 *dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL); - u8 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - - if (!dma_buf) - return -ENOMEM; - - retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - DRCI_READ_REQ, req_type, - 0x0000, - reg, dma_buf, sizeof(*dma_buf), 5 * HZ); - *buf = le16_to_cpu(*dma_buf); - kfree(dma_buf); - - return retval; -} - -/** - * drci_wr_reg - write a DCI register - * @dev: usb device - * @reg: register address - * @data: data to write - * - * This is writes data to INIC's direct register communication interface - */ -static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) -{ - return usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - DRCI_WRITE_REQ, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - data, - reg, - NULL, - 0, - 5 * HZ); -} - -static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep) -{ - return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1); -} - -/** - * get_stream_frame_size - calculate frame size of current configuration - * @cfg: channel configuration - */ -static unsigned int get_stream_frame_size(struct most_channel_config *cfg) -{ - unsigned int frame_size = 0; - unsigned int sub_size = cfg->subbuffer_size; - - if (!sub_size) { - pr_warn("Misconfig: Subbuffer size zero.\n"); - return frame_size; - } - switch (cfg->data_type) { - case MOST_CH_ISOC: - frame_size = AV_PACKETS_PER_XACT * sub_size; - break; - case MOST_CH_SYNC: - if (cfg->packets_per_xact == 0) { - pr_warn("Misconfig: Packets per XACT zero\n"); - frame_size = 0; - } else if (cfg->packets_per_xact == 0xFF) { - frame_size = (USB_MTU / sub_size) * sub_size; - } else { - frame_size = cfg->packets_per_xact * sub_size; - } - break; - default: - pr_warn("Query frame size of non-streaming channel\n"); - break; - } - return frame_size; -} - -/** - * hdm_poison_channel - mark buffers of this channel as invalid - * @iface: pointer to the interface - * @channel: channel ID - * - * This unlinks all URBs submitted to the HCD, - * calls the associated completion function of the core and removes - * them from the list. - * - * Returns 0 on success or error code otherwise. - */ -static int hdm_poison_channel(struct most_interface *iface, int channel) -{ - struct most_dev *mdev = to_mdev(iface); - unsigned long flags; - spinlock_t *lock; /* temp. lock */ - - if (unlikely(!iface)) { - dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n"); - return -EIO; - } - if (unlikely(channel < 0 || channel >= iface->num_channels)) { - dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n"); - return -ECHRNG; - } - - lock = mdev->channel_lock + channel; - spin_lock_irqsave(lock, flags); - mdev->is_channel_healthy[channel] = false; - spin_unlock_irqrestore(lock, flags); - - cancel_work_sync(&mdev->clear_work[channel].ws); - - mutex_lock(&mdev->io_mutex); - usb_kill_anchored_urbs(&mdev->busy_urbs[channel]); - if (mdev->padding_active[channel]) - mdev->padding_active[channel] = false; - - if (mdev->conf[channel].data_type == MOST_CH_ASYNC) { - del_timer_sync(&mdev->link_stat_timer); - cancel_work_sync(&mdev->poll_work_obj); - } - mutex_unlock(&mdev->io_mutex); - return 0; -} - -/** - * hdm_add_padding - add padding bytes - * @mdev: most device - * @channel: channel ID - * @mbo: buffer object - * - * This inserts the INIC hardware specific padding bytes into a streaming - * channel's buffer - */ -static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo) -{ - struct most_channel_config *conf = &mdev->conf[channel]; - unsigned int frame_size = get_stream_frame_size(conf); - unsigned int j, num_frames; - - if (!frame_size) - return -EIO; - num_frames = mbo->buffer_length / frame_size; - - if (num_frames < 1) { - dev_err(&mdev->usb_device->dev, - "Missed minimal transfer unit.\n"); - return -EIO; - } - - for (j = num_frames - 1; j > 0; j--) - memmove(mbo->virt_address + j * USB_MTU, - mbo->virt_address + j * frame_size, - frame_size); - mbo->buffer_length = num_frames * USB_MTU; - return 0; -} - -/** - * hdm_remove_padding - remove padding bytes - * @mdev: most device - * @channel: channel ID - * @mbo: buffer object - * - * This takes the INIC hardware specific padding bytes off a streaming - * channel's buffer. - */ -static int hdm_remove_padding(struct most_dev *mdev, int channel, - struct mbo *mbo) -{ - struct most_channel_config *const conf = &mdev->conf[channel]; - unsigned int frame_size = get_stream_frame_size(conf); - unsigned int j, num_frames; - - if (!frame_size) - return -EIO; - num_frames = mbo->processed_length / USB_MTU; - - for (j = 1; j < num_frames; j++) - memmove(mbo->virt_address + frame_size * j, - mbo->virt_address + USB_MTU * j, - frame_size); - - mbo->processed_length = frame_size * num_frames; - return 0; -} - -/** - * hdm_write_completion - completion function for submitted Tx URBs - * @urb: the URB that has been completed - * - * This checks the status of the completed URB. In case the URB has been - * unlinked before, it is immediately freed. On any other error the MBO - * transfer flag is set. On success it frees allocated resources and calls - * the completion function. - * - * Context: interrupt! - */ -static void hdm_write_completion(struct urb *urb) -{ - struct mbo *mbo = urb->context; - struct most_dev *mdev = to_mdev(mbo->ifp); - unsigned int channel = mbo->hdm_channel_id; - struct device *dev = &mdev->usb_device->dev; - spinlock_t *lock = mdev->channel_lock + channel; - unsigned long flags; - - spin_lock_irqsave(lock, flags); - - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - if (likely(mdev->is_channel_healthy[channel])) { - switch (urb->status) { - case 0: - case -ESHUTDOWN: - mbo->processed_length = urb->actual_length; - mbo->status = MBO_SUCCESS; - break; - case -EPIPE: - dev_warn(dev, "Broken OUT pipe detected\n"); - mdev->is_channel_healthy[channel] = false; - mdev->clear_work[channel].pipe = urb->pipe; - schedule_work(&mdev->clear_work[channel].ws); - break; - case -ENODEV: - case -EPROTO: - mbo->status = MBO_E_CLOSE; - break; - } - } - - spin_unlock_irqrestore(lock, flags); - - if (likely(mbo->complete)) - mbo->complete(mbo); - usb_free_urb(urb); -} - -/** - * hdm_read_completion - completion function for submitted Rx URBs - * @urb: the URB that has been completed - * - * This checks the status of the completed URB. In case the URB has been - * unlinked before it is immediately freed. On any other error the MBO transfer - * flag is set. On success it frees allocated resources, removes - * padding bytes -if necessary- and calls the completion function. - * - * Context: interrupt! - * - * ************************************************************************** - * Error codes returned by in urb->status - * or in iso_frame_desc[n].status (for ISO) - * ************************************************************************* - * - * USB device drivers may only test urb status values in completion handlers. - * This is because otherwise there would be a race between HCDs updating - * these values on one CPU, and device drivers testing them on another CPU. - * - * A transfer's actual_length may be positive even when an error has been - * reported. That's because transfers often involve several packets, so that - * one or more packets could finish before an error stops further endpoint I/O. - * - * For isochronous URBs, the urb status value is non-zero only if the URB is - * unlinked, the device is removed, the host controller is disabled or the total - * transferred length is less than the requested length and the URB_SHORT_NOT_OK - * flag is set. Completion handlers for isochronous URBs should only see - * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO. - * Individual frame descriptor status fields may report more status codes. - * - * - * 0 Transfer completed successfully - * - * -ENOENT URB was synchronously unlinked by usb_unlink_urb - * - * -EINPROGRESS URB still pending, no results yet - * (That is, if drivers see this it's a bug.) - * - * -EPROTO (*, **) a) bitstuff error - * b) no response packet received within the - * prescribed bus turn-around time - * c) unknown USB error - * - * -EILSEQ (*, **) a) CRC mismatch - * b) no response packet received within the - * prescribed bus turn-around time - * c) unknown USB error - * - * Note that often the controller hardware does not - * distinguish among cases a), b), and c), so a - * driver cannot tell whether there was a protocol - * error, a failure to respond (often caused by - * device disconnect), or some other fault. - * - * -ETIME (**) No response packet received within the prescribed - * bus turn-around time. This error may instead be - * reported as -EPROTO or -EILSEQ. - * - * -ETIMEDOUT Synchronous USB message functions use this code - * to indicate timeout expired before the transfer - * completed, and no other error was reported by HC. - * - * -EPIPE (**) Endpoint stalled. For non-control endpoints, - * reset this status with usb_clear_halt(). - * - * -ECOMM During an IN transfer, the host controller - * received data from an endpoint faster than it - * could be written to system memory - * - * -ENOSR During an OUT transfer, the host controller - * could not retrieve data from system memory fast - * enough to keep up with the USB data rate - * - * -EOVERFLOW (*) The amount of data returned by the endpoint was - * greater than either the max packet size of the - * endpoint or the remaining buffer size. "Babble". - * - * -EREMOTEIO The data read from the endpoint did not fill the - * specified buffer, and URB_SHORT_NOT_OK was set in - * urb->transfer_flags. - * - * -ENODEV Device was removed. Often preceded by a burst of - * other errors, since the hub driver doesn't detect - * device removal events immediately. - * - * -EXDEV ISO transfer only partially completed - * (only set in iso_frame_desc[n].status, not urb->status) - * - * -EINVAL ISO madness, if this happens: Log off and go home - * - * -ECONNRESET URB was asynchronously unlinked by usb_unlink_urb - * - * -ESHUTDOWN The device or host controller has been disabled due - * to some problem that could not be worked around, - * such as a physical disconnect. - * - * - * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate - * hardware problems such as bad devices (including firmware) or cables. - * - * (**) This is also one of several codes that different kinds of host - * controller use to indicate a transfer has failed because of device - * disconnect. In the interval before the hub driver starts disconnect - * processing, devices may receive such fault reports for every request. - * - * See - */ -static void hdm_read_completion(struct urb *urb) -{ - struct mbo *mbo = urb->context; - struct most_dev *mdev = to_mdev(mbo->ifp); - unsigned int channel = mbo->hdm_channel_id; - struct device *dev = &mdev->usb_device->dev; - spinlock_t *lock = mdev->channel_lock + channel; - unsigned long flags; - - spin_lock_irqsave(lock, flags); - - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - if (likely(mdev->is_channel_healthy[channel])) { - switch (urb->status) { - case 0: - case -ESHUTDOWN: - mbo->processed_length = urb->actual_length; - mbo->status = MBO_SUCCESS; - if (mdev->padding_active[channel] && - hdm_remove_padding(mdev, channel, mbo)) { - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - } - break; - case -EPIPE: - dev_warn(dev, "Broken IN pipe detected\n"); - mdev->is_channel_healthy[channel] = false; - mdev->clear_work[channel].pipe = urb->pipe; - schedule_work(&mdev->clear_work[channel].ws); - break; - case -ENODEV: - case -EPROTO: - mbo->status = MBO_E_CLOSE; - break; - case -EOVERFLOW: - dev_warn(dev, "Babble on IN pipe detected\n"); - break; - } - } - - spin_unlock_irqrestore(lock, flags); - - if (likely(mbo->complete)) - mbo->complete(mbo); - usb_free_urb(urb); -} - -/** - * hdm_enqueue - receive a buffer to be used for data transfer - * @iface: interface to enqueue to - * @channel: ID of the channel - * @mbo: pointer to the buffer object - * - * This allocates a new URB and fills it according to the channel - * that is being used for transmission of data. Before the URB is - * submitted it is stored in the private anchor list. - * - * Returns 0 on success. On any error the URB is freed and a error code - * is returned. - * - * Context: Could in _some_ cases be interrupt! - */ -static int hdm_enqueue(struct most_interface *iface, int channel, - struct mbo *mbo) -{ - struct most_dev *mdev; - struct most_channel_config *conf; - struct device *dev; - int retval = 0; - struct urb *urb; - unsigned long length; - void *virt_address; - - if (unlikely(!iface || !mbo)) - return -EIO; - if (unlikely(iface->num_channels <= channel || channel < 0)) - return -ECHRNG; - - mdev = to_mdev(iface); - conf = &mdev->conf[channel]; - dev = &mdev->usb_device->dev; - - if (!mdev->usb_device) - return -ENODEV; - - urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC); - if (!urb) - return -ENOMEM; - - if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] && - hdm_add_padding(mdev, channel, mbo)) { - retval = -EIO; - goto _error; - } - - urb->transfer_dma = mbo->bus_address; - virt_address = mbo->virt_address; - length = mbo->buffer_length; - - if (conf->direction & MOST_CH_TX) { - usb_fill_bulk_urb(urb, mdev->usb_device, - usb_sndbulkpipe(mdev->usb_device, - mdev->ep_address[channel]), - virt_address, - length, - hdm_write_completion, - mbo); - if (conf->data_type != MOST_CH_ISOC) - urb->transfer_flags |= URB_ZERO_PACKET; - } else { - usb_fill_bulk_urb(urb, mdev->usb_device, - usb_rcvbulkpipe(mdev->usb_device, - mdev->ep_address[channel]), - virt_address, - length + conf->extra_len, - hdm_read_completion, - mbo); - } - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_anchor_urb(urb, &mdev->busy_urbs[channel]); - - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) { - dev_err(dev, "URB submit failed with error %d.\n", retval); - goto _error_1; - } - return 0; - -_error_1: - usb_unanchor_urb(urb); -_error: - usb_free_urb(urb); - return retval; -} - -/** - * hdm_configure_channel - receive channel configuration from core - * @iface: interface - * @channel: channel ID - * @conf: structure that holds the configuration information - * - * The attached network interface controller (NIC) supports a padding mode - * to avoid short packets on USB, hence increasing the performance due to a - * lower interrupt load. This mode is default for synchronous data and can - * be switched on for isochronous data. In case padding is active the - * driver needs to know the frame size of the payload in order to calculate - * the number of bytes it needs to pad when transmitting or to cut off when - * receiving data. - * - */ -static int hdm_configure_channel(struct most_interface *iface, int channel, - struct most_channel_config *conf) -{ - unsigned int num_frames; - unsigned int frame_size; - struct most_dev *mdev = to_mdev(iface); - struct device *dev = &mdev->usb_device->dev; - - mdev->is_channel_healthy[channel] = true; - mdev->clear_work[channel].channel = channel; - mdev->clear_work[channel].mdev = mdev; - INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt); - - if (unlikely(!iface || !conf)) { - dev_err(dev, "Bad interface or config pointer.\n"); - return -EINVAL; - } - if (unlikely(channel < 0 || channel >= iface->num_channels)) { - dev_err(dev, "Channel ID out of range.\n"); - return -EINVAL; - } - if (!conf->num_buffers || !conf->buffer_size) { - dev_err(dev, "Misconfig: buffer size or #buffers zero.\n"); - return -EINVAL; - } - - if (conf->data_type != MOST_CH_SYNC && - !(conf->data_type == MOST_CH_ISOC && - conf->packets_per_xact != 0xFF)) { - mdev->padding_active[channel] = false; - /* - * Since the NIC's padding mode is not going to be - * used, we can skip the frame size calculations and - * move directly on to exit. - */ - goto exit; - } - - mdev->padding_active[channel] = true; - - frame_size = get_stream_frame_size(conf); - if (frame_size == 0 || frame_size > USB_MTU) { - dev_warn(dev, "Misconfig: frame size wrong\n"); - return -EINVAL; - } - - num_frames = conf->buffer_size / frame_size; - - if (conf->buffer_size % frame_size) { - u16 old_size = conf->buffer_size; - - conf->buffer_size = num_frames * frame_size; - dev_warn(dev, "%s: fixed buffer size (%d -> %d)\n", - mdev->suffix[channel], old_size, conf->buffer_size); - } - - /* calculate extra length to comply w/ HW padding */ - conf->extra_len = num_frames * (USB_MTU - frame_size); - -exit: - mdev->conf[channel] = *conf; - if (conf->data_type == MOST_CH_ASYNC) { - u16 ep = mdev->ep_address[channel]; - - if (start_sync_ep(mdev->usb_device, ep) < 0) - dev_warn(dev, "sync for ep%02x failed", ep); - } - return 0; -} - -/** - * hdm_request_netinfo - request network information - * @iface: pointer to interface - * @channel: channel ID - * - * This is used as trigger to set up the link status timer that - * polls for the NI state of the INIC every 2 seconds. - * - */ -static void hdm_request_netinfo(struct most_interface *iface, int channel, - void (*on_netinfo)(struct most_interface *, - unsigned char, - unsigned char *)) -{ - struct most_dev *mdev; - - BUG_ON(!iface); - mdev = to_mdev(iface); - mdev->on_netinfo = on_netinfo; - if (!on_netinfo) - return; - - mdev->link_stat_timer.expires = jiffies + HZ; - mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires); -} - -/** - * link_stat_timer_handler - schedule work obtaining mac address and link status - * @data: pointer to USB device instance - * - * The handler runs in interrupt context. That's why we need to defer the - * tasks to a work queue. - */ -static void link_stat_timer_handler(struct timer_list *t) -{ - struct most_dev *mdev = from_timer(mdev, t, link_stat_timer); - - schedule_work(&mdev->poll_work_obj); - mdev->link_stat_timer.expires = jiffies + (2 * HZ); - add_timer(&mdev->link_stat_timer); -} - -/** - * wq_netinfo - work queue function to deliver latest networking information - * @wq_obj: object that holds data for our deferred work to do - * - * This retrieves the network interface status of the USB INIC - */ -static void wq_netinfo(struct work_struct *wq_obj) -{ - struct most_dev *mdev = to_mdev_from_work(wq_obj); - struct usb_device *usb_device = mdev->usb_device; - struct device *dev = &usb_device->dev; - u16 hi, mi, lo, link; - u8 hw_addr[6]; - - if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) { - dev_err(dev, "Vendor request 'hw_addr_hi' failed\n"); - return; - } - - if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) { - dev_err(dev, "Vendor request 'hw_addr_mid' failed\n"); - return; - } - - if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) { - dev_err(dev, "Vendor request 'hw_addr_low' failed\n"); - return; - } - - if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) { - dev_err(dev, "Vendor request 'link status' failed\n"); - return; - } - - hw_addr[0] = hi >> 8; - hw_addr[1] = hi; - hw_addr[2] = mi >> 8; - hw_addr[3] = mi; - hw_addr[4] = lo >> 8; - hw_addr[5] = lo; - - if (mdev->on_netinfo) - mdev->on_netinfo(&mdev->iface, link, hw_addr); -} - -/** - * wq_clear_halt - work queue function - * @wq_obj: work_struct object to execute - * - * This sends a clear_halt to the given USB pipe. - */ -static void wq_clear_halt(struct work_struct *wq_obj) -{ - struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj); - struct most_dev *mdev = clear_work->mdev; - unsigned int channel = clear_work->channel; - int pipe = clear_work->pipe; - - mutex_lock(&mdev->io_mutex); - most_stop_enqueue(&mdev->iface, channel); - usb_kill_anchored_urbs(&mdev->busy_urbs[channel]); - if (usb_clear_halt(mdev->usb_device, pipe)) - dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); - - mdev->is_channel_healthy[channel] = true; - most_resume_enqueue(&mdev->iface, channel); - mutex_unlock(&mdev->io_mutex); -} - -/** - * hdm_usb_fops - file operation table for USB driver - */ -static const struct file_operations hdm_usb_fops = { - .owner = THIS_MODULE, -}; - -/** - * usb_device_id - ID table for HCD device probing - */ -static const struct usb_device_id usbid[] = { - { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), }, - { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), }, - { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), }, - { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), }, - { } /* Terminating entry */ -}; - -#define MOST_DCI_RO_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0444, show_value, NULL) - -#define MOST_DCI_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0644, show_value, store_value) - -#define MOST_DCI_WO_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0200, NULL, store_value) - -/** - * struct most_dci_attribute - to access the attributes of a dci object - * @attr: attributes of a dci object - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_dci_attribute { - struct attribute attr; - ssize_t (*show)(struct most_dci_obj *d, - struct most_dci_attribute *attr, - char *buf); - ssize_t (*store)(struct most_dci_obj *d, - struct most_dci_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr) - -/** - * dci_attr_show - show function for dci object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct most_dci_attribute *dci_attr = to_dci_attr(attr); - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - if (!dci_attr->show) - return -EIO; - - return dci_attr->show(dci_obj, dci_attr, buf); -} - -/** - * dci_attr_store - store function for dci object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t dci_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_dci_attribute *dci_attr = to_dci_attr(attr); - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - if (!dci_attr->store) - return -EIO; - - return dci_attr->store(dci_obj, dci_attr, buf, len); -} - -static const struct sysfs_ops most_dci_sysfs_ops = { - .show = dci_attr_show, - .store = dci_attr_store, -}; - -/** - * most_dci_release - release function for dci object - * @kobj: pointer to kobject - * - * This frees the memory allocated for the dci object - */ -static void most_dci_release(struct kobject *kobj) -{ - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - kfree(dci_obj); -} - -struct regs { - const char *name; - u16 reg; -}; - -static const struct regs ro_regs[] = { - { "ni_state", DRCI_REG_NI_STATE }, - { "packet_bandwidth", DRCI_REG_PACKET_BW }, - { "node_address", DRCI_REG_NODE_ADDR }, - { "node_position", DRCI_REG_NODE_POS }, -}; - -static const struct regs rw_regs[] = { - { "mep_filter", DRCI_REG_MEP_FILTER }, - { "mep_hash0", DRCI_REG_HASH_TBL0 }, - { "mep_hash1", DRCI_REG_HASH_TBL1 }, - { "mep_hash2", DRCI_REG_HASH_TBL2 }, - { "mep_hash3", DRCI_REG_HASH_TBL3 }, - { "mep_eui48_hi", DRCI_REG_HW_ADDR_HI }, - { "mep_eui48_mi", DRCI_REG_HW_ADDR_MI }, - { "mep_eui48_lo", DRCI_REG_HW_ADDR_LO }, -}; - -static int get_stat_reg_addr(const struct regs *regs, int size, - const char *name, u16 *reg_addr) -{ - int i; - - for (i = 0; i < size; i++) { - if (!strcmp(name, regs[i].name)) { - *reg_addr = regs[i].reg; - return 0; - } - } - return -EFAULT; -} - -#define get_static_reg_addr(regs, name, reg_addr) \ - get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr) - -static ssize_t show_value(struct most_dci_obj *dci_obj, - struct most_dci_attribute *attr, char *buf) -{ - const char *name = attr->attr.name; - u16 val; - u16 reg_addr; - int err; - - if (!strcmp(name, "arb_address")) - return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr); - - if (!strcmp(name, "arb_value")) - reg_addr = dci_obj->reg_addr; - else if (get_static_reg_addr(ro_regs, name, ®_addr) && - get_static_reg_addr(rw_regs, name, ®_addr)) - return -EFAULT; - - err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val); - if (err < 0) - return err; - - return snprintf(buf, PAGE_SIZE, "%04x\n", val); -} - -static ssize_t store_value(struct most_dci_obj *dci_obj, - struct most_dci_attribute *attr, - const char *buf, size_t count) -{ - u16 val; - u16 reg_addr; - const char *name = attr->attr.name; - struct usb_device *usb_dev = dci_obj->usb_device; - int err = kstrtou16(buf, 16, &val); - - if (err) - return err; - - if (!strcmp(name, "arb_address")) { - dci_obj->reg_addr = val; - return count; - } - - if (!strcmp(name, "arb_value")) - err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val); - else if (!strcmp(name, "sync_ep")) - err = start_sync_ep(usb_dev, val); - else if (!get_static_reg_addr(rw_regs, name, ®_addr)) - err = drci_wr_reg(usb_dev, reg_addr, val); - else - return -EFAULT; - - if (err < 0) - return err; - - return count; -} - -static MOST_DCI_RO_ATTR(ni_state); -static MOST_DCI_RO_ATTR(packet_bandwidth); -static MOST_DCI_RO_ATTR(node_address); -static MOST_DCI_RO_ATTR(node_position); -static MOST_DCI_WO_ATTR(sync_ep); -static MOST_DCI_ATTR(mep_filter); -static MOST_DCI_ATTR(mep_hash0); -static MOST_DCI_ATTR(mep_hash1); -static MOST_DCI_ATTR(mep_hash2); -static MOST_DCI_ATTR(mep_hash3); -static MOST_DCI_ATTR(mep_eui48_hi); -static MOST_DCI_ATTR(mep_eui48_mi); -static MOST_DCI_ATTR(mep_eui48_lo); -static MOST_DCI_ATTR(arb_address); -static MOST_DCI_ATTR(arb_value); - -/** - * most_dci_def_attrs - array of default attribute files of the dci object - */ -static struct attribute *most_dci_def_attrs[] = { - &most_dci_attr_ni_state.attr, - &most_dci_attr_packet_bandwidth.attr, - &most_dci_attr_node_address.attr, - &most_dci_attr_node_position.attr, - &most_dci_attr_sync_ep.attr, - &most_dci_attr_mep_filter.attr, - &most_dci_attr_mep_hash0.attr, - &most_dci_attr_mep_hash1.attr, - &most_dci_attr_mep_hash2.attr, - &most_dci_attr_mep_hash3.attr, - &most_dci_attr_mep_eui48_hi.attr, - &most_dci_attr_mep_eui48_mi.attr, - &most_dci_attr_mep_eui48_lo.attr, - &most_dci_attr_arb_address.attr, - &most_dci_attr_arb_value.attr, - NULL, -}; - -/** - * DCI ktype - */ -static struct kobj_type most_dci_ktype = { - .sysfs_ops = &most_dci_sysfs_ops, - .release = most_dci_release, - .default_attrs = most_dci_def_attrs, -}; - -/** - * create_most_dci_obj - allocates a dci object - * @parent: parent kobject - * - * This creates a dci object and registers it with sysfs. - * Returns a pointer to the object or NULL when something went wrong. - */ -static struct -most_dci_obj *create_most_dci_obj(struct kobject *parent) -{ - struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); - int retval; - - if (!most_dci) - return NULL; - - retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent, - "dci"); - if (retval) { - kobject_put(&most_dci->kobj); - return NULL; - } - return most_dci; -} - -/** - * destroy_most_dci_obj - DCI object release function - * @p: pointer to dci object - */ -static void destroy_most_dci_obj(struct most_dci_obj *p) -{ - kobject_put(&p->kobj); -} - -/** - * hdm_probe - probe function of USB device driver - * @interface: Interface of the attached USB device - * @id: Pointer to the USB ID table. - * - * This allocates and initializes the device instance, adds the new - * entry to the internal list, scans the USB descriptors and registers - * the interface with the core. - * Additionally, the DCI objects are created and the hardware is sync'd. - * - * Return 0 on success. In case of an error a negative number is returned. - */ -static int -hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_host_interface *usb_iface_desc = interface->cur_altsetting; - struct usb_device *usb_dev = interface_to_usbdev(interface); - struct device *dev = &usb_dev->dev; - struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - unsigned int i; - unsigned int num_endpoints; - struct most_channel_capability *tmp_cap; - struct usb_endpoint_descriptor *ep_desc; - int ret = 0; - - if (!mdev) - goto exit_ENOMEM; - - usb_set_intfdata(interface, mdev); - num_endpoints = usb_iface_desc->desc.bNumEndpoints; - mutex_init(&mdev->io_mutex); - INIT_WORK(&mdev->poll_work_obj, wq_netinfo); - timer_setup(&mdev->link_stat_timer, link_stat_timer_handler, 0); - - mdev->usb_device = usb_dev; - mdev->link_stat_timer.expires = jiffies + (2 * HZ); - - mdev->iface.mod = hdm_usb_fops.owner; - mdev->iface.interface = ITYPE_USB; - mdev->iface.configure = hdm_configure_channel; - mdev->iface.request_netinfo = hdm_request_netinfo; - mdev->iface.enqueue = hdm_enqueue; - mdev->iface.poison_channel = hdm_poison_channel; - mdev->iface.description = mdev->description; - mdev->iface.num_channels = num_endpoints; - - snprintf(mdev->description, sizeof(mdev->description), - "usb_device %d-%s:%d.%d", - usb_dev->bus->busnum, - usb_dev->devpath, - usb_dev->config->desc.bConfigurationValue, - usb_iface_desc->desc.bInterfaceNumber); - - mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL); - if (!mdev->conf) - goto exit_free; - - mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL); - if (!mdev->cap) - goto exit_free1; - - mdev->iface.channel_vector = mdev->cap; - mdev->iface.priv = NULL; - - mdev->ep_address = - kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL); - if (!mdev->ep_address) - goto exit_free2; - - mdev->busy_urbs = - kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL); - if (!mdev->busy_urbs) - goto exit_free3; - - tmp_cap = mdev->cap; - for (i = 0; i < num_endpoints; i++) { - ep_desc = &usb_iface_desc->endpoint[i].desc; - mdev->ep_address[i] = ep_desc->bEndpointAddress; - mdev->padding_active[i] = false; - mdev->is_channel_healthy[i] = true; - - snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x", - mdev->ep_address[i]); - - tmp_cap->name_suffix = &mdev->suffix[i][0]; - tmp_cap->buffer_size_packet = MAX_BUF_SIZE; - tmp_cap->buffer_size_streaming = MAX_BUF_SIZE; - tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE; - tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE; - tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | - MOST_CH_ISOC | MOST_CH_SYNC; - if (usb_endpoint_dir_in(ep_desc)) - tmp_cap->direction = MOST_CH_RX; - else - tmp_cap->direction = MOST_CH_TX; - tmp_cap++; - init_usb_anchor(&mdev->busy_urbs[i]); - spin_lock_init(&mdev->channel_lock[i]); - } - dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n", - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - usb_dev->bus->busnum, - usb_dev->devnum); - - dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n", - usb_dev->bus->busnum, - usb_dev->devpath, - usb_dev->config->desc.bConfigurationValue, - usb_iface_desc->desc.bInterfaceNumber); - - mdev->parent = most_register_interface(&mdev->iface); - if (IS_ERR(mdev->parent)) { - ret = PTR_ERR(mdev->parent); - goto exit_free4; - } - - mutex_lock(&mdev->io_mutex); - if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || - le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 || - le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) { - /* this increments the reference count of the instance - * object of the core - */ - mdev->dci = create_most_dci_obj(mdev->parent); - if (!mdev->dci) { - mutex_unlock(&mdev->io_mutex); - most_deregister_interface(&mdev->iface); - ret = -ENOMEM; - goto exit_free4; - } - - kobject_uevent(&mdev->dci->kobj, KOBJ_ADD); - mdev->dci->usb_device = mdev->usb_device; - } - mutex_unlock(&mdev->io_mutex); - return 0; - -exit_free4: - kfree(mdev->busy_urbs); -exit_free3: - kfree(mdev->ep_address); -exit_free2: - kfree(mdev->cap); -exit_free1: - kfree(mdev->conf); -exit_free: - kfree(mdev); -exit_ENOMEM: - if (ret == 0 || ret == -ENOMEM) { - ret = -ENOMEM; - dev_err(dev, "out of memory\n"); - } - return ret; -} - -/** - * hdm_disconnect - disconnect function of USB device driver - * @interface: Interface of the attached USB device - * - * This deregisters the interface with the core, removes the kernel timer - * and frees resources. - * - * Context: hub kernel thread - */ -static void hdm_disconnect(struct usb_interface *interface) -{ - struct most_dev *mdev = usb_get_intfdata(interface); - - mutex_lock(&mdev->io_mutex); - usb_set_intfdata(interface, NULL); - mdev->usb_device = NULL; - mutex_unlock(&mdev->io_mutex); - - del_timer_sync(&mdev->link_stat_timer); - cancel_work_sync(&mdev->poll_work_obj); - - destroy_most_dci_obj(mdev->dci); - most_deregister_interface(&mdev->iface); - - kfree(mdev->busy_urbs); - kfree(mdev->cap); - kfree(mdev->conf); - kfree(mdev->ep_address); - kfree(mdev); -} - -static struct usb_driver hdm_usb = { - .name = "hdm_usb", - .id_table = usbid, - .probe = hdm_probe, - .disconnect = hdm_disconnect, -}; - -module_usb_driver(hdm_usb); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Gromm "); -MODULE_DESCRIPTION("HDM_4_USB"); diff --git a/drivers/staging/most/usb/Kconfig b/drivers/staging/most/usb/Kconfig new file mode 100644 index 000000000000..ebbdb573a9a6 --- /dev/null +++ b/drivers/staging/most/usb/Kconfig @@ -0,0 +1,13 @@ +# +# MOST USB configuration +# + +config MOST_USB + tristate "USB" + depends on USB && NET + ---help--- + Say Y here if you want to connect via USB to network tranceiver. + This device driver depends on the networking AIM. + + To compile this driver as a module, choose M here: the + module will be called most_usb. diff --git a/drivers/staging/most/usb/Makefile b/drivers/staging/most/usb/Makefile new file mode 100644 index 000000000000..18d28cba4fbf --- /dev/null +++ b/drivers/staging/most/usb/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_USB) += most_usb.o + +most_usb-objs := usb.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c new file mode 100644 index 000000000000..b2d2abe15efe --- /dev/null +++ b/drivers/staging/most/usb/usb.c @@ -0,0 +1,1300 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * usb.c - Hardware dependent module for USB + * + * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "most/core.h" + +#define USB_MTU 512 +#define NO_ISOCHRONOUS_URB 0 +#define AV_PACKETS_PER_XACT 2 +#define BUF_CHAIN_SIZE 0xFFFF +#define MAX_NUM_ENDPOINTS 30 +#define MAX_SUFFIX_LEN 10 +#define MAX_STRING_LEN 80 +#define MAX_BUF_SIZE 0xFFFF + +#define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */ +#define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */ +#define USB_DEV_ID_OS81118 0xCF18 /* PID: USB OS81118 */ +#define USB_DEV_ID_OS81119 0xCF19 /* PID: USB OS81119 */ +#define USB_DEV_ID_OS81210 0xCF30 /* PID: USB OS81210 */ +/* DRCI Addresses */ +#define DRCI_REG_NI_STATE 0x0100 +#define DRCI_REG_PACKET_BW 0x0101 +#define DRCI_REG_NODE_ADDR 0x0102 +#define DRCI_REG_NODE_POS 0x0103 +#define DRCI_REG_MEP_FILTER 0x0140 +#define DRCI_REG_HASH_TBL0 0x0141 +#define DRCI_REG_HASH_TBL1 0x0142 +#define DRCI_REG_HASH_TBL2 0x0143 +#define DRCI_REG_HASH_TBL3 0x0144 +#define DRCI_REG_HW_ADDR_HI 0x0145 +#define DRCI_REG_HW_ADDR_MI 0x0146 +#define DRCI_REG_HW_ADDR_LO 0x0147 +#define DRCI_REG_BASE 0x1100 +#define DRCI_COMMAND 0x02 +#define DRCI_READ_REQ 0xA0 +#define DRCI_WRITE_REQ 0xA1 + +/** + * struct most_dci_obj - Direct Communication Interface + * @kobj:position in sysfs + * @usb_device: pointer to the usb device + * @reg_addr: register address for arbitrary DCI access + */ +struct most_dci_obj { + struct kobject kobj; + struct usb_device *usb_device; + u16 reg_addr; +}; + +#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) + +struct most_dev; + +struct clear_hold_work { + struct work_struct ws; + struct most_dev *mdev; + unsigned int channel; + int pipe; +}; + +#define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws) + +/** + * struct most_dev - holds all usb interface specific stuff + * @parent: parent object in sysfs + * @usb_device: pointer to usb device + * @iface: hardware interface + * @cap: channel capabilities + * @conf: channel configuration + * @dci: direct communication interface of hardware + * @ep_address: endpoint address table + * @description: device description + * @suffix: suffix for channel name + * @channel_lock: synchronize channel access + * @padding_active: indicates channel uses padding + * @is_channel_healthy: health status table of each channel + * @busy_urbs: list of anchored items + * @io_mutex: synchronize I/O with disconnect + * @link_stat_timer: timer for link status reports + * @poll_work_obj: work for polling link status + */ +struct most_dev { + struct kobject *parent; + struct usb_device *usb_device; + struct most_interface iface; + struct most_channel_capability *cap; + struct most_channel_config *conf; + struct most_dci_obj *dci; + u8 *ep_address; + char description[MAX_STRING_LEN]; + char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN]; + spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */ + bool padding_active[MAX_NUM_ENDPOINTS]; + bool is_channel_healthy[MAX_NUM_ENDPOINTS]; + struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS]; + struct usb_anchor *busy_urbs; + struct mutex io_mutex; + struct timer_list link_stat_timer; + struct work_struct poll_work_obj; + void (*on_netinfo)(struct most_interface *, unsigned char, + unsigned char *); +}; + +#define to_mdev(d) container_of(d, struct most_dev, iface) +#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj) + +static void wq_clear_halt(struct work_struct *wq_obj); +static void wq_netinfo(struct work_struct *wq_obj); + +/** + * drci_rd_reg - read a DCI register + * @dev: usb device + * @reg: register address + * @buf: buffer to store data + * + * This is reads data from INIC's direct register communication interface + */ +static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf) +{ + int retval; + __le16 *dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL); + u8 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + + if (!dma_buf) + return -ENOMEM; + + retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + DRCI_READ_REQ, req_type, + 0x0000, + reg, dma_buf, sizeof(*dma_buf), 5 * HZ); + *buf = le16_to_cpu(*dma_buf); + kfree(dma_buf); + + return retval; +} + +/** + * drci_wr_reg - write a DCI register + * @dev: usb device + * @reg: register address + * @data: data to write + * + * This is writes data to INIC's direct register communication interface + */ +static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) +{ + return usb_control_msg(dev, + usb_sndctrlpipe(dev, 0), + DRCI_WRITE_REQ, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + data, + reg, + NULL, + 0, + 5 * HZ); +} + +static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep) +{ + return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1); +} + +/** + * get_stream_frame_size - calculate frame size of current configuration + * @cfg: channel configuration + */ +static unsigned int get_stream_frame_size(struct most_channel_config *cfg) +{ + unsigned int frame_size = 0; + unsigned int sub_size = cfg->subbuffer_size; + + if (!sub_size) { + pr_warn("Misconfig: Subbuffer size zero.\n"); + return frame_size; + } + switch (cfg->data_type) { + case MOST_CH_ISOC: + frame_size = AV_PACKETS_PER_XACT * sub_size; + break; + case MOST_CH_SYNC: + if (cfg->packets_per_xact == 0) { + pr_warn("Misconfig: Packets per XACT zero\n"); + frame_size = 0; + } else if (cfg->packets_per_xact == 0xFF) { + frame_size = (USB_MTU / sub_size) * sub_size; + } else { + frame_size = cfg->packets_per_xact * sub_size; + } + break; + default: + pr_warn("Query frame size of non-streaming channel\n"); + break; + } + return frame_size; +} + +/** + * hdm_poison_channel - mark buffers of this channel as invalid + * @iface: pointer to the interface + * @channel: channel ID + * + * This unlinks all URBs submitted to the HCD, + * calls the associated completion function of the core and removes + * them from the list. + * + * Returns 0 on success or error code otherwise. + */ +static int hdm_poison_channel(struct most_interface *iface, int channel) +{ + struct most_dev *mdev = to_mdev(iface); + unsigned long flags; + spinlock_t *lock; /* temp. lock */ + + if (unlikely(!iface)) { + dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n"); + return -EIO; + } + if (unlikely(channel < 0 || channel >= iface->num_channels)) { + dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n"); + return -ECHRNG; + } + + lock = mdev->channel_lock + channel; + spin_lock_irqsave(lock, flags); + mdev->is_channel_healthy[channel] = false; + spin_unlock_irqrestore(lock, flags); + + cancel_work_sync(&mdev->clear_work[channel].ws); + + mutex_lock(&mdev->io_mutex); + usb_kill_anchored_urbs(&mdev->busy_urbs[channel]); + if (mdev->padding_active[channel]) + mdev->padding_active[channel] = false; + + if (mdev->conf[channel].data_type == MOST_CH_ASYNC) { + del_timer_sync(&mdev->link_stat_timer); + cancel_work_sync(&mdev->poll_work_obj); + } + mutex_unlock(&mdev->io_mutex); + return 0; +} + +/** + * hdm_add_padding - add padding bytes + * @mdev: most device + * @channel: channel ID + * @mbo: buffer object + * + * This inserts the INIC hardware specific padding bytes into a streaming + * channel's buffer + */ +static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo) +{ + struct most_channel_config *conf = &mdev->conf[channel]; + unsigned int frame_size = get_stream_frame_size(conf); + unsigned int j, num_frames; + + if (!frame_size) + return -EIO; + num_frames = mbo->buffer_length / frame_size; + + if (num_frames < 1) { + dev_err(&mdev->usb_device->dev, + "Missed minimal transfer unit.\n"); + return -EIO; + } + + for (j = num_frames - 1; j > 0; j--) + memmove(mbo->virt_address + j * USB_MTU, + mbo->virt_address + j * frame_size, + frame_size); + mbo->buffer_length = num_frames * USB_MTU; + return 0; +} + +/** + * hdm_remove_padding - remove padding bytes + * @mdev: most device + * @channel: channel ID + * @mbo: buffer object + * + * This takes the INIC hardware specific padding bytes off a streaming + * channel's buffer. + */ +static int hdm_remove_padding(struct most_dev *mdev, int channel, + struct mbo *mbo) +{ + struct most_channel_config *const conf = &mdev->conf[channel]; + unsigned int frame_size = get_stream_frame_size(conf); + unsigned int j, num_frames; + + if (!frame_size) + return -EIO; + num_frames = mbo->processed_length / USB_MTU; + + for (j = 1; j < num_frames; j++) + memmove(mbo->virt_address + frame_size * j, + mbo->virt_address + USB_MTU * j, + frame_size); + + mbo->processed_length = frame_size * num_frames; + return 0; +} + +/** + * hdm_write_completion - completion function for submitted Tx URBs + * @urb: the URB that has been completed + * + * This checks the status of the completed URB. In case the URB has been + * unlinked before, it is immediately freed. On any other error the MBO + * transfer flag is set. On success it frees allocated resources and calls + * the completion function. + * + * Context: interrupt! + */ +static void hdm_write_completion(struct urb *urb) +{ + struct mbo *mbo = urb->context; + struct most_dev *mdev = to_mdev(mbo->ifp); + unsigned int channel = mbo->hdm_channel_id; + struct device *dev = &mdev->usb_device->dev; + spinlock_t *lock = mdev->channel_lock + channel; + unsigned long flags; + + spin_lock_irqsave(lock, flags); + + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + if (likely(mdev->is_channel_healthy[channel])) { + switch (urb->status) { + case 0: + case -ESHUTDOWN: + mbo->processed_length = urb->actual_length; + mbo->status = MBO_SUCCESS; + break; + case -EPIPE: + dev_warn(dev, "Broken OUT pipe detected\n"); + mdev->is_channel_healthy[channel] = false; + mdev->clear_work[channel].pipe = urb->pipe; + schedule_work(&mdev->clear_work[channel].ws); + break; + case -ENODEV: + case -EPROTO: + mbo->status = MBO_E_CLOSE; + break; + } + } + + spin_unlock_irqrestore(lock, flags); + + if (likely(mbo->complete)) + mbo->complete(mbo); + usb_free_urb(urb); +} + +/** + * hdm_read_completion - completion function for submitted Rx URBs + * @urb: the URB that has been completed + * + * This checks the status of the completed URB. In case the URB has been + * unlinked before it is immediately freed. On any other error the MBO transfer + * flag is set. On success it frees allocated resources, removes + * padding bytes -if necessary- and calls the completion function. + * + * Context: interrupt! + * + * ************************************************************************** + * Error codes returned by in urb->status + * or in iso_frame_desc[n].status (for ISO) + * ************************************************************************* + * + * USB device drivers may only test urb status values in completion handlers. + * This is because otherwise there would be a race between HCDs updating + * these values on one CPU, and device drivers testing them on another CPU. + * + * A transfer's actual_length may be positive even when an error has been + * reported. That's because transfers often involve several packets, so that + * one or more packets could finish before an error stops further endpoint I/O. + * + * For isochronous URBs, the urb status value is non-zero only if the URB is + * unlinked, the device is removed, the host controller is disabled or the total + * transferred length is less than the requested length and the URB_SHORT_NOT_OK + * flag is set. Completion handlers for isochronous URBs should only see + * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO. + * Individual frame descriptor status fields may report more status codes. + * + * + * 0 Transfer completed successfully + * + * -ENOENT URB was synchronously unlinked by usb_unlink_urb + * + * -EINPROGRESS URB still pending, no results yet + * (That is, if drivers see this it's a bug.) + * + * -EPROTO (*, **) a) bitstuff error + * b) no response packet received within the + * prescribed bus turn-around time + * c) unknown USB error + * + * -EILSEQ (*, **) a) CRC mismatch + * b) no response packet received within the + * prescribed bus turn-around time + * c) unknown USB error + * + * Note that often the controller hardware does not + * distinguish among cases a), b), and c), so a + * driver cannot tell whether there was a protocol + * error, a failure to respond (often caused by + * device disconnect), or some other fault. + * + * -ETIME (**) No response packet received within the prescribed + * bus turn-around time. This error may instead be + * reported as -EPROTO or -EILSEQ. + * + * -ETIMEDOUT Synchronous USB message functions use this code + * to indicate timeout expired before the transfer + * completed, and no other error was reported by HC. + * + * -EPIPE (**) Endpoint stalled. For non-control endpoints, + * reset this status with usb_clear_halt(). + * + * -ECOMM During an IN transfer, the host controller + * received data from an endpoint faster than it + * could be written to system memory + * + * -ENOSR During an OUT transfer, the host controller + * could not retrieve data from system memory fast + * enough to keep up with the USB data rate + * + * -EOVERFLOW (*) The amount of data returned by the endpoint was + * greater than either the max packet size of the + * endpoint or the remaining buffer size. "Babble". + * + * -EREMOTEIO The data read from the endpoint did not fill the + * specified buffer, and URB_SHORT_NOT_OK was set in + * urb->transfer_flags. + * + * -ENODEV Device was removed. Often preceded by a burst of + * other errors, since the hub driver doesn't detect + * device removal events immediately. + * + * -EXDEV ISO transfer only partially completed + * (only set in iso_frame_desc[n].status, not urb->status) + * + * -EINVAL ISO madness, if this happens: Log off and go home + * + * -ECONNRESET URB was asynchronously unlinked by usb_unlink_urb + * + * -ESHUTDOWN The device or host controller has been disabled due + * to some problem that could not be worked around, + * such as a physical disconnect. + * + * + * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate + * hardware problems such as bad devices (including firmware) or cables. + * + * (**) This is also one of several codes that different kinds of host + * controller use to indicate a transfer has failed because of device + * disconnect. In the interval before the hub driver starts disconnect + * processing, devices may receive such fault reports for every request. + * + * See + */ +static void hdm_read_completion(struct urb *urb) +{ + struct mbo *mbo = urb->context; + struct most_dev *mdev = to_mdev(mbo->ifp); + unsigned int channel = mbo->hdm_channel_id; + struct device *dev = &mdev->usb_device->dev; + spinlock_t *lock = mdev->channel_lock + channel; + unsigned long flags; + + spin_lock_irqsave(lock, flags); + + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + if (likely(mdev->is_channel_healthy[channel])) { + switch (urb->status) { + case 0: + case -ESHUTDOWN: + mbo->processed_length = urb->actual_length; + mbo->status = MBO_SUCCESS; + if (mdev->padding_active[channel] && + hdm_remove_padding(mdev, channel, mbo)) { + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + } + break; + case -EPIPE: + dev_warn(dev, "Broken IN pipe detected\n"); + mdev->is_channel_healthy[channel] = false; + mdev->clear_work[channel].pipe = urb->pipe; + schedule_work(&mdev->clear_work[channel].ws); + break; + case -ENODEV: + case -EPROTO: + mbo->status = MBO_E_CLOSE; + break; + case -EOVERFLOW: + dev_warn(dev, "Babble on IN pipe detected\n"); + break; + } + } + + spin_unlock_irqrestore(lock, flags); + + if (likely(mbo->complete)) + mbo->complete(mbo); + usb_free_urb(urb); +} + +/** + * hdm_enqueue - receive a buffer to be used for data transfer + * @iface: interface to enqueue to + * @channel: ID of the channel + * @mbo: pointer to the buffer object + * + * This allocates a new URB and fills it according to the channel + * that is being used for transmission of data. Before the URB is + * submitted it is stored in the private anchor list. + * + * Returns 0 on success. On any error the URB is freed and a error code + * is returned. + * + * Context: Could in _some_ cases be interrupt! + */ +static int hdm_enqueue(struct most_interface *iface, int channel, + struct mbo *mbo) +{ + struct most_dev *mdev; + struct most_channel_config *conf; + struct device *dev; + int retval = 0; + struct urb *urb; + unsigned long length; + void *virt_address; + + if (unlikely(!iface || !mbo)) + return -EIO; + if (unlikely(iface->num_channels <= channel || channel < 0)) + return -ECHRNG; + + mdev = to_mdev(iface); + conf = &mdev->conf[channel]; + dev = &mdev->usb_device->dev; + + if (!mdev->usb_device) + return -ENODEV; + + urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC); + if (!urb) + return -ENOMEM; + + if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] && + hdm_add_padding(mdev, channel, mbo)) { + retval = -EIO; + goto _error; + } + + urb->transfer_dma = mbo->bus_address; + virt_address = mbo->virt_address; + length = mbo->buffer_length; + + if (conf->direction & MOST_CH_TX) { + usb_fill_bulk_urb(urb, mdev->usb_device, + usb_sndbulkpipe(mdev->usb_device, + mdev->ep_address[channel]), + virt_address, + length, + hdm_write_completion, + mbo); + if (conf->data_type != MOST_CH_ISOC) + urb->transfer_flags |= URB_ZERO_PACKET; + } else { + usb_fill_bulk_urb(urb, mdev->usb_device, + usb_rcvbulkpipe(mdev->usb_device, + mdev->ep_address[channel]), + virt_address, + length + conf->extra_len, + hdm_read_completion, + mbo); + } + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_anchor_urb(urb, &mdev->busy_urbs[channel]); + + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) { + dev_err(dev, "URB submit failed with error %d.\n", retval); + goto _error_1; + } + return 0; + +_error_1: + usb_unanchor_urb(urb); +_error: + usb_free_urb(urb); + return retval; +} + +/** + * hdm_configure_channel - receive channel configuration from core + * @iface: interface + * @channel: channel ID + * @conf: structure that holds the configuration information + * + * The attached network interface controller (NIC) supports a padding mode + * to avoid short packets on USB, hence increasing the performance due to a + * lower interrupt load. This mode is default for synchronous data and can + * be switched on for isochronous data. In case padding is active the + * driver needs to know the frame size of the payload in order to calculate + * the number of bytes it needs to pad when transmitting or to cut off when + * receiving data. + * + */ +static int hdm_configure_channel(struct most_interface *iface, int channel, + struct most_channel_config *conf) +{ + unsigned int num_frames; + unsigned int frame_size; + struct most_dev *mdev = to_mdev(iface); + struct device *dev = &mdev->usb_device->dev; + + mdev->is_channel_healthy[channel] = true; + mdev->clear_work[channel].channel = channel; + mdev->clear_work[channel].mdev = mdev; + INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt); + + if (unlikely(!iface || !conf)) { + dev_err(dev, "Bad interface or config pointer.\n"); + return -EINVAL; + } + if (unlikely(channel < 0 || channel >= iface->num_channels)) { + dev_err(dev, "Channel ID out of range.\n"); + return -EINVAL; + } + if (!conf->num_buffers || !conf->buffer_size) { + dev_err(dev, "Misconfig: buffer size or #buffers zero.\n"); + return -EINVAL; + } + + if (conf->data_type != MOST_CH_SYNC && + !(conf->data_type == MOST_CH_ISOC && + conf->packets_per_xact != 0xFF)) { + mdev->padding_active[channel] = false; + /* + * Since the NIC's padding mode is not going to be + * used, we can skip the frame size calculations and + * move directly on to exit. + */ + goto exit; + } + + mdev->padding_active[channel] = true; + + frame_size = get_stream_frame_size(conf); + if (frame_size == 0 || frame_size > USB_MTU) { + dev_warn(dev, "Misconfig: frame size wrong\n"); + return -EINVAL; + } + + num_frames = conf->buffer_size / frame_size; + + if (conf->buffer_size % frame_size) { + u16 old_size = conf->buffer_size; + + conf->buffer_size = num_frames * frame_size; + dev_warn(dev, "%s: fixed buffer size (%d -> %d)\n", + mdev->suffix[channel], old_size, conf->buffer_size); + } + + /* calculate extra length to comply w/ HW padding */ + conf->extra_len = num_frames * (USB_MTU - frame_size); + +exit: + mdev->conf[channel] = *conf; + if (conf->data_type == MOST_CH_ASYNC) { + u16 ep = mdev->ep_address[channel]; + + if (start_sync_ep(mdev->usb_device, ep) < 0) + dev_warn(dev, "sync for ep%02x failed", ep); + } + return 0; +} + +/** + * hdm_request_netinfo - request network information + * @iface: pointer to interface + * @channel: channel ID + * + * This is used as trigger to set up the link status timer that + * polls for the NI state of the INIC every 2 seconds. + * + */ +static void hdm_request_netinfo(struct most_interface *iface, int channel, + void (*on_netinfo)(struct most_interface *, + unsigned char, + unsigned char *)) +{ + struct most_dev *mdev; + + BUG_ON(!iface); + mdev = to_mdev(iface); + mdev->on_netinfo = on_netinfo; + if (!on_netinfo) + return; + + mdev->link_stat_timer.expires = jiffies + HZ; + mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires); +} + +/** + * link_stat_timer_handler - schedule work obtaining mac address and link status + * @data: pointer to USB device instance + * + * The handler runs in interrupt context. That's why we need to defer the + * tasks to a work queue. + */ +static void link_stat_timer_handler(struct timer_list *t) +{ + struct most_dev *mdev = from_timer(mdev, t, link_stat_timer); + + schedule_work(&mdev->poll_work_obj); + mdev->link_stat_timer.expires = jiffies + (2 * HZ); + add_timer(&mdev->link_stat_timer); +} + +/** + * wq_netinfo - work queue function to deliver latest networking information + * @wq_obj: object that holds data for our deferred work to do + * + * This retrieves the network interface status of the USB INIC + */ +static void wq_netinfo(struct work_struct *wq_obj) +{ + struct most_dev *mdev = to_mdev_from_work(wq_obj); + struct usb_device *usb_device = mdev->usb_device; + struct device *dev = &usb_device->dev; + u16 hi, mi, lo, link; + u8 hw_addr[6]; + + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) { + dev_err(dev, "Vendor request 'hw_addr_hi' failed\n"); + return; + } + + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) { + dev_err(dev, "Vendor request 'hw_addr_mid' failed\n"); + return; + } + + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) { + dev_err(dev, "Vendor request 'hw_addr_low' failed\n"); + return; + } + + if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) { + dev_err(dev, "Vendor request 'link status' failed\n"); + return; + } + + hw_addr[0] = hi >> 8; + hw_addr[1] = hi; + hw_addr[2] = mi >> 8; + hw_addr[3] = mi; + hw_addr[4] = lo >> 8; + hw_addr[5] = lo; + + if (mdev->on_netinfo) + mdev->on_netinfo(&mdev->iface, link, hw_addr); +} + +/** + * wq_clear_halt - work queue function + * @wq_obj: work_struct object to execute + * + * This sends a clear_halt to the given USB pipe. + */ +static void wq_clear_halt(struct work_struct *wq_obj) +{ + struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj); + struct most_dev *mdev = clear_work->mdev; + unsigned int channel = clear_work->channel; + int pipe = clear_work->pipe; + + mutex_lock(&mdev->io_mutex); + most_stop_enqueue(&mdev->iface, channel); + usb_kill_anchored_urbs(&mdev->busy_urbs[channel]); + if (usb_clear_halt(mdev->usb_device, pipe)) + dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); + + mdev->is_channel_healthy[channel] = true; + most_resume_enqueue(&mdev->iface, channel); + mutex_unlock(&mdev->io_mutex); +} + +/** + * hdm_usb_fops - file operation table for USB driver + */ +static const struct file_operations hdm_usb_fops = { + .owner = THIS_MODULE, +}; + +/** + * usb_device_id - ID table for HCD device probing + */ +static const struct usb_device_id usbid[] = { + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), }, + { } /* Terminating entry */ +}; + +#define MOST_DCI_RO_ATTR(_name) \ + struct most_dci_attribute most_dci_attr_##_name = \ + __ATTR(_name, 0444, show_value, NULL) + +#define MOST_DCI_ATTR(_name) \ + struct most_dci_attribute most_dci_attr_##_name = \ + __ATTR(_name, 0644, show_value, store_value) + +#define MOST_DCI_WO_ATTR(_name) \ + struct most_dci_attribute most_dci_attr_##_name = \ + __ATTR(_name, 0200, NULL, store_value) + +/** + * struct most_dci_attribute - to access the attributes of a dci object + * @attr: attributes of a dci object + * @show: pointer to the show function + * @store: pointer to the store function + */ +struct most_dci_attribute { + struct attribute attr; + ssize_t (*show)(struct most_dci_obj *d, + struct most_dci_attribute *attr, + char *buf); + ssize_t (*store)(struct most_dci_obj *d, + struct most_dci_attribute *attr, + const char *buf, + size_t count); +}; + +#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr) + +/** + * dci_attr_show - show function for dci object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + */ +static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct most_dci_attribute *dci_attr = to_dci_attr(attr); + struct most_dci_obj *dci_obj = to_dci_obj(kobj); + + if (!dci_attr->show) + return -EIO; + + return dci_attr->show(dci_obj, dci_attr, buf); +} + +/** + * dci_attr_store - store function for dci object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + * @len: length of buffer + */ +static ssize_t dci_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, + size_t len) +{ + struct most_dci_attribute *dci_attr = to_dci_attr(attr); + struct most_dci_obj *dci_obj = to_dci_obj(kobj); + + if (!dci_attr->store) + return -EIO; + + return dci_attr->store(dci_obj, dci_attr, buf, len); +} + +static const struct sysfs_ops most_dci_sysfs_ops = { + .show = dci_attr_show, + .store = dci_attr_store, +}; + +/** + * most_dci_release - release function for dci object + * @kobj: pointer to kobject + * + * This frees the memory allocated for the dci object + */ +static void most_dci_release(struct kobject *kobj) +{ + struct most_dci_obj *dci_obj = to_dci_obj(kobj); + + kfree(dci_obj); +} + +struct regs { + const char *name; + u16 reg; +}; + +static const struct regs ro_regs[] = { + { "ni_state", DRCI_REG_NI_STATE }, + { "packet_bandwidth", DRCI_REG_PACKET_BW }, + { "node_address", DRCI_REG_NODE_ADDR }, + { "node_position", DRCI_REG_NODE_POS }, +}; + +static const struct regs rw_regs[] = { + { "mep_filter", DRCI_REG_MEP_FILTER }, + { "mep_hash0", DRCI_REG_HASH_TBL0 }, + { "mep_hash1", DRCI_REG_HASH_TBL1 }, + { "mep_hash2", DRCI_REG_HASH_TBL2 }, + { "mep_hash3", DRCI_REG_HASH_TBL3 }, + { "mep_eui48_hi", DRCI_REG_HW_ADDR_HI }, + { "mep_eui48_mi", DRCI_REG_HW_ADDR_MI }, + { "mep_eui48_lo", DRCI_REG_HW_ADDR_LO }, +}; + +static int get_stat_reg_addr(const struct regs *regs, int size, + const char *name, u16 *reg_addr) +{ + int i; + + for (i = 0; i < size; i++) { + if (!strcmp(name, regs[i].name)) { + *reg_addr = regs[i].reg; + return 0; + } + } + return -EFAULT; +} + +#define get_static_reg_addr(regs, name, reg_addr) \ + get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr) + +static ssize_t show_value(struct most_dci_obj *dci_obj, + struct most_dci_attribute *attr, char *buf) +{ + const char *name = attr->attr.name; + u16 val; + u16 reg_addr; + int err; + + if (!strcmp(name, "arb_address")) + return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr); + + if (!strcmp(name, "arb_value")) + reg_addr = dci_obj->reg_addr; + else if (get_static_reg_addr(ro_regs, name, ®_addr) && + get_static_reg_addr(rw_regs, name, ®_addr)) + return -EFAULT; + + err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val); + if (err < 0) + return err; + + return snprintf(buf, PAGE_SIZE, "%04x\n", val); +} + +static ssize_t store_value(struct most_dci_obj *dci_obj, + struct most_dci_attribute *attr, + const char *buf, size_t count) +{ + u16 val; + u16 reg_addr; + const char *name = attr->attr.name; + struct usb_device *usb_dev = dci_obj->usb_device; + int err = kstrtou16(buf, 16, &val); + + if (err) + return err; + + if (!strcmp(name, "arb_address")) { + dci_obj->reg_addr = val; + return count; + } + + if (!strcmp(name, "arb_value")) + err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val); + else if (!strcmp(name, "sync_ep")) + err = start_sync_ep(usb_dev, val); + else if (!get_static_reg_addr(rw_regs, name, ®_addr)) + err = drci_wr_reg(usb_dev, reg_addr, val); + else + return -EFAULT; + + if (err < 0) + return err; + + return count; +} + +static MOST_DCI_RO_ATTR(ni_state); +static MOST_DCI_RO_ATTR(packet_bandwidth); +static MOST_DCI_RO_ATTR(node_address); +static MOST_DCI_RO_ATTR(node_position); +static MOST_DCI_WO_ATTR(sync_ep); +static MOST_DCI_ATTR(mep_filter); +static MOST_DCI_ATTR(mep_hash0); +static MOST_DCI_ATTR(mep_hash1); +static MOST_DCI_ATTR(mep_hash2); +static MOST_DCI_ATTR(mep_hash3); +static MOST_DCI_ATTR(mep_eui48_hi); +static MOST_DCI_ATTR(mep_eui48_mi); +static MOST_DCI_ATTR(mep_eui48_lo); +static MOST_DCI_ATTR(arb_address); +static MOST_DCI_ATTR(arb_value); + +/** + * most_dci_def_attrs - array of default attribute files of the dci object + */ +static struct attribute *most_dci_def_attrs[] = { + &most_dci_attr_ni_state.attr, + &most_dci_attr_packet_bandwidth.attr, + &most_dci_attr_node_address.attr, + &most_dci_attr_node_position.attr, + &most_dci_attr_sync_ep.attr, + &most_dci_attr_mep_filter.attr, + &most_dci_attr_mep_hash0.attr, + &most_dci_attr_mep_hash1.attr, + &most_dci_attr_mep_hash2.attr, + &most_dci_attr_mep_hash3.attr, + &most_dci_attr_mep_eui48_hi.attr, + &most_dci_attr_mep_eui48_mi.attr, + &most_dci_attr_mep_eui48_lo.attr, + &most_dci_attr_arb_address.attr, + &most_dci_attr_arb_value.attr, + NULL, +}; + +/** + * DCI ktype + */ +static struct kobj_type most_dci_ktype = { + .sysfs_ops = &most_dci_sysfs_ops, + .release = most_dci_release, + .default_attrs = most_dci_def_attrs, +}; + +/** + * create_most_dci_obj - allocates a dci object + * @parent: parent kobject + * + * This creates a dci object and registers it with sysfs. + * Returns a pointer to the object or NULL when something went wrong. + */ +static struct +most_dci_obj *create_most_dci_obj(struct kobject *parent) +{ + struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); + int retval; + + if (!most_dci) + return NULL; + + retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent, + "dci"); + if (retval) { + kobject_put(&most_dci->kobj); + return NULL; + } + return most_dci; +} + +/** + * destroy_most_dci_obj - DCI object release function + * @p: pointer to dci object + */ +static void destroy_most_dci_obj(struct most_dci_obj *p) +{ + kobject_put(&p->kobj); +} + +/** + * hdm_probe - probe function of USB device driver + * @interface: Interface of the attached USB device + * @id: Pointer to the USB ID table. + * + * This allocates and initializes the device instance, adds the new + * entry to the internal list, scans the USB descriptors and registers + * the interface with the core. + * Additionally, the DCI objects are created and the hardware is sync'd. + * + * Return 0 on success. In case of an error a negative number is returned. + */ +static int +hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_host_interface *usb_iface_desc = interface->cur_altsetting; + struct usb_device *usb_dev = interface_to_usbdev(interface); + struct device *dev = &usb_dev->dev; + struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + unsigned int i; + unsigned int num_endpoints; + struct most_channel_capability *tmp_cap; + struct usb_endpoint_descriptor *ep_desc; + int ret = 0; + + if (!mdev) + goto exit_ENOMEM; + + usb_set_intfdata(interface, mdev); + num_endpoints = usb_iface_desc->desc.bNumEndpoints; + mutex_init(&mdev->io_mutex); + INIT_WORK(&mdev->poll_work_obj, wq_netinfo); + timer_setup(&mdev->link_stat_timer, link_stat_timer_handler, 0); + + mdev->usb_device = usb_dev; + mdev->link_stat_timer.expires = jiffies + (2 * HZ); + + mdev->iface.mod = hdm_usb_fops.owner; + mdev->iface.interface = ITYPE_USB; + mdev->iface.configure = hdm_configure_channel; + mdev->iface.request_netinfo = hdm_request_netinfo; + mdev->iface.enqueue = hdm_enqueue; + mdev->iface.poison_channel = hdm_poison_channel; + mdev->iface.description = mdev->description; + mdev->iface.num_channels = num_endpoints; + + snprintf(mdev->description, sizeof(mdev->description), + "usb_device %d-%s:%d.%d", + usb_dev->bus->busnum, + usb_dev->devpath, + usb_dev->config->desc.bConfigurationValue, + usb_iface_desc->desc.bInterfaceNumber); + + mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL); + if (!mdev->conf) + goto exit_free; + + mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL); + if (!mdev->cap) + goto exit_free1; + + mdev->iface.channel_vector = mdev->cap; + mdev->iface.priv = NULL; + + mdev->ep_address = + kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL); + if (!mdev->ep_address) + goto exit_free2; + + mdev->busy_urbs = + kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL); + if (!mdev->busy_urbs) + goto exit_free3; + + tmp_cap = mdev->cap; + for (i = 0; i < num_endpoints; i++) { + ep_desc = &usb_iface_desc->endpoint[i].desc; + mdev->ep_address[i] = ep_desc->bEndpointAddress; + mdev->padding_active[i] = false; + mdev->is_channel_healthy[i] = true; + + snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x", + mdev->ep_address[i]); + + tmp_cap->name_suffix = &mdev->suffix[i][0]; + tmp_cap->buffer_size_packet = MAX_BUF_SIZE; + tmp_cap->buffer_size_streaming = MAX_BUF_SIZE; + tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE; + tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE; + tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | + MOST_CH_ISOC | MOST_CH_SYNC; + if (usb_endpoint_dir_in(ep_desc)) + tmp_cap->direction = MOST_CH_RX; + else + tmp_cap->direction = MOST_CH_TX; + tmp_cap++; + init_usb_anchor(&mdev->busy_urbs[i]); + spin_lock_init(&mdev->channel_lock[i]); + } + dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n", + le16_to_cpu(usb_dev->descriptor.idVendor), + le16_to_cpu(usb_dev->descriptor.idProduct), + usb_dev->bus->busnum, + usb_dev->devnum); + + dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n", + usb_dev->bus->busnum, + usb_dev->devpath, + usb_dev->config->desc.bConfigurationValue, + usb_iface_desc->desc.bInterfaceNumber); + + mdev->parent = most_register_interface(&mdev->iface); + if (IS_ERR(mdev->parent)) { + ret = PTR_ERR(mdev->parent); + goto exit_free4; + } + + mutex_lock(&mdev->io_mutex); + if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || + le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 || + le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) { + /* this increments the reference count of the instance + * object of the core + */ + mdev->dci = create_most_dci_obj(mdev->parent); + if (!mdev->dci) { + mutex_unlock(&mdev->io_mutex); + most_deregister_interface(&mdev->iface); + ret = -ENOMEM; + goto exit_free4; + } + + kobject_uevent(&mdev->dci->kobj, KOBJ_ADD); + mdev->dci->usb_device = mdev->usb_device; + } + mutex_unlock(&mdev->io_mutex); + return 0; + +exit_free4: + kfree(mdev->busy_urbs); +exit_free3: + kfree(mdev->ep_address); +exit_free2: + kfree(mdev->cap); +exit_free1: + kfree(mdev->conf); +exit_free: + kfree(mdev); +exit_ENOMEM: + if (ret == 0 || ret == -ENOMEM) { + ret = -ENOMEM; + dev_err(dev, "out of memory\n"); + } + return ret; +} + +/** + * hdm_disconnect - disconnect function of USB device driver + * @interface: Interface of the attached USB device + * + * This deregisters the interface with the core, removes the kernel timer + * and frees resources. + * + * Context: hub kernel thread + */ +static void hdm_disconnect(struct usb_interface *interface) +{ + struct most_dev *mdev = usb_get_intfdata(interface); + + mutex_lock(&mdev->io_mutex); + usb_set_intfdata(interface, NULL); + mdev->usb_device = NULL; + mutex_unlock(&mdev->io_mutex); + + del_timer_sync(&mdev->link_stat_timer); + cancel_work_sync(&mdev->poll_work_obj); + + destroy_most_dci_obj(mdev->dci); + most_deregister_interface(&mdev->iface); + + kfree(mdev->busy_urbs); + kfree(mdev->cap); + kfree(mdev->conf); + kfree(mdev->ep_address); + kfree(mdev); +} + +static struct usb_driver hdm_usb = { + .name = "hdm_usb", + .id_table = usbid, + .probe = hdm_probe, + .disconnect = hdm_disconnect, +}; + +module_usb_driver(hdm_usb); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Gromm "); +MODULE_DESCRIPTION("HDM_4_USB"); -- cgit v1.2.3 From 2c22cdfb4e817a7be48419c3c7b1423ee8f5df38 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:42 +0100 Subject: staging: most: video: rename module This patch renames the folder of the video module. It is needed to clean up the directory layout of the driver. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Kconfig | 2 +- drivers/staging/most/aim-v4l2/Kconfig | 12 - drivers/staging/most/aim-v4l2/video.c | 610 ---------------------------------- drivers/staging/most/video/Kconfig | 12 + drivers/staging/most/video/Makefile | 4 + drivers/staging/most/video/video.c | 610 ++++++++++++++++++++++++++++++++++ 6 files changed, 627 insertions(+), 623 deletions(-) delete mode 100644 drivers/staging/most/aim-v4l2/Kconfig delete mode 100644 drivers/staging/most/aim-v4l2/video.c create mode 100644 drivers/staging/most/video/Kconfig create mode 100644 drivers/staging/most/video/Makefile create mode 100644 drivers/staging/most/video/video.c (limited to 'drivers') diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 86d4f12596bb..20047abbe560 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -23,7 +23,7 @@ source "drivers/staging/most/net/Kconfig" source "drivers/staging/most/sound/Kconfig" -source "drivers/staging/most/aim-v4l2/Kconfig" +source "drivers/staging/most/video/Kconfig" source "drivers/staging/most/dim2/Kconfig" diff --git a/drivers/staging/most/aim-v4l2/Kconfig b/drivers/staging/most/aim-v4l2/Kconfig deleted file mode 100644 index d70eaaf0936c..000000000000 --- a/drivers/staging/most/aim-v4l2/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# -# MOST V4L2 configuration -# - -config AIM_V4L2 - tristate "V4L2 AIM" - depends on VIDEO_V4L2 - ---help--- - Say Y here if you want to commumicate via Video 4 Linux. - - To compile this driver as a module, choose M here: the - module will be called aim_v4l2. \ No newline at end of file diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c deleted file mode 100644 index 3c813ed7f3ec..000000000000 --- a/drivers/staging/most/aim-v4l2/video.c +++ /dev/null @@ -1,610 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * V4L2 AIM - V4L2 Application Interface Module for MostCore - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "most/core.h" - -#define V4L2_AIM_MAX_INPUT 1 - -static struct most_aim aim_info; - -struct most_video_dev { - struct most_interface *iface; - int ch_idx; - struct list_head list; - bool mute; - - struct list_head pending_mbos; - spinlock_t list_lock; - - struct v4l2_device v4l2_dev; - atomic_t access_ref; - struct video_device *vdev; - unsigned int ctrl_input; - - struct mutex lock; - - wait_queue_head_t wait_data; -}; - -struct aim_fh { - /* must be the first field of this struct! */ - struct v4l2_fh fh; - struct most_video_dev *mdev; - u32 offs; -}; - -static struct list_head video_devices = LIST_HEAD_INIT(video_devices); -static struct spinlock list_lock; - -static inline bool data_ready(struct most_video_dev *mdev) -{ - return !list_empty(&mdev->pending_mbos); -} - -static inline struct mbo *get_top_mbo(struct most_video_dev *mdev) -{ - return list_first_entry(&mdev->pending_mbos, struct mbo, list); -} - -static int aim_vdev_open(struct file *filp) -{ - int ret; - struct video_device *vdev = video_devdata(filp); - struct most_video_dev *mdev = video_drvdata(filp); - struct aim_fh *fh; - - v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n"); - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - break; - default: - return -EINVAL; - } - - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (!fh) - return -ENOMEM; - - if (!atomic_inc_and_test(&mdev->access_ref)) { - v4l2_err(&mdev->v4l2_dev, "too many clients\n"); - ret = -EBUSY; - goto err_dec; - } - - fh->mdev = mdev; - v4l2_fh_init(&fh->fh, vdev); - filp->private_data = fh; - - v4l2_fh_add(&fh->fh); - - ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info); - if (ret) { - v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n"); - goto err_rm; - } - - return 0; - -err_rm: - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - -err_dec: - atomic_dec(&mdev->access_ref); - kfree(fh); - return ret; -} - -static int aim_vdev_close(struct file *filp) -{ - struct aim_fh *fh = filp->private_data; - struct most_video_dev *mdev = fh->mdev; - struct mbo *mbo, *tmp; - - v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n"); - - /* - * We need to put MBOs back before we call most_stop_channel() - * to deallocate MBOs. - * From the other hand mostcore still calling rx_completion() - * to deliver MBOs until most_stop_channel() is called. - * Use mute to work around this issue. - * This must be implemented in core. - */ - - spin_lock_irq(&mdev->list_lock); - mdev->mute = true; - list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) { - list_del(&mbo->list); - spin_unlock_irq(&mdev->list_lock); - most_put_mbo(mbo); - spin_lock_irq(&mdev->list_lock); - } - spin_unlock_irq(&mdev->list_lock); - most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info); - mdev->mute = false; - - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - - atomic_dec(&mdev->access_ref); - kfree(fh); - return 0; -} - -static ssize_t aim_vdev_read(struct file *filp, char __user *buf, - size_t count, loff_t *pos) -{ - struct aim_fh *fh = filp->private_data; - struct most_video_dev *mdev = fh->mdev; - int ret = 0; - - if (*pos) - return -ESPIPE; - - if (!mdev) - return -ENODEV; - - /* wait for the first buffer */ - if (!(filp->f_flags & O_NONBLOCK)) { - if (wait_event_interruptible(mdev->wait_data, data_ready(mdev))) - return -ERESTARTSYS; - } - - if (!data_ready(mdev)) - return -EAGAIN; - - while (count > 0 && data_ready(mdev)) { - struct mbo *const mbo = get_top_mbo(mdev); - int const rem = mbo->processed_length - fh->offs; - int const cnt = rem < count ? rem : count; - - if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) { - v4l2_err(&mdev->v4l2_dev, "read: copy_to_user failed\n"); - if (!ret) - ret = -EFAULT; - return ret; - } - - fh->offs += cnt; - count -= cnt; - buf += cnt; - ret += cnt; - - if (cnt >= rem) { - fh->offs = 0; - spin_lock_irq(&mdev->list_lock); - list_del(&mbo->list); - spin_unlock_irq(&mdev->list_lock); - most_put_mbo(mbo); - } - } - return ret; -} - -static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait) -{ - struct aim_fh *fh = filp->private_data; - struct most_video_dev *mdev = fh->mdev; - unsigned int mask = 0; - - /* only wait if no data is available */ - if (!data_ready(mdev)) - poll_wait(filp, &mdev->wait_data, wait); - if (data_ready(mdev)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} - -static void aim_set_format_struct(struct v4l2_format *f) -{ - f->fmt.pix.width = 8; - f->fmt.pix.height = 8; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = 188 * 2; - f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.priv = 0; -} - -static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, - struct v4l2_format *format) -{ - if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG) - return -EINVAL; - - if (cmd == VIDIOC_TRY_FMT) - return 0; - - aim_set_format_struct(format); - - return 0; -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - - v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n"); - - strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver)); - strlcpy(cap->card, "MOST", sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), - "%s", mdev->iface->description); - - cap->capabilities = - V4L2_CAP_READWRITE | - V4L2_CAP_TUNER | - V4L2_CAP_VIDEO_CAPTURE; - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - - v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index); - - if (f->index) - return -EINVAL; - - strcpy(f->description, "MPEG"); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - f->pixelformat = V4L2_PIX_FMT_MPEG; - - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - - v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n"); - - aim_set_format_struct(f); - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - - return aim_set_format(mdev, VIDIOC_TRY_FMT, f); -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - - return aim_set_format(mdev, VIDIOC_S_FMT, f); -} - -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - - v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n"); - - *norm = V4L2_STD_UNKNOWN; - return 0; -} - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *input) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - - if (input->index >= V4L2_AIM_MAX_INPUT) - return -EINVAL; - - strcpy(input->name, "MOST Video"); - input->type |= V4L2_INPUT_TYPE_CAMERA; - input->audioset = 0; - - input->std = mdev->vdev->tvnorms; - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - *i = mdev->ctrl_input; - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int index) -{ - struct aim_fh *fh = priv; - struct most_video_dev *mdev = fh->mdev; - - v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index); - - if (index >= V4L2_AIM_MAX_INPUT) - return -EINVAL; - mdev->ctrl_input = index; - return 0; -} - -static const struct v4l2_file_operations aim_fops = { - .owner = THIS_MODULE, - .open = aim_vdev_open, - .release = aim_vdev_close, - .read = aim_vdev_read, - .poll = aim_vdev_poll, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_std = vidioc_g_std, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, -}; - -static const struct video_device aim_videodev_template = { - .fops = &aim_fops, - .release = video_device_release, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = V4L2_STD_UNKNOWN, -}; - -/**************************************************************************/ - -static struct most_video_dev *get_aim_dev( - struct most_interface *iface, int channel_idx) -{ - struct most_video_dev *mdev; - unsigned long flags; - - spin_lock_irqsave(&list_lock, flags); - list_for_each_entry(mdev, &video_devices, list) { - if (mdev->iface == iface && mdev->ch_idx == channel_idx) { - spin_unlock_irqrestore(&list_lock, flags); - return mdev; - } - } - spin_unlock_irqrestore(&list_lock, flags); - return NULL; -} - -static int aim_rx_data(struct mbo *mbo) -{ - unsigned long flags; - struct most_video_dev *mdev = - get_aim_dev(mbo->ifp, mbo->hdm_channel_id); - - if (!mdev) - return -EIO; - - spin_lock_irqsave(&mdev->list_lock, flags); - if (unlikely(mdev->mute)) { - spin_unlock_irqrestore(&mdev->list_lock, flags); - return -EIO; - } - - list_add_tail(&mbo->list, &mdev->pending_mbos); - spin_unlock_irqrestore(&mdev->list_lock, flags); - wake_up_interruptible(&mdev->wait_data); - return 0; -} - -static int aim_register_videodev(struct most_video_dev *mdev) -{ - int ret; - - v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n"); - - init_waitqueue_head(&mdev->wait_data); - - /* allocate and fill v4l2 video struct */ - mdev->vdev = video_device_alloc(); - if (!mdev->vdev) - return -ENOMEM; - - /* Fill the video capture device struct */ - *mdev->vdev = aim_videodev_template; - mdev->vdev->v4l2_dev = &mdev->v4l2_dev; - mdev->vdev->lock = &mdev->lock; - snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s", - mdev->v4l2_dev.name); - - /* Register the v4l2 device */ - video_set_drvdata(mdev->vdev, mdev); - ret = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1); - if (ret) { - v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n", - ret); - video_device_release(mdev->vdev); - } - - return ret; -} - -static void aim_unregister_videodev(struct most_video_dev *mdev) -{ - v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n"); - - video_unregister_device(mdev->vdev); -} - -static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) -{ - struct most_video_dev *mdev = - container_of(v4l2_dev, struct most_video_dev, v4l2_dev); - - v4l2_device_unregister(v4l2_dev); - kfree(mdev); -} - -static int aim_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, - struct kobject *parent, char *name) -{ - int ret; - struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); - - pr_info("aim_probe_channel(%s)\n", name); - - if (mdev) { - pr_err("channel already linked\n"); - return -EEXIST; - } - - if (ccfg->direction != MOST_CH_RX) { - pr_err("wrong direction, expect rx\n"); - return -EINVAL; - } - - if (ccfg->data_type != MOST_CH_SYNC && - ccfg->data_type != MOST_CH_ISOC) { - pr_err("wrong channel type, expect sync or isoc\n"); - return -EINVAL; - } - - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return -ENOMEM; - - mutex_init(&mdev->lock); - atomic_set(&mdev->access_ref, -1); - spin_lock_init(&mdev->list_lock); - INIT_LIST_HEAD(&mdev->pending_mbos); - mdev->iface = iface; - mdev->ch_idx = channel_idx; - mdev->v4l2_dev.release = aim_v4l2_dev_release; - - /* Create the v4l2_device */ - strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name)); - ret = v4l2_device_register(NULL, &mdev->v4l2_dev); - if (ret) { - pr_err("v4l2_device_register() failed\n"); - kfree(mdev); - return ret; - } - - ret = aim_register_videodev(mdev); - if (ret) - goto err_unreg; - - spin_lock_irq(&list_lock); - list_add(&mdev->list, &video_devices); - spin_unlock_irq(&list_lock); - v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n"); - return 0; - -err_unreg: - v4l2_device_disconnect(&mdev->v4l2_dev); - v4l2_device_put(&mdev->v4l2_dev); - return ret; -} - -static int aim_disconnect_channel(struct most_interface *iface, - int channel_idx) -{ - struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); - - if (!mdev) { - pr_err("no such channel is linked\n"); - return -ENOENT; - } - - v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n"); - - spin_lock_irq(&list_lock); - list_del(&mdev->list); - spin_unlock_irq(&list_lock); - - aim_unregister_videodev(mdev); - v4l2_device_disconnect(&mdev->v4l2_dev); - v4l2_device_put(&mdev->v4l2_dev); - return 0; -} - -static struct most_aim aim_info = { - .name = "v4l", - .probe_channel = aim_probe_channel, - .disconnect_channel = aim_disconnect_channel, - .rx_completion = aim_rx_data, -}; - -static int __init aim_init(void) -{ - spin_lock_init(&list_lock); - return most_register_aim(&aim_info); -} - -static void __exit aim_exit(void) -{ - struct most_video_dev *mdev, *tmp; - - /* - * As the mostcore currently doesn't call disconnect_channel() - * for linked channels while we call most_deregister_aim() - * we simulate this call here. - * This must be fixed in core. - */ - spin_lock_irq(&list_lock); - list_for_each_entry_safe(mdev, tmp, &video_devices, list) { - list_del(&mdev->list); - spin_unlock_irq(&list_lock); - - aim_unregister_videodev(mdev); - v4l2_device_disconnect(&mdev->v4l2_dev); - v4l2_device_put(&mdev->v4l2_dev); - spin_lock_irq(&list_lock); - } - spin_unlock_irq(&list_lock); - - most_deregister_aim(&aim_info); - BUG_ON(!list_empty(&video_devices)); -} - -module_init(aim_init); -module_exit(aim_exit); - -MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore"); -MODULE_AUTHOR("Andrey Shvetsov "); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/most/video/Kconfig b/drivers/staging/most/video/Kconfig new file mode 100644 index 000000000000..ce6af4f951a6 --- /dev/null +++ b/drivers/staging/most/video/Kconfig @@ -0,0 +1,12 @@ +# +# MOST V4L2 configuration +# + +config MOST_VIDEO + tristate "Video" + depends on VIDEO_V4L2 + ---help--- + Say Y here if you want to commumicate via Video 4 Linux. + + To compile this driver as a module, choose M here: the + module will be called most_video. diff --git a/drivers/staging/most/video/Makefile b/drivers/staging/most/video/Makefile new file mode 100644 index 000000000000..1c8e520e02a2 --- /dev/null +++ b/drivers/staging/most/video/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_MOST_VIDEO) += most_video.o + +most_video-objs := video.o +ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c new file mode 100644 index 000000000000..3c813ed7f3ec --- /dev/null +++ b/drivers/staging/most/video/video.c @@ -0,0 +1,610 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * V4L2 AIM - V4L2 Application Interface Module for MostCore + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "most/core.h" + +#define V4L2_AIM_MAX_INPUT 1 + +static struct most_aim aim_info; + +struct most_video_dev { + struct most_interface *iface; + int ch_idx; + struct list_head list; + bool mute; + + struct list_head pending_mbos; + spinlock_t list_lock; + + struct v4l2_device v4l2_dev; + atomic_t access_ref; + struct video_device *vdev; + unsigned int ctrl_input; + + struct mutex lock; + + wait_queue_head_t wait_data; +}; + +struct aim_fh { + /* must be the first field of this struct! */ + struct v4l2_fh fh; + struct most_video_dev *mdev; + u32 offs; +}; + +static struct list_head video_devices = LIST_HEAD_INIT(video_devices); +static struct spinlock list_lock; + +static inline bool data_ready(struct most_video_dev *mdev) +{ + return !list_empty(&mdev->pending_mbos); +} + +static inline struct mbo *get_top_mbo(struct most_video_dev *mdev) +{ + return list_first_entry(&mdev->pending_mbos, struct mbo, list); +} + +static int aim_vdev_open(struct file *filp) +{ + int ret; + struct video_device *vdev = video_devdata(filp); + struct most_video_dev *mdev = video_drvdata(filp); + struct aim_fh *fh; + + v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n"); + + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: + break; + default: + return -EINVAL; + } + + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (!fh) + return -ENOMEM; + + if (!atomic_inc_and_test(&mdev->access_ref)) { + v4l2_err(&mdev->v4l2_dev, "too many clients\n"); + ret = -EBUSY; + goto err_dec; + } + + fh->mdev = mdev; + v4l2_fh_init(&fh->fh, vdev); + filp->private_data = fh; + + v4l2_fh_add(&fh->fh); + + ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info); + if (ret) { + v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n"); + goto err_rm; + } + + return 0; + +err_rm: + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); + +err_dec: + atomic_dec(&mdev->access_ref); + kfree(fh); + return ret; +} + +static int aim_vdev_close(struct file *filp) +{ + struct aim_fh *fh = filp->private_data; + struct most_video_dev *mdev = fh->mdev; + struct mbo *mbo, *tmp; + + v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n"); + + /* + * We need to put MBOs back before we call most_stop_channel() + * to deallocate MBOs. + * From the other hand mostcore still calling rx_completion() + * to deliver MBOs until most_stop_channel() is called. + * Use mute to work around this issue. + * This must be implemented in core. + */ + + spin_lock_irq(&mdev->list_lock); + mdev->mute = true; + list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) { + list_del(&mbo->list); + spin_unlock_irq(&mdev->list_lock); + most_put_mbo(mbo); + spin_lock_irq(&mdev->list_lock); + } + spin_unlock_irq(&mdev->list_lock); + most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info); + mdev->mute = false; + + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); + + atomic_dec(&mdev->access_ref); + kfree(fh); + return 0; +} + +static ssize_t aim_vdev_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos) +{ + struct aim_fh *fh = filp->private_data; + struct most_video_dev *mdev = fh->mdev; + int ret = 0; + + if (*pos) + return -ESPIPE; + + if (!mdev) + return -ENODEV; + + /* wait for the first buffer */ + if (!(filp->f_flags & O_NONBLOCK)) { + if (wait_event_interruptible(mdev->wait_data, data_ready(mdev))) + return -ERESTARTSYS; + } + + if (!data_ready(mdev)) + return -EAGAIN; + + while (count > 0 && data_ready(mdev)) { + struct mbo *const mbo = get_top_mbo(mdev); + int const rem = mbo->processed_length - fh->offs; + int const cnt = rem < count ? rem : count; + + if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) { + v4l2_err(&mdev->v4l2_dev, "read: copy_to_user failed\n"); + if (!ret) + ret = -EFAULT; + return ret; + } + + fh->offs += cnt; + count -= cnt; + buf += cnt; + ret += cnt; + + if (cnt >= rem) { + fh->offs = 0; + spin_lock_irq(&mdev->list_lock); + list_del(&mbo->list); + spin_unlock_irq(&mdev->list_lock); + most_put_mbo(mbo); + } + } + return ret; +} + +static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait) +{ + struct aim_fh *fh = filp->private_data; + struct most_video_dev *mdev = fh->mdev; + unsigned int mask = 0; + + /* only wait if no data is available */ + if (!data_ready(mdev)) + poll_wait(filp, &mdev->wait_data, wait); + if (data_ready(mdev)) + mask |= POLLIN | POLLRDNORM; + + return mask; +} + +static void aim_set_format_struct(struct v4l2_format *f) +{ + f->fmt.pix.width = 8; + f->fmt.pix.height = 8; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = 188 * 2; + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.priv = 0; +} + +static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, + struct v4l2_format *format) +{ + if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG) + return -EINVAL; + + if (cmd == VIDIOC_TRY_FMT) + return 0; + + aim_set_format_struct(format); + + return 0; +} + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n"); + + strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver)); + strlcpy(cap->card, "MOST", sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "%s", mdev->iface->description); + + cap->capabilities = + V4L2_CAP_READWRITE | + V4L2_CAP_TUNER | + V4L2_CAP_VIDEO_CAPTURE; + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index); + + if (f->index) + return -EINVAL; + + strcpy(f->description, "MPEG"); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + f->pixelformat = V4L2_PIX_FMT_MPEG; + + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n"); + + aim_set_format_struct(f); + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + return aim_set_format(mdev, VIDIOC_TRY_FMT, f); +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + return aim_set_format(mdev, VIDIOC_S_FMT, f); +} + +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n"); + + *norm = V4L2_STD_UNKNOWN; + return 0; +} + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *input) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + if (input->index >= V4L2_AIM_MAX_INPUT) + return -EINVAL; + + strcpy(input->name, "MOST Video"); + input->type |= V4L2_INPUT_TYPE_CAMERA; + input->audioset = 0; + + input->std = mdev->vdev->tvnorms; + + return 0; +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + *i = mdev->ctrl_input; + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int index) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index); + + if (index >= V4L2_AIM_MAX_INPUT) + return -EINVAL; + mdev->ctrl_input = index; + return 0; +} + +static const struct v4l2_file_operations aim_fops = { + .owner = THIS_MODULE, + .open = aim_vdev_open, + .release = aim_vdev_close, + .read = aim_vdev_read, + .poll = aim_vdev_poll, + .unlocked_ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_g_std = vidioc_g_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, +}; + +static const struct video_device aim_videodev_template = { + .fops = &aim_fops, + .release = video_device_release, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = V4L2_STD_UNKNOWN, +}; + +/**************************************************************************/ + +static struct most_video_dev *get_aim_dev( + struct most_interface *iface, int channel_idx) +{ + struct most_video_dev *mdev; + unsigned long flags; + + spin_lock_irqsave(&list_lock, flags); + list_for_each_entry(mdev, &video_devices, list) { + if (mdev->iface == iface && mdev->ch_idx == channel_idx) { + spin_unlock_irqrestore(&list_lock, flags); + return mdev; + } + } + spin_unlock_irqrestore(&list_lock, flags); + return NULL; +} + +static int aim_rx_data(struct mbo *mbo) +{ + unsigned long flags; + struct most_video_dev *mdev = + get_aim_dev(mbo->ifp, mbo->hdm_channel_id); + + if (!mdev) + return -EIO; + + spin_lock_irqsave(&mdev->list_lock, flags); + if (unlikely(mdev->mute)) { + spin_unlock_irqrestore(&mdev->list_lock, flags); + return -EIO; + } + + list_add_tail(&mbo->list, &mdev->pending_mbos); + spin_unlock_irqrestore(&mdev->list_lock, flags); + wake_up_interruptible(&mdev->wait_data); + return 0; +} + +static int aim_register_videodev(struct most_video_dev *mdev) +{ + int ret; + + v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n"); + + init_waitqueue_head(&mdev->wait_data); + + /* allocate and fill v4l2 video struct */ + mdev->vdev = video_device_alloc(); + if (!mdev->vdev) + return -ENOMEM; + + /* Fill the video capture device struct */ + *mdev->vdev = aim_videodev_template; + mdev->vdev->v4l2_dev = &mdev->v4l2_dev; + mdev->vdev->lock = &mdev->lock; + snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s", + mdev->v4l2_dev.name); + + /* Register the v4l2 device */ + video_set_drvdata(mdev->vdev, mdev); + ret = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1); + if (ret) { + v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n", + ret); + video_device_release(mdev->vdev); + } + + return ret; +} + +static void aim_unregister_videodev(struct most_video_dev *mdev) +{ + v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n"); + + video_unregister_device(mdev->vdev); +} + +static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) +{ + struct most_video_dev *mdev = + container_of(v4l2_dev, struct most_video_dev, v4l2_dev); + + v4l2_device_unregister(v4l2_dev); + kfree(mdev); +} + +static int aim_probe_channel(struct most_interface *iface, int channel_idx, + struct most_channel_config *ccfg, + struct kobject *parent, char *name) +{ + int ret; + struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); + + pr_info("aim_probe_channel(%s)\n", name); + + if (mdev) { + pr_err("channel already linked\n"); + return -EEXIST; + } + + if (ccfg->direction != MOST_CH_RX) { + pr_err("wrong direction, expect rx\n"); + return -EINVAL; + } + + if (ccfg->data_type != MOST_CH_SYNC && + ccfg->data_type != MOST_CH_ISOC) { + pr_err("wrong channel type, expect sync or isoc\n"); + return -EINVAL; + } + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + mutex_init(&mdev->lock); + atomic_set(&mdev->access_ref, -1); + spin_lock_init(&mdev->list_lock); + INIT_LIST_HEAD(&mdev->pending_mbos); + mdev->iface = iface; + mdev->ch_idx = channel_idx; + mdev->v4l2_dev.release = aim_v4l2_dev_release; + + /* Create the v4l2_device */ + strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name)); + ret = v4l2_device_register(NULL, &mdev->v4l2_dev); + if (ret) { + pr_err("v4l2_device_register() failed\n"); + kfree(mdev); + return ret; + } + + ret = aim_register_videodev(mdev); + if (ret) + goto err_unreg; + + spin_lock_irq(&list_lock); + list_add(&mdev->list, &video_devices); + spin_unlock_irq(&list_lock); + v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n"); + return 0; + +err_unreg: + v4l2_device_disconnect(&mdev->v4l2_dev); + v4l2_device_put(&mdev->v4l2_dev); + return ret; +} + +static int aim_disconnect_channel(struct most_interface *iface, + int channel_idx) +{ + struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); + + if (!mdev) { + pr_err("no such channel is linked\n"); + return -ENOENT; + } + + v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n"); + + spin_lock_irq(&list_lock); + list_del(&mdev->list); + spin_unlock_irq(&list_lock); + + aim_unregister_videodev(mdev); + v4l2_device_disconnect(&mdev->v4l2_dev); + v4l2_device_put(&mdev->v4l2_dev); + return 0; +} + +static struct most_aim aim_info = { + .name = "v4l", + .probe_channel = aim_probe_channel, + .disconnect_channel = aim_disconnect_channel, + .rx_completion = aim_rx_data, +}; + +static int __init aim_init(void) +{ + spin_lock_init(&list_lock); + return most_register_aim(&aim_info); +} + +static void __exit aim_exit(void) +{ + struct most_video_dev *mdev, *tmp; + + /* + * As the mostcore currently doesn't call disconnect_channel() + * for linked channels while we call most_deregister_aim() + * we simulate this call here. + * This must be fixed in core. + */ + spin_lock_irq(&list_lock); + list_for_each_entry_safe(mdev, tmp, &video_devices, list) { + list_del(&mdev->list); + spin_unlock_irq(&list_lock); + + aim_unregister_videodev(mdev); + v4l2_device_disconnect(&mdev->v4l2_dev); + v4l2_device_put(&mdev->v4l2_dev); + spin_lock_irq(&list_lock); + } + spin_unlock_irq(&list_lock); + + most_deregister_aim(&aim_info); + BUG_ON(!list_empty(&video_devices)); +} + +module_init(aim_init); +module_exit(aim_exit); + +MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore"); +MODULE_AUTHOR("Andrey Shvetsov "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4d5f022f3a664ee5987118b754058ff31df03835 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:43 +0100 Subject: staging: most: remove proprietary kobjects This patch removes the proprietary kobjects used by the driver modules and replaces them with device structs. The patch is needed to have the driver being integrated into the kernel's device model. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 6 +- drivers/staging/most/core.c | 803 +++++++++++-------------------------- drivers/staging/most/core.h | 13 +- drivers/staging/most/dim2/dim2.c | 19 +- drivers/staging/most/dim2/sysfs.c | 92 +---- drivers/staging/most/dim2/sysfs.h | 6 +- drivers/staging/most/i2c/i2c.c | 7 +- drivers/staging/most/net/net.c | 3 +- drivers/staging/most/sound/sound.c | 3 +- drivers/staging/most/usb/usb.c | 243 +++-------- drivers/staging/most/video/video.c | 3 +- 11 files changed, 342 insertions(+), 856 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 3ae9246c0c5c..cd23db574d5f 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -412,7 +412,6 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) * @iface: pointer to interface instance * @channel_id: channel index/ID * @cfg: pointer to actual channel configuration - * @parent: pointer to kobject (needed for sysfs hook-up) * @name: name of the device to be created * * This allocates achannel object and creates the device node in /dev @@ -420,15 +419,14 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) * Returns 0 on success or error code otherwise. */ static int aim_probe(struct most_interface *iface, int channel_id, - struct most_channel_config *cfg, - struct kobject *parent, char *name) + struct most_channel_config *cfg, char *name) { struct aim_channel *c; unsigned long cl_flags; int retval; int current_minor; - if ((!iface) || (!cfg) || (!parent) || (!name)) { + if ((!iface) || (!cfg) || (!name)) { pr_info("Probing AIM with bad arguments"); return -EINVAL; } diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 8fe3f2ecd4e4..d4456abf18ed 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -27,7 +27,7 @@ #define STRING_SIZE 80 static struct class *most_class; -static struct device *core_dev; +static struct device core_dev; static struct ida mdev_id; static int dummy_num_buffers; @@ -38,7 +38,7 @@ struct most_c_aim_obj { }; struct most_c_obj { - struct kobject kobj; + struct device dev; struct completion cleanup; atomic_t mbo_ref; atomic_t mbo_nq_level; @@ -63,14 +63,13 @@ struct most_c_obj { wait_queue_head_t hdm_fifo_wq; }; -#define to_c_obj(d) container_of(d, struct most_c_obj, kobj) +#define to_c_obj(d) container_of(d, struct most_c_obj, dev) struct most_inst_obj { int dev_id; struct most_interface *iface; struct list_head channel_list; struct most_c_obj *channel[MAX_CHANNELS]; - struct kobject kobj; struct list_head list; }; @@ -85,8 +84,6 @@ static const struct { { MOST_CH_ISOC, "isoc_avp\n"}, }; -#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) - /** * list_pop_mbo - retrieves the first MBO of the list and removes it * @ptr: the list head to grab the MBO from. @@ -102,68 +99,6 @@ static const struct { * ___C H A N N E L___ */ -/** - * struct most_c_attr - to access the attributes of a channel object - * @attr: attributes of a channel - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_c_attr { - struct attribute attr; - ssize_t (*show)(struct most_c_obj *d, - struct most_c_attr *attr, - char *buf); - ssize_t (*store)(struct most_c_obj *d, - struct most_c_attr *attr, - const char *buf, - size_t count); -}; - -#define to_channel_attr(a) container_of(a, struct most_c_attr, attr) - -/** - * channel_attr_show - show function of channel object - * @kobj: pointer to its kobject - * @attr: pointer to its attributes - * @buf: buffer - */ -static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct most_c_attr *channel_attr = to_channel_attr(attr); - struct most_c_obj *c_obj = to_c_obj(kobj); - - if (!channel_attr->show) - return -EIO; - - return channel_attr->show(c_obj, channel_attr, buf); -} - -/** - * channel_attr_store - store function of channel object - * @kobj: pointer to its kobject - * @attr: pointer to its attributes - * @buf: buffer - * @len: length of buffer - */ -static ssize_t channel_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_c_attr *channel_attr = to_channel_attr(attr); - struct most_c_obj *c_obj = to_c_obj(kobj); - - if (!channel_attr->store) - return -EIO; - return channel_attr->store(c_obj, channel_attr, buf, len); -} - -static const struct sysfs_ops most_channel_sysfs_ops = { - .show = channel_attr_show, - .store = channel_attr_store, -}; - /** * most_free_mbo_coherent - free an MBO and its coherent buffer * @mbo: buffer to be released @@ -235,21 +170,11 @@ static int flush_trash_fifo(struct most_c_obj *c) return 0; } -/** - * most_channel_release - release function of channel object - * @kobj: pointer to channel's kobject - */ -static void most_channel_release(struct kobject *kobj) -{ - struct most_c_obj *c = to_c_obj(kobj); - - kfree(c); -} - -static ssize_t available_directions_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t available_directions_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; strcpy(buf, ""); @@ -261,10 +186,11 @@ static ssize_t available_directions_show(struct most_c_obj *c, return strlen(buf); } -static ssize_t available_datatypes_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t available_datatypes_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; strcpy(buf, ""); @@ -280,65 +206,75 @@ static ssize_t available_datatypes_show(struct most_c_obj *c, return strlen(buf); } -static ssize_t number_of_packet_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t number_of_packet_buffers_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", c->iface->channel_vector[i].num_buffers_packet); } -static ssize_t number_of_stream_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t number_of_stream_buffers_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", c->iface->channel_vector[i].num_buffers_streaming); } -static ssize_t size_of_packet_buffer_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t size_of_packet_buffer_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", c->iface->channel_vector[i].buffer_size_packet); } -static ssize_t size_of_stream_buffer_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t size_of_stream_buffer_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", c->iface->channel_vector[i].buffer_size_streaming); } -static ssize_t channel_starving_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t channel_starving_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); } -static ssize_t set_number_of_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_number_of_buffers_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); } -static ssize_t set_number_of_buffers_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_number_of_buffers_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); + int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); if (ret) @@ -346,18 +282,21 @@ static ssize_t set_number_of_buffers_store(struct most_c_obj *c, return count; } -static ssize_t set_buffer_size_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_buffer_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); } -static ssize_t set_buffer_size_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_buffer_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); if (ret) @@ -365,10 +304,12 @@ static ssize_t set_buffer_size_store(struct most_c_obj *c, return count; } -static ssize_t set_direction_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_direction_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + if (c->cfg.direction & MOST_CH_TX) return snprintf(buf, PAGE_SIZE, "tx\n"); else if (c->cfg.direction & MOST_CH_RX) @@ -376,11 +317,13 @@ static ssize_t set_direction_show(struct most_c_obj *c, return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } -static ssize_t set_direction_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_direction_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); + if (!strcmp(buf, "dir_rx\n")) { c->cfg.direction = MOST_CH_RX; } else if (!strcmp(buf, "rx\n")) { @@ -396,11 +339,12 @@ static ssize_t set_direction_store(struct most_c_obj *c, return count; } -static ssize_t set_datatype_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_datatype_show(struct device *dev, + struct device_attribute *attr, char *buf) { int i; + struct most_c_obj *c = to_c_obj(dev); for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) @@ -409,12 +353,13 @@ static ssize_t set_datatype_show(struct most_c_obj *c, return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } -static ssize_t set_datatype_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_datatype_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { int i; + struct most_c_obj *c = to_c_obj(dev); for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { if (!strcmp(buf, ch_data_type[i].name)) { @@ -430,18 +375,21 @@ static ssize_t set_datatype_store(struct most_c_obj *c, return count; } -static ssize_t set_subbuffer_size_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_subbuffer_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); } -static ssize_t set_subbuffer_size_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_subbuffer_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); if (ret) @@ -449,18 +397,21 @@ static ssize_t set_subbuffer_size_store(struct most_c_obj *c, return count; } -static ssize_t set_packets_per_xact_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_packets_per_xact_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); } -static ssize_t set_packets_per_xact_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_packets_per_xact_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); if (ret) @@ -468,77 +419,47 @@ static ssize_t set_packets_per_xact_store(struct most_c_obj *c, return count; } -static struct most_c_attr most_c_attrs[] = { - __ATTR_RO(available_directions), - __ATTR_RO(available_datatypes), - __ATTR_RO(number_of_packet_buffers), - __ATTR_RO(number_of_stream_buffers), - __ATTR_RO(size_of_stream_buffer), - __ATTR_RO(size_of_packet_buffer), - __ATTR_RO(channel_starving), - __ATTR_RW(set_buffer_size), - __ATTR_RW(set_number_of_buffers), - __ATTR_RW(set_direction), - __ATTR_RW(set_datatype), - __ATTR_RW(set_subbuffer_size), - __ATTR_RW(set_packets_per_xact), -}; - -/** - * most_channel_def_attrs - array of default attributes of channel object - */ -static struct attribute *most_channel_def_attrs[] = { - &most_c_attrs[0].attr, - &most_c_attrs[1].attr, - &most_c_attrs[2].attr, - &most_c_attrs[3].attr, - &most_c_attrs[4].attr, - &most_c_attrs[5].attr, - &most_c_attrs[6].attr, - &most_c_attrs[7].attr, - &most_c_attrs[8].attr, - &most_c_attrs[9].attr, - &most_c_attrs[10].attr, - &most_c_attrs[11].attr, - &most_c_attrs[12].attr, +#define DEV_ATTR(_name) (&dev_attr_##_name.attr) + +static DEVICE_ATTR_RO(available_directions); +static DEVICE_ATTR_RO(available_datatypes); +static DEVICE_ATTR_RO(number_of_packet_buffers); +static DEVICE_ATTR_RO(number_of_stream_buffers); +static DEVICE_ATTR_RO(size_of_stream_buffer); +static DEVICE_ATTR_RO(size_of_packet_buffer); +static DEVICE_ATTR_RO(channel_starving); +static DEVICE_ATTR_RW(set_buffer_size); +static DEVICE_ATTR_RW(set_number_of_buffers); +static DEVICE_ATTR_RW(set_direction); +static DEVICE_ATTR_RW(set_datatype); +static DEVICE_ATTR_RW(set_subbuffer_size); +static DEVICE_ATTR_RW(set_packets_per_xact); + +static struct attribute *channel_attrs[] = { + DEV_ATTR(available_directions), + DEV_ATTR(available_datatypes), + DEV_ATTR(number_of_packet_buffers), + DEV_ATTR(number_of_stream_buffers), + DEV_ATTR(size_of_stream_buffer), + DEV_ATTR(size_of_packet_buffer), + DEV_ATTR(channel_starving), + DEV_ATTR(set_buffer_size), + DEV_ATTR(set_number_of_buffers), + DEV_ATTR(set_direction), + DEV_ATTR(set_datatype), + DEV_ATTR(set_subbuffer_size), + DEV_ATTR(set_packets_per_xact), NULL, }; -static struct kobj_type most_channel_ktype = { - .sysfs_ops = &most_channel_sysfs_ops, - .release = most_channel_release, - .default_attrs = most_channel_def_attrs, +static struct attribute_group channel_attr_group = { + .attrs = channel_attrs, }; -static struct kset *most_channel_kset; - -/** - * create_most_c_obj - allocates a channel object - * @name: name of the channel object - * @parent: parent kobject - * - * This create a channel object and registers it with sysfs. - * Returns a pointer to the object or NULL when something went wrong. - */ -static struct most_c_obj * -create_most_c_obj(const char *name, struct kobject *parent) -{ - struct most_c_obj *c; - int retval; - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) - return NULL; - c->kobj.kset = most_channel_kset; - retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent, - "%s", name); - if (retval) { - kobject_put(&c->kobj); - return NULL; - } - kobject_uevent(&c->kobj, KOBJ_ADD); - return c; -} +static const struct attribute_group *channel_attr_groups[] = { + &channel_attr_group, + NULL, +}; /* ___ ___ * ___I N S T A N C E___ @@ -546,103 +467,22 @@ create_most_c_obj(const char *name, struct kobject *parent) static struct list_head instance_list; -/** - * struct most_inst_attribute - to access the attributes of instance object - * @attr: attributes of an instance - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_inst_attribute { - struct attribute attr; - ssize_t (*show)(struct most_inst_obj *d, - struct most_inst_attribute *attr, - char *buf); - ssize_t (*store)(struct most_inst_obj *d, - struct most_inst_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_instance_attr(a) \ - container_of(a, struct most_inst_attribute, attr) - -/** - * instance_attr_show - show function for an instance object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t instance_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct most_inst_attribute *instance_attr; - struct most_inst_obj *instance_obj; - - instance_attr = to_instance_attr(attr); - instance_obj = to_inst_obj(kobj); - - if (!instance_attr->show) - return -EIO; - - return instance_attr->show(instance_obj, instance_attr, buf); -} - -/** - * instance_attr_store - store function for an instance object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t instance_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_inst_attribute *instance_attr; - struct most_inst_obj *instance_obj; - - instance_attr = to_instance_attr(attr); - instance_obj = to_inst_obj(kobj); - - if (!instance_attr->store) - return -EIO; - - return instance_attr->store(instance_obj, instance_attr, buf, len); -} - -static const struct sysfs_ops most_inst_sysfs_ops = { - .show = instance_attr_show, - .store = instance_attr_store, -}; - -/** - * most_inst_release - release function for instance object - * @kobj: pointer to instance's kobject - * - * This frees the allocated memory for the instance object - */ -static void most_inst_release(struct kobject *kobj) -{ - struct most_inst_obj *inst = to_inst_obj(kobj); - - kfree(inst); -} - -static ssize_t description_show(struct most_inst_obj *instance_obj, - struct most_inst_attribute *attr, +static ssize_t description_show(struct device *dev, + struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", - instance_obj->iface->description); + struct most_interface *iface = to_most_interface(dev); + + return snprintf(buf, PAGE_SIZE, "%s\n", iface->description); } -static ssize_t interface_show(struct most_inst_obj *instance_obj, - struct most_inst_attribute *attr, +static ssize_t interface_show(struct device *dev, + struct device_attribute *attr, char *buf) { - switch (instance_obj->iface->interface) { + struct most_interface *iface = to_most_interface(dev); + + switch (iface->interface) { case ITYPE_LOOPBACK: return snprintf(buf, PAGE_SIZE, "loopback\n"); case ITYPE_I2C: @@ -665,182 +505,42 @@ static ssize_t interface_show(struct most_inst_obj *instance_obj, return snprintf(buf, PAGE_SIZE, "unknown\n"); } -static struct most_inst_attribute most_inst_attr_description = - __ATTR_RO(description); - -static struct most_inst_attribute most_inst_attr_interface = - __ATTR_RO(interface); +static DEVICE_ATTR_RO(description); +static DEVICE_ATTR_RO(interface); -static struct attribute *most_inst_def_attrs[] = { - &most_inst_attr_description.attr, - &most_inst_attr_interface.attr, +static struct attribute *interface_attrs[] = { + DEV_ATTR(description), + DEV_ATTR(interface), NULL, }; -static struct kobj_type most_inst_ktype = { - .sysfs_ops = &most_inst_sysfs_ops, - .release = most_inst_release, - .default_attrs = most_inst_def_attrs, +static struct attribute_group interface_attr_group = { + .attrs = interface_attrs, }; -static struct kset *most_inst_kset; - -/** - * create_most_inst_obj - creates an instance object - * @name: name of the object to be created - * - * This allocates memory for an instance structure, assigns the proper kset - * and registers it with sysfs. - * - * Returns a pointer to the instance object or NULL when something went wrong. - */ -static struct most_inst_obj *create_most_inst_obj(const char *name) -{ - struct most_inst_obj *inst; - int retval; - - inst = kzalloc(sizeof(*inst), GFP_KERNEL); - if (!inst) - return NULL; - inst->kobj.kset = most_inst_kset; - retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL, - "%s", name); - if (retval) { - kobject_put(&inst->kobj); - return NULL; - } - kobject_uevent(&inst->kobj, KOBJ_ADD); - return inst; -} - -/** - * destroy_most_inst_obj - MOST instance release function - * @inst: pointer to the instance object - * - * This decrements the reference counter of the instance object. - * If the reference count turns zero, its release function is called - */ -static void destroy_most_inst_obj(struct most_inst_obj *inst) -{ - struct most_c_obj *c, *tmp; - - list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - flush_trash_fifo(c); - flush_channel_fifos(c); - kobject_put(&c->kobj); - } - kobject_put(&inst->kobj); -} +static const struct attribute_group *interface_attr_groups[] = { + &interface_attr_group, + NULL, +}; /* ___ ___ * ___A I M___ */ -struct most_aim_obj { - struct kobject kobj; - struct list_head list; - struct most_aim *driver; -}; - -#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj) - -static struct list_head aim_list; - -/** - * struct most_aim_attribute - to access the attributes of AIM object - * @attr: attributes of an AIM - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_aim_attribute { - struct attribute attr; - ssize_t (*show)(struct most_aim_obj *d, - struct most_aim_attribute *attr, - char *buf); - ssize_t (*store)(struct most_aim_obj *d, - struct most_aim_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr) - -/** - * aim_attr_show - show function of an AIM object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t aim_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct most_aim_attribute *aim_attr; - struct most_aim_obj *aim_obj; - - aim_attr = to_aim_attr(attr); - aim_obj = to_aim_obj(kobj); - - if (!aim_attr->show) - return -EIO; - - return aim_attr->show(aim_obj, aim_attr, buf); -} - -/** - * aim_attr_store - store function of an AIM object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t aim_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_aim_attribute *aim_attr; - struct most_aim_obj *aim_obj; - - aim_attr = to_aim_attr(attr); - aim_obj = to_aim_obj(kobj); - - if (!aim_attr->store) - return -EIO; - return aim_attr->store(aim_obj, aim_attr, buf, len); -} - -static const struct sysfs_ops most_aim_sysfs_ops = { - .show = aim_attr_show, - .store = aim_attr_store, -}; - -/** - * most_aim_release - AIM release function - * @kobj: pointer to AIM's kobject - */ -static void most_aim_release(struct kobject *kobj) -{ - struct most_aim_obj *aim_obj = to_aim_obj(kobj); - - kfree(aim_obj); -} - -static ssize_t links_show(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, +static ssize_t links_show(struct device *dev, struct device_attribute *attr, char *buf) { struct most_c_obj *c; struct most_inst_obj *i; + struct most_aim *aim = to_most_aim(dev); int offs = 0; list_for_each_entry(i, &instance_list, list) { list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.ptr == aim_obj->driver || - c->aim1.ptr == aim_obj->driver) { + if (c->aim0.ptr == aim || c->aim1.ptr == aim) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s:%s\n", - kobject_name(&i->kobj), - kobject_name(&c->kobj)); + dev_name(&i->iface->dev), + dev_name(&c->dev)); } } } @@ -901,7 +601,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) int found = 0; list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - if (!strcmp(kobject_name(&i->kobj), mdev)) { + if (!strcmp(dev_name(&i->iface->dev), mdev)) { found++; break; } @@ -910,7 +610,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) return ERR_PTR(-EIO); list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (!strcmp(kobject_name(&c->kobj), mdev_ch)) { + if (!strcmp(dev_name(&c->dev), mdev_ch)) { found++; break; } @@ -942,13 +642,14 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) * (1) would create the device node /dev/my_rxchannel * (2) would create the device node /dev/mdev1-ep81 */ -static ssize_t add_link_store(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, +static ssize_t add_link_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { struct most_c_obj *c; struct most_aim **aim_ptr; + struct most_aim *aim = to_most_aim(dev); char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; @@ -980,9 +681,8 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj, else return -ENOSPC; - *aim_ptr = aim_obj->driver; - ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, - &c->cfg, &c->kobj, mdev_devnod); + *aim_ptr = aim; + ret = aim->probe_channel(c->iface, c->channel_id, &c->cfg, mdev_devnod); if (ret) { *aim_ptr = NULL; return ret; @@ -1001,12 +701,13 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj, * Example: * echo "mdev0:ep81" >remove_link */ -static ssize_t remove_link_store(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, +static ssize_t remove_link_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { struct most_c_obj *c; + struct most_aim *aim = to_most_aim(dev); char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; @@ -1022,74 +723,34 @@ static ssize_t remove_link_store(struct most_aim_obj *aim_obj, if (IS_ERR(c)) return -ENODEV; - if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) + if (aim->disconnect_channel(c->iface, c->channel_id)) return -EIO; - if (c->aim0.ptr == aim_obj->driver) + if (c->aim0.ptr == aim) c->aim0.ptr = NULL; - if (c->aim1.ptr == aim_obj->driver) + if (c->aim1.ptr == aim) c->aim1.ptr = NULL; return len; } -static struct most_aim_attribute most_aim_attrs[] = { - __ATTR_RO(links), - __ATTR_WO(add_link), - __ATTR_WO(remove_link), -}; +static DEVICE_ATTR_RO(links); +static DEVICE_ATTR_WO(add_link); +static DEVICE_ATTR_WO(remove_link); -static struct attribute *most_aim_def_attrs[] = { - &most_aim_attrs[0].attr, - &most_aim_attrs[1].attr, - &most_aim_attrs[2].attr, +static struct attribute *aim_attrs[] = { + DEV_ATTR(links), + DEV_ATTR(add_link), + DEV_ATTR(remove_link), NULL, }; -static struct kobj_type most_aim_ktype = { - .sysfs_ops = &most_aim_sysfs_ops, - .release = most_aim_release, - .default_attrs = most_aim_def_attrs, +static struct attribute_group aim_attr_group = { + .attrs = aim_attrs, }; -static struct kset *most_aim_kset; - -/** - * create_most_aim_obj - creates an AIM object - * @name: name of the AIM - * - * This creates an AIM object assigns the proper kset and registers - * it with sysfs. - * Returns a pointer to the object or NULL if something went wrong. - */ -static struct most_aim_obj *create_most_aim_obj(const char *name) -{ - struct most_aim_obj *most_aim; - int retval; - - most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL); - if (!most_aim) - return NULL; - most_aim->kobj.kset = most_aim_kset; - retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype, - NULL, "%s", name); - if (retval) { - kobject_put(&most_aim->kobj); - return NULL; - } - kobject_uevent(&most_aim->kobj, KOBJ_ADD); - return most_aim; -} - -/** - * destroy_most_aim_obj - AIM release function - * @p: pointer to AIM object - * - * This decrements the reference counter of the AIM object. If the - * reference count turns zero, its release function will be called. - */ -static void destroy_most_aim_obj(struct most_aim_obj *p) -{ - kobject_put(&p->kobj); -} +static const struct attribute_group *aim_attr_groups[] = { + &aim_attr_group, + NULL, +}; /* ___ ___ * ___C O R E___ @@ -1615,28 +1276,35 @@ out: } EXPORT_SYMBOL_GPL(most_stop_channel); +void release_aim(struct device *dev) +{ + pr_info("releasing aim %s\n", dev_name(dev)); +} + /** * most_register_aim - registers an AIM (driver) with the core * @aim: instance of AIM to be registered */ int most_register_aim(struct most_aim *aim) { - struct most_aim_obj *aim_obj; + int ret; if (!aim) { pr_err("Bad driver\n"); return -EINVAL; } - aim_obj = create_most_aim_obj(aim->name); - if (!aim_obj) { - pr_info("failed to alloc driver object\n"); - return -ENOMEM; + aim->dev.init_name = aim->name; + aim->dev.bus = &most_bus; + aim->dev.parent = &core_dev; + aim->dev.groups = aim_attr_groups; + aim->dev.release = release_aim; + ret = device_register(&aim->dev); + if (ret) { + pr_err("registering device %s failed\n", aim->name); + return ret; } - aim_obj->driver = aim; - aim->context = aim_obj; pr_info("registered new application interfacing module %s\n", aim->name); - list_add_tail(&aim_obj->list, &aim_list); return 0; } EXPORT_SYMBOL_GPL(most_register_aim); @@ -1647,7 +1315,6 @@ EXPORT_SYMBOL_GPL(most_register_aim); */ int most_deregister_aim(struct most_aim *aim) { - struct most_aim_obj *aim_obj; struct most_c_obj *c, *tmp; struct most_inst_obj *i, *i_tmp; @@ -1656,11 +1323,6 @@ int most_deregister_aim(struct most_aim *aim) return -EINVAL; } - aim_obj = aim->context; - if (!aim_obj) { - pr_info("driver not registered.\n"); - return -EINVAL; - } list_for_each_entry_safe(i, i_tmp, &instance_list, list) { list_for_each_entry_safe(c, tmp, &i->channel_list, list) { if (c->aim0.ptr == aim || c->aim1.ptr == aim) @@ -1672,13 +1334,22 @@ int most_deregister_aim(struct most_aim *aim) c->aim1.ptr = NULL; } } - list_del(&aim_obj->list); - destroy_most_aim_obj(aim_obj); + device_unregister(&aim->dev); pr_info("deregistering application interfacing module %s\n", aim->name); return 0; } EXPORT_SYMBOL_GPL(most_deregister_aim); +static void release_interface(struct device *dev) +{ + pr_info("releasing interface dev %s...\n", dev_name(dev)); +} + +static void release_channel(struct device *dev) +{ + pr_info("releasing channel dev %s...\n", dev_name(dev)); +} + /** * most_register_interface - registers an interface with core * @iface: pointer to the instance of the interface description. @@ -1686,7 +1357,7 @@ EXPORT_SYMBOL_GPL(most_deregister_aim); * Allocates and initializes a new interface instance and all of its channels. * Returns a pointer to kobject or an error pointer. */ -struct kobject *most_register_interface(struct most_interface *iface) +int most_register_interface(struct most_interface *iface) { unsigned int i; int id; @@ -1698,21 +1369,20 @@ struct kobject *most_register_interface(struct most_interface *iface) if (!iface || !iface->enqueue || !iface->configure || !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { pr_err("Bad interface or channel overflow\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); if (id < 0) { pr_info("Failed to alloc mdev ID\n"); - return ERR_PTR(id); + return id; } - snprintf(name, STRING_SIZE, "mdev%d", id); - inst = create_most_inst_obj(name); + inst = kzalloc(sizeof(*inst), GFP_KERNEL); if (!inst) { pr_info("Failed to allocate interface instance\n"); ida_simple_remove(&mdev_id, id); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } iface->priv = inst; @@ -1720,6 +1390,18 @@ struct kobject *most_register_interface(struct most_interface *iface) inst->iface = iface; inst->dev_id = id; list_add_tail(&inst->list, &instance_list); + snprintf(name, STRING_SIZE, "mdev%d", id); + iface->dev.init_name = name; + iface->dev.bus = &most_bus; + iface->dev.parent = &core_dev; + iface->dev.groups = interface_attr_groups; + iface->dev.release = release_interface; + if (device_register(&iface->dev)) { + pr_err("registering iface->dev failed\n"); + kfree(inst); + ida_simple_remove(&mdev_id, id); + return -ENOMEM; + } for (i = 0; i < iface->num_channels; i++) { const char *name_suffix = iface->channel_vector[i].name_suffix; @@ -1730,9 +1412,17 @@ struct kobject *most_register_interface(struct most_interface *iface) snprintf(channel_name, STRING_SIZE, "%s", name_suffix); /* this increments the reference count of this instance */ - c = create_most_c_obj(channel_name, &inst->kobj); + c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) goto free_instance; + c->dev.init_name = channel_name; + c->dev.parent = &iface->dev; + c->dev.groups = channel_attr_groups; + c->dev.release = release_channel; + if (device_register(&c->dev)) { + pr_err("registering c->dev failed\n"); + goto free_instance; + } inst->channel[i] = c; c->is_starving = 0; c->iface = iface; @@ -1758,15 +1448,14 @@ struct kobject *most_register_interface(struct most_interface *iface) list_add_tail(&c->list, &inst->channel_list); } pr_info("registered new MOST device mdev%d (%s)\n", - inst->dev_id, iface->description); - return &inst->kobj; + id, iface->description); + return 0; free_instance: pr_info("Failed allocate channel(s)\n"); - list_del(&inst->list); + device_unregister(&iface->dev); ida_simple_remove(&mdev_id, id); - destroy_most_inst_obj(inst); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } EXPORT_SYMBOL_GPL(most_register_interface); @@ -1779,17 +1468,14 @@ EXPORT_SYMBOL_GPL(most_register_interface); */ void most_deregister_interface(struct most_interface *iface) { - struct most_inst_obj *i = iface->priv; + int i; struct most_c_obj *c; + struct most_inst_obj *inst; - if (unlikely(!i)) { - pr_info("Bad Interface\n"); - return; - } - pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, - iface->description); - - list_for_each_entry(c, &i->channel_list, list) { + pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description); + inst = iface->priv; + for (i = 0; i < iface->num_channels; i++) { + c = inst->channel[i]; if (c->aim0.ptr) c->aim0.ptr->disconnect_channel(c->iface, c->channel_id); @@ -1798,11 +1484,14 @@ void most_deregister_interface(struct most_interface *iface) c->channel_id); c->aim0.ptr = NULL; c->aim1.ptr = NULL; + list_del(&c->list); + device_unregister(&c->dev); + kfree(c); } - ida_simple_remove(&mdev_id, i->dev_id); - list_del(&i->list); - destroy_most_inst_obj(i); + ida_simple_remove(&mdev_id, inst->dev_id); + kfree(inst); + device_unregister(&iface->dev); } EXPORT_SYMBOL_GPL(most_deregister_interface); @@ -1852,13 +1541,17 @@ void most_resume_enqueue(struct most_interface *iface, int id) } EXPORT_SYMBOL_GPL(most_resume_enqueue); +static void release_most_sub(struct device *dev) +{ + pr_info("releasing most_subsystem\n"); +} + static int __init most_init(void) { int err; pr_info("init()\n"); INIT_LIST_HEAD(&instance_list); - INIT_LIST_HEAD(&aim_list); ida_init(&mdev_id); err = bus_register(&most_bus); @@ -1880,30 +1573,15 @@ static int __init most_init(void) goto exit_class; } - core_dev = device_create(most_class, NULL, 0, NULL, "mostcore"); - if (IS_ERR(core_dev)) { - err = PTR_ERR(core_dev); - goto exit_driver; - } - - most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj); - if (!most_aim_kset) { - err = -ENOMEM; - goto exit_class_container; - } - - most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj); - if (!most_inst_kset) { + core_dev.init_name = "most_bus"; + core_dev.release = release_most_sub; + if (device_register(&core_dev)) { err = -ENOMEM; - goto exit_driver_kset; + goto exit_driver; } return 0; -exit_driver_kset: - kset_unregister(most_aim_kset); -exit_class_container: - device_destroy(most_class, 0); exit_driver: driver_unregister(&mostcore); exit_class: @@ -1915,21 +1593,8 @@ exit_bus: static void __exit most_exit(void) { - struct most_inst_obj *i, *i_tmp; - struct most_aim_obj *d, *d_tmp; - pr_info("exit core module\n"); - list_for_each_entry_safe(d, d_tmp, &aim_list, list) { - destroy_most_aim_obj(d); - } - - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - list_del(&i->list); - destroy_most_inst_obj(i); - } - kset_unregister(most_inst_kset); - kset_unregister(most_aim_kset); - device_destroy(most_class, 0); + device_unregister(&core_dev); driver_unregister(&mostcore); class_destroy(most_class); bus_unregister(&most_bus); diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 5577e8735196..29595d9ef7ed 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -17,8 +17,8 @@ #define __MOST_CORE_H__ #include +#include -struct kobject; struct module; /** @@ -232,6 +232,7 @@ struct mbo { * @priv Private field used by mostcore to store context information. */ struct most_interface { + struct device dev; struct module *mod; enum most_interface_type interface; const char *description; @@ -249,6 +250,8 @@ struct most_interface { void *priv; }; +#define to_most_interface(d) container_of(d, struct most_interface, dev) + /** * struct most_aim - identifies MOST device driver to mostcore * @name: Driver name @@ -259,10 +262,10 @@ struct most_interface { * @context: context pointer to be used by mostcore */ struct most_aim { + struct device dev; const char *name; int (*probe_channel)(struct most_interface *iface, int channel_idx, - struct most_channel_config *cfg, - struct kobject *parent, char *name); + struct most_channel_config *cfg, char *name); int (*disconnect_channel)(struct most_interface *iface, int channel_idx); int (*rx_completion)(struct mbo *mbo); @@ -270,6 +273,8 @@ struct most_aim { void *context; }; +#define to_most_aim(d) container_of(d, struct most_aim, dev) + /** * most_register_interface - Registers instance of the interface. * @iface: Pointer to the interface instance description. @@ -279,7 +284,7 @@ struct most_aim { * Note: HDM has to ensure that any reference held on the kobj is * released before deregistering the interface. */ -struct kobject *most_register_interface(struct most_interface *iface); +int most_register_interface(struct most_interface *iface); /** * Deregisters instance of the interface. diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 921db9880d80..2bd40abbc8c6 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -87,6 +87,7 @@ struct hdm_channel { * @atx_idx: index of async tx channel */ struct dim2_hdm { + struct device dev; struct hdm_channel hch[DMA_CHANNELS]; struct most_channel_capability capabilities[DMA_CHANNELS]; struct most_interface most_iface; @@ -738,7 +739,6 @@ static int dim2_probe(struct platform_device *pdev) struct dim2_hdm *dev; struct resource *res; int ret, i; - struct kobject *kobj; int irq; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); @@ -826,17 +826,20 @@ static int dim2_probe(struct platform_device *pdev) dev->most_iface.enqueue = enqueue; dev->most_iface.poison_channel = poison_channel; dev->most_iface.request_netinfo = request_netinfo; + dev->dev.init_name = "dim2_state"; + dev->dev.parent = &dev->most_iface.dev; - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { - ret = PTR_ERR(kobj); + ret = most_register_interface(&dev->most_iface); + if (ret) { dev_err(&pdev->dev, "failed to register MOST interface\n"); goto err_stop_thread; } - ret = dim2_sysfs_probe(&dev->bus, kobj); - if (ret) + ret = dim2_sysfs_probe(&dev->dev); + if (ret) { + dev_err(&pdev->dev, "failed to create sysfs attribute\n"); goto err_unreg_iface; + } ret = startup_dim(pdev); if (ret) { @@ -847,7 +850,7 @@ static int dim2_probe(struct platform_device *pdev) return 0; err_destroy_bus: - dim2_sysfs_destroy(&dev->bus); + dim2_sysfs_destroy(&dev->dev); err_unreg_iface: most_deregister_interface(&dev->most_iface); err_stop_thread: @@ -875,7 +878,7 @@ static int dim2_remove(struct platform_device *pdev) if (pdata && pdata->destroy) pdata->destroy(pdata); - dim2_sysfs_destroy(&dev->bus); + dim2_sysfs_destroy(&dev->dev); most_deregister_interface(&dev->most_iface); kthread_stop(dev->netinfo_task); diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c index ec1f4cecf9e7..7ead7030c6b8 100644 --- a/drivers/staging/most/dim2/sysfs.c +++ b/drivers/staging/most/dim2/sysfs.c @@ -11,99 +11,39 @@ #include #include "sysfs.h" +#include -struct bus_attr { - struct attribute attr; - ssize_t (*show)(struct medialb_bus *bus, char *buf); - ssize_t (*store)(struct medialb_bus *bus, const char *buf, - size_t count); -}; - -static ssize_t state_show(struct medialb_bus *bus, char *buf) +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) { bool state = dim2_sysfs_get_state_cb(); return sprintf(buf, "%s\n", state ? "locked" : ""); } -static struct bus_attr state_attr = __ATTR_RO(state); +DEVICE_ATTR_RO(state); -static struct attribute *bus_default_attrs[] = { - &state_attr.attr, +static struct attribute *dev_attrs[] = { + &dev_attr_state.attr, NULL, }; -static const struct attribute_group bus_attr_group = { - .attrs = bus_default_attrs, +static struct attribute_group dev_attr_group = { + .attrs = dev_attrs, }; -static void bus_kobj_release(struct kobject *kobj) -{ -} - -static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->show) - return -EIO; - - return xattr->show(bus, buf); -} - -static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->store) - return -EIO; - - return xattr->store(bus, buf, count); -} - -static struct sysfs_ops const bus_kobj_sysfs_ops = { - .show = bus_kobj_attr_show, - .store = bus_kobj_attr_store, -}; - -static struct kobj_type bus_ktype = { - .release = bus_kobj_release, - .sysfs_ops = &bus_kobj_sysfs_ops, +static const struct attribute_group *dev_attr_groups[] = { + &dev_attr_group, + NULL, }; -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj) +int dim2_sysfs_probe(struct device *dev) { - int err; - - kobject_init(&bus->kobj_group, &bus_ktype); - err = kobject_add(&bus->kobj_group, parent_kobj, "bus"); - if (err) { - pr_err("kobject_add() failed: %d\n", err); - goto err_kobject_add; - } - - err = sysfs_create_group(&bus->kobj_group, &bus_attr_group); - if (err) { - pr_err("sysfs_create_group() failed: %d\n", err); - goto err_create_group; - } - - return 0; - -err_create_group: - kobject_put(&bus->kobj_group); - -err_kobject_add: - return err; + dev->groups = dev_attr_groups; + return device_register(dev); } -void dim2_sysfs_destroy(struct medialb_bus *bus) +void dim2_sysfs_destroy(struct device *dev) { - kobject_put(&bus->kobj_group); + device_unregister(dev); } diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h index a33ebd8b45f5..33756a3bffe2 100644 --- a/drivers/staging/most/dim2/sysfs.h +++ b/drivers/staging/most/dim2/sysfs.h @@ -16,10 +16,10 @@ struct medialb_bus { struct kobject kobj_group; }; -struct dim2_hdm; +struct device; -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj); -void dim2_sysfs_destroy(struct medialb_bus *bus); +int dim2_sysfs_probe(struct device *dev); +void dim2_sysfs_destroy(struct device *dev); /* * callback, diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c index 156b2b1bdba9..141239fc9f51 100644 --- a/drivers/staging/most/i2c/i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -303,7 +303,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct hdm_i2c *dev; int ret, i; - struct kobject *kobj; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -341,11 +340,11 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) dev->client = client; i2c_set_clientdata(client, dev); - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { + ret = most_register_interface(&dev->most_iface); + if (ret) { pr_err("Failed to register i2c as a MOST interface\n"); kfree(dev); - return PTR_ERR(kobj); + return ret; } dev->polling_mode = polling_req || client->irq <= 0; diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index 3cbd403aa516..a9323e4afad7 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -291,8 +291,7 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) } static int aim_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, - struct kobject *parent, char *name) + struct most_channel_config *ccfg, char *name) { struct net_dev_context *nd; struct net_dev_channel *ch; diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 5826f710c925..5504f93aca39 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -539,7 +539,6 @@ error: * @iface: pointer to interface instance * @channel_id: channel index/ID * @cfg: pointer to actual channel configuration - * @parent: pointer to kobject (needed for sysfs hook-up) * @arg_list: string that provides the name of the device to be created in /dev * plus the desired audio resolution * @@ -549,7 +548,7 @@ error: */ static int audio_probe_channel(struct most_interface *iface, int channel_id, struct most_channel_config *cfg, - struct kobject *parent, char *arg_list) + char *arg_list) { struct channel *channel; struct snd_card *card; diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index b2d2abe15efe..7da7dd5e718d 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -64,12 +64,12 @@ * @reg_addr: register address for arbitrary DCI access */ struct most_dci_obj { - struct kobject kobj; + struct device dev; struct usb_device *usb_device; u16 reg_addr; }; -#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) +#define to_dci_obj(p) container_of(p, struct most_dci_obj, dev) struct most_dev; @@ -84,7 +84,6 @@ struct clear_hold_work { /** * struct most_dev - holds all usb interface specific stuff - * @parent: parent object in sysfs * @usb_device: pointer to usb device * @iface: hardware interface * @cap: channel capabilities @@ -102,7 +101,6 @@ struct clear_hold_work { * @poll_work_obj: work for polling link status */ struct most_dev { - struct kobject *parent; struct usb_device *usb_device; struct most_interface iface; struct most_channel_capability *cap; @@ -834,94 +832,6 @@ static const struct usb_device_id usbid[] = { { } /* Terminating entry */ }; -#define MOST_DCI_RO_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0444, show_value, NULL) - -#define MOST_DCI_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0644, show_value, store_value) - -#define MOST_DCI_WO_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0200, NULL, store_value) - -/** - * struct most_dci_attribute - to access the attributes of a dci object - * @attr: attributes of a dci object - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_dci_attribute { - struct attribute attr; - ssize_t (*show)(struct most_dci_obj *d, - struct most_dci_attribute *attr, - char *buf); - ssize_t (*store)(struct most_dci_obj *d, - struct most_dci_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr) - -/** - * dci_attr_show - show function for dci object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct most_dci_attribute *dci_attr = to_dci_attr(attr); - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - if (!dci_attr->show) - return -EIO; - - return dci_attr->show(dci_obj, dci_attr, buf); -} - -/** - * dci_attr_store - store function for dci object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t dci_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_dci_attribute *dci_attr = to_dci_attr(attr); - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - if (!dci_attr->store) - return -EIO; - - return dci_attr->store(dci_obj, dci_attr, buf, len); -} - -static const struct sysfs_ops most_dci_sysfs_ops = { - .show = dci_attr_show, - .store = dci_attr_store, -}; - -/** - * most_dci_release - release function for dci object - * @kobj: pointer to kobject - * - * This frees the memory allocated for the dci object - */ -static void most_dci_release(struct kobject *kobj) -{ - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - kfree(dci_obj); -} - struct regs { const char *name; u16 reg; @@ -962,10 +872,11 @@ static int get_stat_reg_addr(const struct regs *regs, int size, #define get_static_reg_addr(regs, name, reg_addr) \ get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr) -static ssize_t show_value(struct most_dci_obj *dci_obj, - struct most_dci_attribute *attr, char *buf) +static ssize_t show_value(struct device *dev, struct device_attribute *attr, + char *buf) { const char *name = attr->attr.name; + struct most_dci_obj *dci_obj = to_dci_obj(dev); u16 val; u16 reg_addr; int err; @@ -986,13 +897,13 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, return snprintf(buf, PAGE_SIZE, "%04x\n", val); } -static ssize_t store_value(struct most_dci_obj *dci_obj, - struct most_dci_attribute *attr, +static ssize_t store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u16 val; u16 reg_addr; const char *name = attr->attr.name; + struct most_dci_obj *dci_obj = to_dci_obj(dev); struct usb_device *usb_dev = dci_obj->usb_device; int err = kstrtou16(buf, 16, &val); @@ -1019,86 +930,49 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, return count; } -static MOST_DCI_RO_ATTR(ni_state); -static MOST_DCI_RO_ATTR(packet_bandwidth); -static MOST_DCI_RO_ATTR(node_address); -static MOST_DCI_RO_ATTR(node_position); -static MOST_DCI_WO_ATTR(sync_ep); -static MOST_DCI_ATTR(mep_filter); -static MOST_DCI_ATTR(mep_hash0); -static MOST_DCI_ATTR(mep_hash1); -static MOST_DCI_ATTR(mep_hash2); -static MOST_DCI_ATTR(mep_hash3); -static MOST_DCI_ATTR(mep_eui48_hi); -static MOST_DCI_ATTR(mep_eui48_mi); -static MOST_DCI_ATTR(mep_eui48_lo); -static MOST_DCI_ATTR(arb_address); -static MOST_DCI_ATTR(arb_value); - -/** - * most_dci_def_attrs - array of default attribute files of the dci object - */ -static struct attribute *most_dci_def_attrs[] = { - &most_dci_attr_ni_state.attr, - &most_dci_attr_packet_bandwidth.attr, - &most_dci_attr_node_address.attr, - &most_dci_attr_node_position.attr, - &most_dci_attr_sync_ep.attr, - &most_dci_attr_mep_filter.attr, - &most_dci_attr_mep_hash0.attr, - &most_dci_attr_mep_hash1.attr, - &most_dci_attr_mep_hash2.attr, - &most_dci_attr_mep_hash3.attr, - &most_dci_attr_mep_eui48_hi.attr, - &most_dci_attr_mep_eui48_mi.attr, - &most_dci_attr_mep_eui48_lo.attr, - &most_dci_attr_arb_address.attr, - &most_dci_attr_arb_value.attr, +DEVICE_ATTR(ni_state, 0444, show_value, NULL); +DEVICE_ATTR(packet_bandwidth, 0444, show_value, NULL); +DEVICE_ATTR(node_address, 0444, show_value, NULL); +DEVICE_ATTR(node_position, 0444, show_value, NULL); +DEVICE_ATTR(sync_ep, 0200, NULL, store_value); +DEVICE_ATTR(mep_filter, 0644, show_value, store_value); +DEVICE_ATTR(mep_hash0, 0644, show_value, store_value); +DEVICE_ATTR(mep_hash1, 0644, show_value, store_value); +DEVICE_ATTR(mep_hash2, 0644, show_value, store_value); +DEVICE_ATTR(mep_hash3, 0644, show_value, store_value); +DEVICE_ATTR(mep_eui48_hi, 0644, show_value, store_value); +DEVICE_ATTR(mep_eui48_mi, 0644, show_value, store_value); +DEVICE_ATTR(mep_eui48_lo, 0644, show_value, store_value); +DEVICE_ATTR(arb_address, 0644, show_value, store_value); +DEVICE_ATTR(arb_value, 0644, show_value, store_value); + +static struct attribute *dci_attrs[] = { + &dev_attr_ni_state.attr, + &dev_attr_packet_bandwidth.attr, + &dev_attr_node_address.attr, + &dev_attr_node_position.attr, + &dev_attr_sync_ep.attr, + &dev_attr_mep_filter.attr, + &dev_attr_mep_hash0.attr, + &dev_attr_mep_hash1.attr, + &dev_attr_mep_hash2.attr, + &dev_attr_mep_hash3.attr, + &dev_attr_mep_eui48_hi.attr, + &dev_attr_mep_eui48_mi.attr, + &dev_attr_mep_eui48_lo.attr, + &dev_attr_arb_address.attr, + &dev_attr_arb_value.attr, NULL, }; -/** - * DCI ktype - */ -static struct kobj_type most_dci_ktype = { - .sysfs_ops = &most_dci_sysfs_ops, - .release = most_dci_release, - .default_attrs = most_dci_def_attrs, +static struct attribute_group dci_attr_group = { + .attrs = dci_attrs, }; -/** - * create_most_dci_obj - allocates a dci object - * @parent: parent kobject - * - * This creates a dci object and registers it with sysfs. - * Returns a pointer to the object or NULL when something went wrong. - */ -static struct -most_dci_obj *create_most_dci_obj(struct kobject *parent) -{ - struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); - int retval; - - if (!most_dci) - return NULL; - - retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent, - "dci"); - if (retval) { - kobject_put(&most_dci->kobj); - return NULL; - } - return most_dci; -} - -/** - * destroy_most_dci_obj - DCI object release function - * @p: pointer to dci object - */ -static void destroy_most_dci_obj(struct most_dci_obj *p) -{ - kobject_put(&p->kobj); -} +static const struct attribute_group *dci_attr_groups[] = { + &dci_attr_group, + NULL, +}; /** * hdm_probe - probe function of USB device driver @@ -1211,20 +1085,15 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) usb_dev->config->desc.bConfigurationValue, usb_iface_desc->desc.bInterfaceNumber); - mdev->parent = most_register_interface(&mdev->iface); - if (IS_ERR(mdev->parent)) { - ret = PTR_ERR(mdev->parent); + ret = most_register_interface(&mdev->iface); + if (ret) goto exit_free4; - } mutex_lock(&mdev->io_mutex); if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 || le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) { - /* this increments the reference count of the instance - * object of the core - */ - mdev->dci = create_most_dci_obj(mdev->parent); + mdev->dci = kzalloc(sizeof(*mdev->dci), GFP_KERNEL); if (!mdev->dci) { mutex_unlock(&mdev->io_mutex); most_deregister_interface(&mdev->iface); @@ -1232,12 +1101,21 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) goto exit_free4; } - kobject_uevent(&mdev->dci->kobj, KOBJ_ADD); + mdev->dci->dev.init_name = "dci"; + mdev->dci->dev.parent = &mdev->iface.dev; + mdev->dci->dev.groups = dci_attr_groups; + if (device_register(&mdev->dci->dev)) { + mutex_unlock(&mdev->io_mutex); + most_deregister_interface(&mdev->iface); + ret = -ENOMEM; + goto exit_free5; + } mdev->dci->usb_device = mdev->usb_device; } mutex_unlock(&mdev->io_mutex); return 0; - +exit_free5: + kfree(mdev->dci); exit_free4: kfree(mdev->busy_urbs); exit_free3: @@ -1277,7 +1155,8 @@ static void hdm_disconnect(struct usb_interface *interface) del_timer_sync(&mdev->link_stat_timer); cancel_work_sync(&mdev->poll_work_obj); - destroy_most_dci_obj(mdev->dci); + device_unregister(&mdev->dci->dev); + kfree(mdev->dci); most_deregister_interface(&mdev->iface); kfree(mdev->busy_urbs); diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 3c813ed7f3ec..25ae4887b04d 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -480,8 +480,7 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) } static int aim_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, - struct kobject *parent, char *name) + struct most_channel_config *ccfg, char *name) { int ret; struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); -- cgit v1.2.3 From 14c018a93e8e74310e2e9f9a9e6cb39e7337c44b Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:44 +0100 Subject: staging: most: core: remove function get_channel_by_iface This patch removes the function get_channel_by_iface that walks a list of all registered interfaces and returns a pointer to a channel when matched. Instead the private field of the interface structure is used to directly access the channel via the id. The patch is needed to remove unnecessary list traversing. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 47 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index d4456abf18ed..7f7d6b65d76f 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -989,37 +989,10 @@ static void most_write_completion(struct mbo *mbo) arm_mbo(mbo); } -/** - * get_channel_by_iface - get pointer to channel object - * @iface: pointer to interface instance - * @id: channel ID - * - * This retrieves a pointer to a channel of the given interface and channel ID. - */ -static struct -most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) -{ - struct most_inst_obj *i; - - if (unlikely(!iface)) { - pr_err("Bad interface\n"); - return NULL; - } - if (unlikely((id < 0) || (id >= iface->num_channels))) { - pr_err("Channel index (%d) out of range\n", id); - return NULL; - } - i = iface->priv; - if (unlikely(!i)) { - pr_err("interface is not registered\n"); - return NULL; - } - return i->channel[id]; -} - int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) { - struct most_c_obj *c = get_channel_by_iface(iface, id); + struct most_inst_obj *inst = iface->priv; + struct most_c_obj *c = inst->channel[id]; unsigned long flags; int empty; @@ -1051,10 +1024,11 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id, { struct mbo *mbo; struct most_c_obj *c; + struct most_inst_obj *inst = iface->priv; unsigned long flags; int *num_buffers_ptr; - c = get_channel_by_iface(iface, id); + c = inst->channel[id]; if (unlikely(!c)) return NULL; @@ -1156,7 +1130,8 @@ int most_start_channel(struct most_interface *iface, int id, { int num_buffer; int ret; - struct most_c_obj *c = get_channel_by_iface(iface, id); + struct most_inst_obj *inst = iface->priv; + struct most_c_obj *c = inst->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1224,13 +1199,15 @@ EXPORT_SYMBOL_GPL(most_start_channel); int most_stop_channel(struct most_interface *iface, int id, struct most_aim *aim) { + struct most_inst_obj *inst; struct most_c_obj *c; if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { pr_err("Bad interface or index out of range\n"); return -EINVAL; } - c = get_channel_by_iface(iface, id); + inst = iface->priv; + c = inst->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1507,7 +1484,8 @@ EXPORT_SYMBOL_GPL(most_deregister_interface); */ void most_stop_enqueue(struct most_interface *iface, int id) { - struct most_c_obj *c = get_channel_by_iface(iface, id); + struct most_inst_obj *inst = iface->priv; + struct most_c_obj *c = inst->channel[id]; if (!c) return; @@ -1528,7 +1506,8 @@ EXPORT_SYMBOL_GPL(most_stop_enqueue); */ void most_resume_enqueue(struct most_interface *iface, int id) { - struct most_c_obj *c = get_channel_by_iface(iface, id); + struct most_inst_obj *inst = iface->priv; + struct most_c_obj *c = inst->channel[id]; if (!c) return; -- cgit v1.2.3 From 921c80c52b7440a0f5c5c542d40a3295d525276b Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:45 +0100 Subject: staging: most: core: add a match function for the bus This patch adds the function most_match. It is needed to accociate registered devices and drivers with the bus. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 7f7d6b65d76f..ce063a1597c3 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -756,11 +756,20 @@ static const struct attribute_group *aim_attr_groups[] = { * ___C O R E___ */ +int most_match(struct device *dev, struct device_driver *drv) +{ + if (!strcmp(dev_name(dev), "most")) + return 0; + else + return 1; +} + /** * Instantiation of the MOST bus */ static struct bus_type most_bus = { .name = "most", + .match = most_match, }; /** -- cgit v1.2.3 From e6e79b449ed99925c59eff66ba836f2532fec911 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:46 +0100 Subject: staging: most: core: encapsulate code in function This patch adds the function link_channel_to_aim to increase readability of the function add_link_store. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index ce063a1597c3..0ef90851f891 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -620,6 +620,30 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) return c; } +static inline int link_channel_to_aim(struct most_c_obj *c, + struct most_aim *aim, char *aim_param) +{ + int ret; + struct most_aim **aim_ptr; + + if (!c->aim0.ptr) + aim_ptr = &c->aim0.ptr; + else if (!c->aim1.ptr) + aim_ptr = &c->aim1.ptr; + else + return -ENOSPC; + + *aim_ptr = aim; + ret = aim->probe_channel(c->iface, c->channel_id, + &c->cfg, aim_param); + if (ret) { + *aim_ptr = NULL; + return ret; + } + + return 0; +} + /** * add_link_store - store() function for add_link attribute * @aim_obj: pointer to AIM object @@ -648,7 +672,6 @@ static ssize_t add_link_store(struct device *dev, size_t len) { struct most_c_obj *c; - struct most_aim **aim_ptr; struct most_aim *aim = to_most_aim(dev); char buffer[STRING_SIZE]; char *mdev; @@ -674,19 +697,9 @@ static ssize_t add_link_store(struct device *dev, if (IS_ERR(c)) return -ENODEV; - if (!c->aim0.ptr) - aim_ptr = &c->aim0.ptr; - else if (!c->aim1.ptr) - aim_ptr = &c->aim1.ptr; - else - return -ENOSPC; - - *aim_ptr = aim; - ret = aim->probe_channel(c->iface, c->channel_id, &c->cfg, mdev_devnod); - if (ret) { - *aim_ptr = NULL; + ret = link_channel_to_aim(c, aim, mdev_devnod); + if (ret) return ret; - } return len; } -- cgit v1.2.3 From fcb7fad82e23f62e2ffa2b732a1cf3c2d10b923e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:47 +0100 Subject: staging: most: core: rename structure This patch renames the structure most_c_obj to most_channel. This is needed to enhance readability. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 104 ++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 0ef90851f891..587e42f65a04 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -37,7 +37,7 @@ struct most_c_aim_obj { int num_buffers; }; -struct most_c_obj { +struct most_channel { struct device dev; struct completion cleanup; atomic_t mbo_ref; @@ -63,13 +63,13 @@ struct most_c_obj { wait_queue_head_t hdm_fifo_wq; }; -#define to_c_obj(d) container_of(d, struct most_c_obj, dev) +#define to_channel(d) container_of(d, struct most_channel, dev) struct most_inst_obj { int dev_id; struct most_interface *iface; struct list_head channel_list; - struct most_c_obj *channel[MAX_CHANNELS]; + struct most_channel *channel[MAX_CHANNELS]; struct list_head list; }; @@ -106,7 +106,7 @@ static const struct { */ static void most_free_mbo_coherent(struct mbo *mbo) { - struct most_c_obj *c = mbo->context; + struct most_channel *c = mbo->context; u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address, @@ -120,7 +120,7 @@ static void most_free_mbo_coherent(struct mbo *mbo) * flush_channel_fifos - clear the channel fifos * @c: pointer to channel object */ -static void flush_channel_fifos(struct most_c_obj *c) +static void flush_channel_fifos(struct most_channel *c) { unsigned long flags, hf_flags; struct mbo *mbo, *tmp; @@ -154,7 +154,7 @@ static void flush_channel_fifos(struct most_c_obj *c) * flush_trash_fifo - clear the trash fifo * @c: pointer to channel object */ -static int flush_trash_fifo(struct most_c_obj *c) +static int flush_trash_fifo(struct most_channel *c) { struct mbo *mbo, *tmp; unsigned long flags; @@ -174,7 +174,7 @@ static ssize_t available_directions_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); unsigned int i = c->channel_id; strcpy(buf, ""); @@ -190,7 +190,7 @@ static ssize_t available_datatypes_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); unsigned int i = c->channel_id; strcpy(buf, ""); @@ -210,7 +210,7 @@ static ssize_t number_of_packet_buffers_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", @@ -221,7 +221,7 @@ static ssize_t number_of_stream_buffers_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", @@ -232,7 +232,7 @@ static ssize_t size_of_packet_buffer_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", @@ -243,7 +243,7 @@ static ssize_t size_of_stream_buffer_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", @@ -254,7 +254,7 @@ static ssize_t channel_starving_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); } @@ -263,7 +263,7 @@ static ssize_t set_number_of_buffers_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); } @@ -273,7 +273,7 @@ static ssize_t set_number_of_buffers_store(struct device *dev, const char *buf, size_t count) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); @@ -286,7 +286,7 @@ static ssize_t set_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); } @@ -296,7 +296,7 @@ static ssize_t set_buffer_size_store(struct device *dev, const char *buf, size_t count) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); if (ret) @@ -308,7 +308,7 @@ static ssize_t set_direction_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); if (c->cfg.direction & MOST_CH_TX) return snprintf(buf, PAGE_SIZE, "tx\n"); @@ -322,7 +322,7 @@ static ssize_t set_direction_store(struct device *dev, const char *buf, size_t count) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); if (!strcmp(buf, "dir_rx\n")) { c->cfg.direction = MOST_CH_RX; @@ -344,7 +344,7 @@ static ssize_t set_datatype_show(struct device *dev, char *buf) { int i; - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) @@ -359,7 +359,7 @@ static ssize_t set_datatype_store(struct device *dev, size_t count) { int i; - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { if (!strcmp(buf, ch_data_type[i].name)) { @@ -379,7 +379,7 @@ static ssize_t set_subbuffer_size_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); } @@ -389,7 +389,7 @@ static ssize_t set_subbuffer_size_store(struct device *dev, const char *buf, size_t count) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); if (ret) @@ -401,7 +401,7 @@ static ssize_t set_packets_per_xact_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); } @@ -411,7 +411,7 @@ static ssize_t set_packets_per_xact_store(struct device *dev, const char *buf, size_t count) { - struct most_c_obj *c = to_c_obj(dev); + struct most_channel *c = to_channel(dev); int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); if (ret) @@ -529,7 +529,7 @@ static const struct attribute_group *interface_attr_groups[] = { static ssize_t links_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_c_obj *c; + struct most_channel *c; struct most_inst_obj *i; struct most_aim *aim = to_most_aim(dev); int offs = 0; @@ -593,10 +593,9 @@ static int split_string(char *buf, char **a, char **b, char **c) * * This retrieves the pointer to a channel object. */ -static struct -most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) +static struct most_channel *get_channel_by_name(char *mdev, char *mdev_ch) { - struct most_c_obj *c, *tmp; + struct most_channel *c, *tmp; struct most_inst_obj *i, *i_tmp; int found = 0; @@ -620,8 +619,9 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) return c; } -static inline int link_channel_to_aim(struct most_c_obj *c, - struct most_aim *aim, char *aim_param) +static +inline int link_channel_to_aim(struct most_channel *c, struct most_aim *aim, + char *aim_param) { int ret; struct most_aim **aim_ptr; @@ -671,7 +671,7 @@ static ssize_t add_link_store(struct device *dev, const char *buf, size_t len) { - struct most_c_obj *c; + struct most_channel *c; struct most_aim *aim = to_most_aim(dev); char buffer[STRING_SIZE]; char *mdev; @@ -719,7 +719,7 @@ static ssize_t remove_link_store(struct device *dev, const char *buf, size_t len) { - struct most_c_obj *c; + struct most_channel *c; struct most_aim *aim = to_most_aim(dev); char buffer[STRING_SIZE]; char *mdev; @@ -796,14 +796,14 @@ static struct device_driver mostcore = { static inline void trash_mbo(struct mbo *mbo) { unsigned long flags; - struct most_c_obj *c = mbo->context; + struct most_channel *c = mbo->context; spin_lock_irqsave(&c->fifo_lock, flags); list_add(&mbo->list, &c->trash_fifo); spin_unlock_irqrestore(&c->fifo_lock, flags); } -static bool hdm_mbo_ready(struct most_c_obj *c) +static bool hdm_mbo_ready(struct most_channel *c) { bool empty; @@ -820,7 +820,7 @@ static bool hdm_mbo_ready(struct most_c_obj *c) static void nq_hdm_mbo(struct mbo *mbo) { unsigned long flags; - struct most_c_obj *c = mbo->context; + struct most_channel *c = mbo->context; spin_lock_irqsave(&c->fifo_lock, flags); list_add_tail(&mbo->list, &c->halt_fifo); @@ -830,7 +830,7 @@ static void nq_hdm_mbo(struct mbo *mbo) static int hdm_enqueue_thread(void *data) { - struct most_c_obj *c = data; + struct most_channel *c = data; struct mbo *mbo; int ret; typeof(c->iface->enqueue) enqueue = c->iface->enqueue; @@ -868,7 +868,7 @@ static int hdm_enqueue_thread(void *data) return 0; } -static int run_enqueue_thread(struct most_c_obj *c, int channel_id) +static int run_enqueue_thread(struct most_channel *c, int channel_id) { struct task_struct *task = kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d", @@ -895,7 +895,7 @@ static int run_enqueue_thread(struct most_c_obj *c, int channel_id) static void arm_mbo(struct mbo *mbo) { unsigned long flags; - struct most_c_obj *c; + struct most_channel *c; BUG_ON((!mbo) || (!mbo->context)); c = mbo->context; @@ -930,7 +930,7 @@ static void arm_mbo(struct mbo *mbo) * * Returns the number of allocated and enqueued MBOs. */ -static int arm_mbo_chain(struct most_c_obj *c, int dir, +static int arm_mbo_chain(struct most_channel *c, int dir, void (*compl)(struct mbo *)) { unsigned int i; @@ -998,7 +998,7 @@ EXPORT_SYMBOL_GPL(most_submit_mbo); */ static void most_write_completion(struct mbo *mbo) { - struct most_c_obj *c; + struct most_channel *c; BUG_ON((!mbo) || (!mbo->context)); @@ -1014,7 +1014,7 @@ static void most_write_completion(struct mbo *mbo) int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) { struct most_inst_obj *inst = iface->priv; - struct most_c_obj *c = inst->channel[id]; + struct most_channel *c = inst->channel[id]; unsigned long flags; int empty; @@ -1045,7 +1045,7 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id, struct most_aim *aim) { struct mbo *mbo; - struct most_c_obj *c; + struct most_channel *c; struct most_inst_obj *inst = iface->priv; unsigned long flags; int *num_buffers_ptr; @@ -1087,7 +1087,7 @@ EXPORT_SYMBOL_GPL(most_get_mbo); */ void most_put_mbo(struct mbo *mbo) { - struct most_c_obj *c = mbo->context; + struct most_channel *c = mbo->context; if (c->cfg.direction == MOST_CH_TX) { arm_mbo(mbo); @@ -1110,7 +1110,7 @@ EXPORT_SYMBOL_GPL(most_put_mbo); */ static void most_read_completion(struct mbo *mbo) { - struct most_c_obj *c = mbo->context; + struct most_channel *c = mbo->context; if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) { trash_mbo(mbo); @@ -1153,7 +1153,7 @@ int most_start_channel(struct most_interface *iface, int id, int num_buffer; int ret; struct most_inst_obj *inst = iface->priv; - struct most_c_obj *c = inst->channel[id]; + struct most_channel *c = inst->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1222,7 +1222,7 @@ int most_stop_channel(struct most_interface *iface, int id, struct most_aim *aim) { struct most_inst_obj *inst; - struct most_c_obj *c; + struct most_channel *c; if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { pr_err("Bad interface or index out of range\n"); @@ -1314,7 +1314,7 @@ EXPORT_SYMBOL_GPL(most_register_aim); */ int most_deregister_aim(struct most_aim *aim) { - struct most_c_obj *c, *tmp; + struct most_channel *c, *tmp; struct most_inst_obj *i, *i_tmp; if (!aim) { @@ -1362,7 +1362,7 @@ int most_register_interface(struct most_interface *iface) int id; char name[STRING_SIZE]; char channel_name[STRING_SIZE]; - struct most_c_obj *c; + struct most_channel *c; struct most_inst_obj *inst; if (!iface || !iface->enqueue || !iface->configure || @@ -1468,7 +1468,7 @@ EXPORT_SYMBOL_GPL(most_register_interface); void most_deregister_interface(struct most_interface *iface) { int i; - struct most_c_obj *c; + struct most_channel *c; struct most_inst_obj *inst; pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description); @@ -1507,7 +1507,7 @@ EXPORT_SYMBOL_GPL(most_deregister_interface); void most_stop_enqueue(struct most_interface *iface, int id) { struct most_inst_obj *inst = iface->priv; - struct most_c_obj *c = inst->channel[id]; + struct most_channel *c = inst->channel[id]; if (!c) return; @@ -1529,7 +1529,7 @@ EXPORT_SYMBOL_GPL(most_stop_enqueue); void most_resume_enqueue(struct most_interface *iface, int id) { struct most_inst_obj *inst = iface->priv; - struct most_c_obj *c = inst->channel[id]; + struct most_channel *c = inst->channel[id]; if (!c) return; -- cgit v1.2.3 From 7faeffec7f4f1a28db47dda9614010b3d7dcc48a Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:48 +0100 Subject: staging: most: core: rename struct most_c_aim_obj to pipe This patch replaces the confusing name of struct "most_c_aim_obj" with "pipe" to better express the function that is behind the structure. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 587e42f65a04..d6aee31f891f 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -31,7 +31,7 @@ static struct device core_dev; static struct ida mdev_id; static int dummy_num_buffers; -struct most_c_aim_obj { +struct pipe { struct most_aim *ptr; int refs; int num_buffers; @@ -56,8 +56,8 @@ struct most_channel { spinlock_t fifo_lock; struct list_head halt_fifo; struct list_head list; - struct most_c_aim_obj aim0; - struct most_c_aim_obj aim1; + struct pipe aim0; + struct pipe aim1; struct list_head trash_fifo; struct task_struct *hdm_enqueue_task; wait_queue_head_t hdm_fifo_wq; -- cgit v1.2.3 From ab868bad3c3cd649c78540d21852378ba0b957ba Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:49 +0100 Subject: staging: most: core: rename struct memeber This patch renames the member "ptr" of struct pipe to "aim". This is needed to increase the readability of the code. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 78 ++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index d6aee31f891f..404595a638b2 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -32,7 +32,7 @@ static struct ida mdev_id; static int dummy_num_buffers; struct pipe { - struct most_aim *ptr; + struct most_aim *aim; int refs; int num_buffers; }; @@ -536,7 +536,7 @@ static ssize_t links_show(struct device *dev, struct device_attribute *attr, list_for_each_entry(i, &instance_list, list) { list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.ptr == aim || c->aim1.ptr == aim) { + if (c->aim0.aim == aim || c->aim1.aim == aim) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s:%s\n", dev_name(&i->iface->dev), @@ -626,10 +626,10 @@ inline int link_channel_to_aim(struct most_channel *c, struct most_aim *aim, int ret; struct most_aim **aim_ptr; - if (!c->aim0.ptr) - aim_ptr = &c->aim0.ptr; - else if (!c->aim1.ptr) - aim_ptr = &c->aim1.ptr; + if (!c->aim0.aim) + aim_ptr = &c->aim0.aim; + else if (!c->aim1.aim) + aim_ptr = &c->aim1.aim; else return -ENOSPC; @@ -738,10 +738,10 @@ static ssize_t remove_link_store(struct device *dev, if (aim->disconnect_channel(c->iface, c->channel_id)) return -EIO; - if (c->aim0.ptr == aim) - c->aim0.ptr = NULL; - if (c->aim1.ptr == aim) - c->aim1.ptr = NULL; + if (c->aim0.aim == aim) + c->aim0.aim = NULL; + if (c->aim1.aim == aim) + c->aim1.aim = NULL; return len; } @@ -910,11 +910,11 @@ static void arm_mbo(struct mbo *mbo) list_add_tail(&mbo->list, &c->fifo); spin_unlock_irqrestore(&c->fifo_lock, flags); - if (c->aim0.refs && c->aim0.ptr->tx_completion) - c->aim0.ptr->tx_completion(c->iface, c->channel_id); + if (c->aim0.refs && c->aim0.aim->tx_completion) + c->aim0.aim->tx_completion(c->iface, c->channel_id); - if (c->aim1.refs && c->aim1.ptr->tx_completion) - c->aim1.ptr->tx_completion(c->iface, c->channel_id); + if (c->aim1.refs && c->aim1.aim->tx_completion) + c->aim1.aim->tx_completion(c->iface, c->channel_id); } /** @@ -1022,8 +1022,8 @@ int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) return -EINVAL; if (c->aim0.refs && c->aim1.refs && - ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || - (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) + ((aim == c->aim0.aim && c->aim0.num_buffers <= 0) || + (aim == c->aim1.aim && c->aim1.num_buffers <= 0))) return 0; spin_lock_irqsave(&c->fifo_lock, flags); @@ -1055,13 +1055,13 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id, return NULL; if (c->aim0.refs && c->aim1.refs && - ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || - (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) + ((aim == c->aim0.aim && c->aim0.num_buffers <= 0) || + (aim == c->aim1.aim && c->aim1.num_buffers <= 0))) return NULL; - if (aim == c->aim0.ptr) + if (aim == c->aim0.aim) num_buffers_ptr = &c->aim0.num_buffers; - else if (aim == c->aim1.ptr) + else if (aim == c->aim1.aim) num_buffers_ptr = &c->aim1.num_buffers; else num_buffers_ptr = &dummy_num_buffers; @@ -1126,12 +1126,12 @@ static void most_read_completion(struct mbo *mbo) if (atomic_sub_and_test(1, &c->mbo_nq_level)) c->is_starving = 1; - if (c->aim0.refs && c->aim0.ptr->rx_completion && - c->aim0.ptr->rx_completion(mbo) == 0) + if (c->aim0.refs && c->aim0.aim->rx_completion && + c->aim0.aim->rx_completion(mbo) == 0) return; - if (c->aim1.refs && c->aim1.ptr->rx_completion && - c->aim1.ptr->rx_completion(mbo) == 0) + if (c->aim1.refs && c->aim1.aim->rx_completion && + c->aim1.aim->rx_completion(mbo) == 0) return; most_put_mbo(mbo); @@ -1199,9 +1199,9 @@ int most_start_channel(struct most_interface *iface, int id, atomic_set(&c->mbo_ref, num_buffer); out: - if (aim == c->aim0.ptr) + if (aim == c->aim0.aim) c->aim0.refs++; - if (aim == c->aim1.ptr) + if (aim == c->aim1.aim) c->aim1.refs++; mutex_unlock(&c->start_mutex); return 0; @@ -1266,9 +1266,9 @@ int most_stop_channel(struct most_interface *iface, int id, c->is_poisoned = false; out: - if (aim == c->aim0.ptr) + if (aim == c->aim0.aim) c->aim0.refs--; - if (aim == c->aim1.ptr) + if (aim == c->aim1.aim) c->aim1.refs--; mutex_unlock(&c->start_mutex); return 0; @@ -1324,13 +1324,13 @@ int most_deregister_aim(struct most_aim *aim) list_for_each_entry_safe(i, i_tmp, &instance_list, list) { list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (c->aim0.ptr == aim || c->aim1.ptr == aim) + if (c->aim0.aim == aim || c->aim1.aim == aim) aim->disconnect_channel( c->iface, c->channel_id); - if (c->aim0.ptr == aim) - c->aim0.ptr = NULL; - if (c->aim1.ptr == aim) - c->aim1.ptr = NULL; + if (c->aim0.aim == aim) + c->aim0.aim = NULL; + if (c->aim1.aim == aim) + c->aim1.aim = NULL; } } device_unregister(&aim->dev); @@ -1475,14 +1475,14 @@ void most_deregister_interface(struct most_interface *iface) inst = iface->priv; for (i = 0; i < iface->num_channels; i++) { c = inst->channel[i]; - if (c->aim0.ptr) - c->aim0.ptr->disconnect_channel(c->iface, + if (c->aim0.aim) + c->aim0.aim->disconnect_channel(c->iface, c->channel_id); - if (c->aim1.ptr) - c->aim1.ptr->disconnect_channel(c->iface, + if (c->aim1.aim) + c->aim1.aim->disconnect_channel(c->iface, c->channel_id); - c->aim0.ptr = NULL; - c->aim1.ptr = NULL; + c->aim0.aim = NULL; + c->aim1.aim = NULL; list_del(&c->list); device_unregister(&c->dev); kfree(c); -- cgit v1.2.3 From f898f989550817b917a9ba812a79fdbac00cb177 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:50 +0100 Subject: staging: most: core: rename members aim* of struct most_channel This patch renames the struct members "aim0" and "aim0" to "pipe0" and "pipe1". It is needed to have a conclusive nomenclature of the struct and its instances. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 104 ++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 404595a638b2..d7a28035f4a2 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -56,8 +56,8 @@ struct most_channel { spinlock_t fifo_lock; struct list_head halt_fifo; struct list_head list; - struct pipe aim0; - struct pipe aim1; + struct pipe pipe0; + struct pipe pipe1; struct list_head trash_fifo; struct task_struct *hdm_enqueue_task; wait_queue_head_t hdm_fifo_wq; @@ -536,7 +536,7 @@ static ssize_t links_show(struct device *dev, struct device_attribute *attr, list_for_each_entry(i, &instance_list, list) { list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.aim == aim || c->aim1.aim == aim) { + if (c->pipe0.aim == aim || c->pipe1.aim == aim) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s:%s\n", dev_name(&i->iface->dev), @@ -626,10 +626,10 @@ inline int link_channel_to_aim(struct most_channel *c, struct most_aim *aim, int ret; struct most_aim **aim_ptr; - if (!c->aim0.aim) - aim_ptr = &c->aim0.aim; - else if (!c->aim1.aim) - aim_ptr = &c->aim1.aim; + if (!c->pipe0.aim) + aim_ptr = &c->pipe0.aim; + else if (!c->pipe1.aim) + aim_ptr = &c->pipe1.aim; else return -ENOSPC; @@ -738,10 +738,10 @@ static ssize_t remove_link_store(struct device *dev, if (aim->disconnect_channel(c->iface, c->channel_id)) return -EIO; - if (c->aim0.aim == aim) - c->aim0.aim = NULL; - if (c->aim1.aim == aim) - c->aim1.aim = NULL; + if (c->pipe0.aim == aim) + c->pipe0.aim = NULL; + if (c->pipe1.aim == aim) + c->pipe1.aim = NULL; return len; } @@ -910,11 +910,11 @@ static void arm_mbo(struct mbo *mbo) list_add_tail(&mbo->list, &c->fifo); spin_unlock_irqrestore(&c->fifo_lock, flags); - if (c->aim0.refs && c->aim0.aim->tx_completion) - c->aim0.aim->tx_completion(c->iface, c->channel_id); + if (c->pipe0.refs && c->pipe0.aim->tx_completion) + c->pipe0.aim->tx_completion(c->iface, c->channel_id); - if (c->aim1.refs && c->aim1.aim->tx_completion) - c->aim1.aim->tx_completion(c->iface, c->channel_id); + if (c->pipe1.refs && c->pipe1.aim->tx_completion) + c->pipe1.aim->tx_completion(c->iface, c->channel_id); } /** @@ -1021,9 +1021,9 @@ int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) if (unlikely(!c)) return -EINVAL; - if (c->aim0.refs && c->aim1.refs && - ((aim == c->aim0.aim && c->aim0.num_buffers <= 0) || - (aim == c->aim1.aim && c->aim1.num_buffers <= 0))) + if (c->pipe0.refs && c->pipe1.refs && + ((aim == c->pipe0.aim && c->pipe0.num_buffers <= 0) || + (aim == c->pipe1.aim && c->pipe1.num_buffers <= 0))) return 0; spin_lock_irqsave(&c->fifo_lock, flags); @@ -1054,15 +1054,15 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id, if (unlikely(!c)) return NULL; - if (c->aim0.refs && c->aim1.refs && - ((aim == c->aim0.aim && c->aim0.num_buffers <= 0) || - (aim == c->aim1.aim && c->aim1.num_buffers <= 0))) + if (c->pipe0.refs && c->pipe1.refs && + ((aim == c->pipe0.aim && c->pipe0.num_buffers <= 0) || + (aim == c->pipe1.aim && c->pipe1.num_buffers <= 0))) return NULL; - if (aim == c->aim0.aim) - num_buffers_ptr = &c->aim0.num_buffers; - else if (aim == c->aim1.aim) - num_buffers_ptr = &c->aim1.num_buffers; + if (aim == c->pipe0.aim) + num_buffers_ptr = &c->pipe0.num_buffers; + else if (aim == c->pipe1.aim) + num_buffers_ptr = &c->pipe1.num_buffers; else num_buffers_ptr = &dummy_num_buffers; @@ -1126,12 +1126,12 @@ static void most_read_completion(struct mbo *mbo) if (atomic_sub_and_test(1, &c->mbo_nq_level)) c->is_starving = 1; - if (c->aim0.refs && c->aim0.aim->rx_completion && - c->aim0.aim->rx_completion(mbo) == 0) + if (c->pipe0.refs && c->pipe0.aim->rx_completion && + c->pipe0.aim->rx_completion(mbo) == 0) return; - if (c->aim1.refs && c->aim1.aim->rx_completion && - c->aim1.aim->rx_completion(mbo) == 0) + if (c->pipe1.refs && c->pipe1.aim->rx_completion && + c->pipe1.aim->rx_completion(mbo) == 0) return; most_put_mbo(mbo); @@ -1159,7 +1159,7 @@ int most_start_channel(struct most_interface *iface, int id, return -EINVAL; mutex_lock(&c->start_mutex); - if (c->aim0.refs + c->aim1.refs > 0) + if (c->pipe0.refs + c->pipe1.refs > 0) goto out; /* already started by other aim */ if (!try_module_get(iface->mod)) { @@ -1194,15 +1194,15 @@ int most_start_channel(struct most_interface *iface, int id, goto error; c->is_starving = 0; - c->aim0.num_buffers = c->cfg.num_buffers / 2; - c->aim1.num_buffers = c->cfg.num_buffers - c->aim0.num_buffers; + c->pipe0.num_buffers = c->cfg.num_buffers / 2; + c->pipe1.num_buffers = c->cfg.num_buffers - c->pipe0.num_buffers; atomic_set(&c->mbo_ref, num_buffer); out: - if (aim == c->aim0.aim) - c->aim0.refs++; - if (aim == c->aim1.aim) - c->aim1.refs++; + if (aim == c->pipe0.aim) + c->pipe0.refs++; + if (aim == c->pipe1.aim) + c->pipe1.refs++; mutex_unlock(&c->start_mutex); return 0; @@ -1234,7 +1234,7 @@ int most_stop_channel(struct most_interface *iface, int id, return -EINVAL; mutex_lock(&c->start_mutex); - if (c->aim0.refs + c->aim1.refs >= 2) + if (c->pipe0.refs + c->pipe1.refs >= 2) goto out; if (c->hdm_enqueue_task) @@ -1266,10 +1266,10 @@ int most_stop_channel(struct most_interface *iface, int id, c->is_poisoned = false; out: - if (aim == c->aim0.aim) - c->aim0.refs--; - if (aim == c->aim1.aim) - c->aim1.refs--; + if (aim == c->pipe0.aim) + c->pipe0.refs--; + if (aim == c->pipe1.aim) + c->pipe1.refs--; mutex_unlock(&c->start_mutex); return 0; } @@ -1324,13 +1324,13 @@ int most_deregister_aim(struct most_aim *aim) list_for_each_entry_safe(i, i_tmp, &instance_list, list) { list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (c->aim0.aim == aim || c->aim1.aim == aim) + if (c->pipe0.aim == aim || c->pipe1.aim == aim) aim->disconnect_channel( c->iface, c->channel_id); - if (c->aim0.aim == aim) - c->aim0.aim = NULL; - if (c->aim1.aim == aim) - c->aim1.aim = NULL; + if (c->pipe0.aim == aim) + c->pipe0.aim = NULL; + if (c->pipe1.aim == aim) + c->pipe1.aim = NULL; } } device_unregister(&aim->dev); @@ -1475,14 +1475,14 @@ void most_deregister_interface(struct most_interface *iface) inst = iface->priv; for (i = 0; i < iface->num_channels; i++) { c = inst->channel[i]; - if (c->aim0.aim) - c->aim0.aim->disconnect_channel(c->iface, + if (c->pipe0.aim) + c->pipe0.aim->disconnect_channel(c->iface, c->channel_id); - if (c->aim1.aim) - c->aim1.aim->disconnect_channel(c->iface, + if (c->pipe1.aim) + c->pipe1.aim->disconnect_channel(c->iface, c->channel_id); - c->aim0.aim = NULL; - c->aim1.aim = NULL; + c->pipe0.aim = NULL; + c->pipe1.aim = NULL; list_del(&c->list); device_unregister(&c->dev); kfree(c); -- cgit v1.2.3 From 14ae5f0383924e502139a2a6e8cbfadc985d3218 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:51 +0100 Subject: staging: most: core: use structure to pack driver specific data This patch introduces the structure "mostcore" to bundle core specific data structures. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 73 +++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index d7a28035f4a2..779464a58674 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -26,11 +26,19 @@ #define MAX_CHANNELS 64 #define STRING_SIZE 80 -static struct class *most_class; -static struct device core_dev; static struct ida mdev_id; static int dummy_num_buffers; +static struct mostcore { + struct device dev; + struct device_driver drv; + struct bus_type bus; + struct class *class; + struct list_head mod_list; +} mc; + +#define to_driver(d) container_of(d, struct mostcore, drv); + struct pipe { struct most_aim *aim; int refs; @@ -777,22 +785,6 @@ int most_match(struct device *dev, struct device_driver *drv) return 1; } -/** - * Instantiation of the MOST bus - */ -static struct bus_type most_bus = { - .name = "most", - .match = most_match, -}; - -/** - * Instantiation of the core driver - */ -static struct device_driver mostcore = { - .name = "mostcore", - .bus = &most_bus, -}; - static inline void trash_mbo(struct mbo *mbo) { unsigned long flags; @@ -1293,8 +1285,8 @@ int most_register_aim(struct most_aim *aim) return -EINVAL; } aim->dev.init_name = aim->name; - aim->dev.bus = &most_bus; - aim->dev.parent = &core_dev; + aim->dev.bus = &mc.bus; + aim->dev.parent = &mc.dev; aim->dev.groups = aim_attr_groups; aim->dev.release = release_aim; ret = device_register(&aim->dev); @@ -1391,8 +1383,8 @@ int most_register_interface(struct most_interface *iface) list_add_tail(&inst->list, &instance_list); snprintf(name, STRING_SIZE, "mdev%d", id); iface->dev.init_name = name; - iface->dev.bus = &most_bus; - iface->dev.parent = &core_dev; + iface->dev.bus = &mc.bus; + iface->dev.parent = &mc.dev; iface->dev.groups = interface_attr_groups; iface->dev.release = release_interface; if (device_register(&iface->dev)) { @@ -1555,28 +1547,31 @@ static int __init most_init(void) INIT_LIST_HEAD(&instance_list); ida_init(&mdev_id); - err = bus_register(&most_bus); + mc.bus.name = "most", + mc.bus.match = most_match, + mc.drv.name = "most_core", + mc.drv.bus = &mc.bus, + + err = bus_register(&mc.bus); if (err) { pr_info("Cannot register most bus\n"); return err; } - - most_class = class_create(THIS_MODULE, "most"); - if (IS_ERR(most_class)) { + mc.class = class_create(THIS_MODULE, "most"); + if (IS_ERR(mc.class)) { pr_info("No udev support.\n"); - err = PTR_ERR(most_class); + err = PTR_ERR(mc.class); goto exit_bus; } - err = driver_register(&mostcore); + err = driver_register(&mc.drv); if (err) { pr_info("Cannot register core driver\n"); goto exit_class; } - - core_dev.init_name = "most_bus"; - core_dev.release = release_most_sub; - if (device_register(&core_dev)) { + mc.dev.init_name = "most_bus"; + mc.dev.release = release_most_sub; + if (device_register(&mc.dev)) { err = -ENOMEM; goto exit_driver; } @@ -1584,21 +1579,21 @@ static int __init most_init(void) return 0; exit_driver: - driver_unregister(&mostcore); + driver_unregister(&mc.drv); exit_class: - class_destroy(most_class); + class_destroy(mc.class); exit_bus: - bus_unregister(&most_bus); + bus_unregister(&mc.bus); return err; } static void __exit most_exit(void) { pr_info("exit core module\n"); - device_unregister(&core_dev); - driver_unregister(&mostcore); - class_destroy(most_class); - bus_unregister(&most_bus); + device_unregister(&mc.dev); + driver_unregister(&mc.drv); + class_destroy(mc.class); + bus_unregister(&mc.bus); ida_destroy(&mdev_id); } -- cgit v1.2.3 From a6404e6e5a0e2933e10be3e42311ee6b65b821fc Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:52 +0100 Subject: staging: most: core: track aim modules with linked list The core needs to know what modules are registered. This patch makes the core keep track of the registered modules. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 6 ++++-- drivers/staging/most/core.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 779464a58674..41a35382a9e3 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -1294,8 +1294,8 @@ int most_register_aim(struct most_aim *aim) pr_err("registering device %s failed\n", aim->name); return ret; } - pr_info("registered new application interfacing module %s\n", - aim->name); + list_add_tail(&aim->list, &mc.mod_list); + pr_info("registered new application interfacing module %s\n", aim->name); return 0; } EXPORT_SYMBOL_GPL(most_register_aim); @@ -1326,6 +1326,7 @@ int most_deregister_aim(struct most_aim *aim) } } device_unregister(&aim->dev); + list_del(&aim->list); pr_info("deregistering application interfacing module %s\n", aim->name); return 0; } @@ -1545,6 +1546,7 @@ static int __init most_init(void) pr_info("init()\n"); INIT_LIST_HEAD(&instance_list); + INIT_LIST_HEAD(&mc.mod_list); ida_init(&mdev_id); mc.bus.name = "most", diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 29595d9ef7ed..845e1d63d8fc 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -263,6 +263,7 @@ struct most_interface { */ struct most_aim { struct device dev; + struct list_head list; const char *name; int (*probe_channel)(struct most_interface *iface, int channel_idx, struct most_channel_config *cfg, char *name); -- cgit v1.2.3 From bdafb7e83b0229379b11bfdd36ccfb3adf447666 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:53 +0100 Subject: staging: most: core: fix sysfs attribute management This patch creates a new attribute group to manage the attributes of a registered aim module in sysfs and changes the show and store functions accordingly. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 109 +++++++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 41a35382a9e3..37b9703504cf 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -534,28 +534,57 @@ static const struct attribute_group *interface_attr_groups[] = { /* ___ ___ * ___A I M___ */ -static ssize_t links_show(struct device *dev, struct device_attribute *attr, - char *buf) +static struct most_aim *match_module(char *name) +{ + struct most_aim *aim; + + list_for_each_entry(aim, &mc.mod_list, list) { + if (!strcmp(aim->name, name)) + return aim; + } + return NULL; +} + +static ssize_t links_show(struct device_driver *drv, char *buf) { struct most_channel *c; struct most_inst_obj *i; - struct most_aim *aim = to_most_aim(dev); int offs = 0; list_for_each_entry(i, &instance_list, list) { list_for_each_entry(c, &i->channel_list, list) { - if (c->pipe0.aim == aim || c->pipe1.aim == aim) { - offs += snprintf(buf + offs, PAGE_SIZE - offs, - "%s:%s\n", + if (c->pipe0.aim) { + offs += snprintf(buf + offs, + PAGE_SIZE - offs, + "%s:%s:%s\n", + c->pipe0.aim->name, + dev_name(&i->iface->dev), + dev_name(&c->dev)); + } + if (c->pipe1.aim) { + offs += snprintf(buf + offs, + PAGE_SIZE - offs, + "%s:%s:%s\n", + c->pipe1.aim->name, dev_name(&i->iface->dev), dev_name(&c->dev)); } } } - return offs; } +static ssize_t modules_show(struct device_driver *drv, char *buf) +{ + struct most_aim *aim; + int offs = 0; + + list_for_each_entry(aim, &mc.mod_list, list) { + offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s\n", + aim->name); + } + return offs; +} /** * split_string - parses and changes string in the buffer buf and * splits it into two mandatory and one optional substrings. @@ -578,7 +607,7 @@ static ssize_t links_show(struct device *dev, struct device_attribute *attr, * Input: "mdev1:ep81" * Output: *a -> "mdev1", *b -> "ep81", *c == NULL */ -static int split_string(char *buf, char **a, char **b, char **c) +static int split_string(char *buf, char **a, char **b, char **c, char **d) { *a = strsep(&buf, ":"); if (!*a) @@ -588,8 +617,12 @@ static int split_string(char *buf, char **a, char **b, char **c) if (!*b) return -EIO; - if (c) - *c = strsep(&buf, ":\n"); + *c = strsep(&buf, ":\n"); + if (!*c) + return -EIO; + + if (d) + *d = strsep(&buf, ":\n"); return 0; } @@ -674,38 +707,38 @@ inline int link_channel_to_aim(struct most_channel *c, struct most_aim *aim, * (1) would create the device node /dev/my_rxchannel * (2) would create the device node /dev/mdev1-ep81 */ -static ssize_t add_link_store(struct device *dev, - struct device_attribute *attr, +static ssize_t add_link_store(struct device_driver *drv, const char *buf, size_t len) { struct most_channel *c; - struct most_aim *aim = to_most_aim(dev); + struct most_aim *aim; char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; - char *mdev_devnod; + char *aim_name; + char *aim_param; char devnod_buf[STRING_SIZE]; int ret; size_t max_len = min_t(size_t, len + 1, STRING_SIZE); strlcpy(buffer, buf, max_len); - ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod); + ret = split_string(buffer, &mdev, &mdev_ch, &aim_name, &aim_param); if (ret) return ret; - - if (!mdev_devnod || *mdev_devnod == 0) { + aim = match_module(aim_name); + if (!aim_param || *aim_param == 0) { snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, mdev_ch); - mdev_devnod = devnod_buf; + aim_param = devnod_buf; } c = get_channel_by_name(mdev, mdev_ch); if (IS_ERR(c)) return -ENODEV; - ret = link_channel_to_aim(c, aim, mdev_devnod); + ret = link_channel_to_aim(c, aim, aim_param); if (ret) return ret; @@ -722,24 +755,24 @@ static ssize_t add_link_store(struct device *dev, * Example: * echo "mdev0:ep81" >remove_link */ -static ssize_t remove_link_store(struct device *dev, - struct device_attribute *attr, +static ssize_t remove_link_store(struct device_driver *drv, const char *buf, size_t len) { struct most_channel *c; - struct most_aim *aim = to_most_aim(dev); + struct most_aim *aim; char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; + char *aim_name; int ret; size_t max_len = min_t(size_t, len + 1, STRING_SIZE); strlcpy(buffer, buf, max_len); - ret = split_string(buffer, &mdev, &mdev_ch, NULL); + ret = split_string(buffer, &mdev, &mdev_ch, &aim_name, NULL); if (ret) return ret; - + aim = match_module(aim_name); c = get_channel_by_name(mdev, mdev_ch); if (IS_ERR(c)) return -ENODEV; @@ -753,23 +786,27 @@ static ssize_t remove_link_store(struct device *dev, return len; } -static DEVICE_ATTR_RO(links); -static DEVICE_ATTR_WO(add_link); -static DEVICE_ATTR_WO(remove_link); +#define DRV_ATTR(_name) (&driver_attr_##_name.attr) + +static DRIVER_ATTR_RO(links); +static DRIVER_ATTR_RO(modules); +static DRIVER_ATTR_WO(add_link); +static DRIVER_ATTR_WO(remove_link); -static struct attribute *aim_attrs[] = { - DEV_ATTR(links), - DEV_ATTR(add_link), - DEV_ATTR(remove_link), +static struct attribute *module_attrs[] = { + DRV_ATTR(links), + DRV_ATTR(modules), + DRV_ATTR(add_link), + DRV_ATTR(remove_link), NULL, }; -static struct attribute_group aim_attr_group = { - .attrs = aim_attrs, +static struct attribute_group module_attr_group = { + .attrs = module_attrs, }; -static const struct attribute_group *aim_attr_groups[] = { - &aim_attr_group, +static const struct attribute_group *module_attr_groups[] = { + &module_attr_group, NULL, }; @@ -1287,7 +1324,6 @@ int most_register_aim(struct most_aim *aim) aim->dev.init_name = aim->name; aim->dev.bus = &mc.bus; aim->dev.parent = &mc.dev; - aim->dev.groups = aim_attr_groups; aim->dev.release = release_aim; ret = device_register(&aim->dev); if (ret) { @@ -1553,6 +1589,7 @@ static int __init most_init(void) mc.bus.match = most_match, mc.drv.name = "most_core", mc.drv.bus = &mc.bus, + mc.drv.groups = module_attr_groups; err = bus_register(&mc.bus); if (err) { -- cgit v1.2.3 From 3d6eb1d238ee981d2881c8478ed5bd3e948c1eb0 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:54 +0100 Subject: staging: most: core: remove struct device This patch takes out the struct device of struct most_aim, because it is not needed. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 17 ----------------- drivers/staging/most/core.h | 1 - 2 files changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 37b9703504cf..076d4f2756ff 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -1304,32 +1304,16 @@ out: } EXPORT_SYMBOL_GPL(most_stop_channel); -void release_aim(struct device *dev) -{ - pr_info("releasing aim %s\n", dev_name(dev)); -} - /** * most_register_aim - registers an AIM (driver) with the core * @aim: instance of AIM to be registered */ int most_register_aim(struct most_aim *aim) { - int ret; - if (!aim) { pr_err("Bad driver\n"); return -EINVAL; } - aim->dev.init_name = aim->name; - aim->dev.bus = &mc.bus; - aim->dev.parent = &mc.dev; - aim->dev.release = release_aim; - ret = device_register(&aim->dev); - if (ret) { - pr_err("registering device %s failed\n", aim->name); - return ret; - } list_add_tail(&aim->list, &mc.mod_list); pr_info("registered new application interfacing module %s\n", aim->name); return 0; @@ -1361,7 +1345,6 @@ int most_deregister_aim(struct most_aim *aim) c->pipe1.aim = NULL; } } - device_unregister(&aim->dev); list_del(&aim->list); pr_info("deregistering application interfacing module %s\n", aim->name); return 0; diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 845e1d63d8fc..2f61a69afb77 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -262,7 +262,6 @@ struct most_interface { * @context: context pointer to be used by mostcore */ struct most_aim { - struct device dev; struct list_head list; const char *name; int (*probe_channel)(struct most_interface *iface, int channel_idx, -- cgit v1.2.3 From ec0c2f62ab8cebde7dbe8a3a4780dee280f1a98c Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:55 +0100 Subject: staging: most: core: rename function The core module used to have two functions to find a certain channel. One by name and one by interface. Since no channel is searched by its interface name anymore the by_name suffix is rendered redundant. This patch renames the function accordingly. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 076d4f2756ff..9ab480914f95 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -628,13 +628,13 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d) } /** - * get_channel_by_name - get pointer to channel object + * get_channel - get pointer to channel object * @mdev: name of the device instance * @mdev_ch: name of the respective channel * * This retrieves the pointer to a channel object. */ -static struct most_channel *get_channel_by_name(char *mdev, char *mdev_ch) +static struct most_channel *get_channel(char *mdev, char *mdev_ch) { struct most_channel *c, *tmp; struct most_inst_obj *i, *i_tmp; @@ -734,7 +734,7 @@ static ssize_t add_link_store(struct device_driver *drv, aim_param = devnod_buf; } - c = get_channel_by_name(mdev, mdev_ch); + c = get_channel(mdev, mdev_ch); if (IS_ERR(c)) return -ENODEV; @@ -773,7 +773,7 @@ static ssize_t remove_link_store(struct device_driver *drv, if (ret) return ret; aim = match_module(aim_name); - c = get_channel_by_name(mdev, mdev_ch); + c = get_channel(mdev, mdev_ch); if (IS_ERR(c)) return -ENODEV; -- cgit v1.2.3 From 9136fccf38a7aaf173c42365664c2fce1bcc67a1 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:56 +0100 Subject: staging: most: core: replace struct most_inst_obj This patch introduces struct interface_private as a replacement for the struct most_inst_obj. This structure holds private data that is only needed by the core module and will be accessed by a pointer from within the most_interface structure. As a result of this replacement the bus helper functions can be used to search for devices. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 200 +++++++++++++++++++++----------------------- drivers/staging/most/core.h | 2 + 2 files changed, 99 insertions(+), 103 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 9ab480914f95..02772ce207f8 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -56,7 +56,6 @@ struct most_channel { struct mutex nq_mutex; /* nq thread synchronization */ int is_starving; struct most_interface *iface; - struct most_inst_obj *inst; struct most_channel_config cfg; bool keep_mbo; bool enqueue_halt; @@ -73,12 +72,11 @@ struct most_channel { #define to_channel(d) container_of(d, struct most_channel, dev) -struct most_inst_obj { +struct interface_private { int dev_id; - struct most_interface *iface; - struct list_head channel_list; + char name[STRING_SIZE]; struct most_channel *channel[MAX_CHANNELS]; - struct list_head list; + struct list_head channel_list; }; static const struct { @@ -472,9 +470,6 @@ static const struct attribute_group *channel_attr_groups[] = { /* ___ ___ * ___I N S T A N C E___ */ - -static struct list_head instance_list; - static ssize_t description_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -545,33 +540,38 @@ static struct most_aim *match_module(char *name) return NULL; } -static ssize_t links_show(struct device_driver *drv, char *buf) +int print_links(struct device *dev, void *data) { - struct most_channel *c; - struct most_inst_obj *i; int offs = 0; + char *buf = data; + struct most_channel *c; + struct most_interface *iface = to_most_interface(dev); - list_for_each_entry(i, &instance_list, list) { - list_for_each_entry(c, &i->channel_list, list) { - if (c->pipe0.aim) { - offs += snprintf(buf + offs, - PAGE_SIZE - offs, - "%s:%s:%s\n", - c->pipe0.aim->name, - dev_name(&i->iface->dev), - dev_name(&c->dev)); - } - if (c->pipe1.aim) { - offs += snprintf(buf + offs, - PAGE_SIZE - offs, - "%s:%s:%s\n", - c->pipe1.aim->name, - dev_name(&i->iface->dev), - dev_name(&c->dev)); - } + list_for_each_entry(c, &iface->p->channel_list, list) { + if (c->pipe0.aim) { + offs += snprintf(buf + offs, + PAGE_SIZE - offs, + "%s:%s:%s\n", + c->pipe0.aim->name, + dev_name(&iface->dev), + dev_name(&c->dev)); + } + if (c->pipe1.aim) { + offs += snprintf(buf + offs, + PAGE_SIZE - offs, + "%s:%s:%s\n", + c->pipe1.aim->name, + dev_name(&iface->dev), + dev_name(&c->dev)); } } - return offs; + return 0; +} + +static ssize_t links_show(struct device_driver *drv, char *buf) +{ + bus_for_each_dev(&mc.bus, NULL, buf, print_links); + return strlen(buf); } static ssize_t modules_show(struct device_driver *drv, char *buf) @@ -627,6 +627,13 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d) return 0; } +static int match_bus_dev(struct device *dev, void *data) +{ + char *mdev_name = data; + + return !strcmp(dev_name(dev), mdev_name); +} + /** * get_channel - get pointer to channel object * @mdev: name of the device instance @@ -636,28 +643,19 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d) */ static struct most_channel *get_channel(char *mdev, char *mdev_ch) { + struct device *dev = NULL; + struct most_interface *iface; struct most_channel *c, *tmp; - struct most_inst_obj *i, *i_tmp; - int found = 0; - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - if (!strcmp(dev_name(&i->iface->dev), mdev)) { - found++; - break; - } - } - if (unlikely(!found)) - return ERR_PTR(-EIO); - - list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (!strcmp(dev_name(&c->dev), mdev_ch)) { - found++; - break; - } + dev = bus_find_device(&mc.bus, NULL, mdev, match_bus_dev); + if (!dev) + return NULL; + iface = to_most_interface(dev); + list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { + if (!strcmp(dev_name(&c->dev), mdev_ch)) + return c; } - if (unlikely(found < 2)) - return ERR_PTR(-EIO); - return c; + return NULL; } static @@ -735,7 +733,7 @@ static ssize_t add_link_store(struct device_driver *drv, } c = get_channel(mdev, mdev_ch); - if (IS_ERR(c)) + if (!c) return -ENODEV; ret = link_channel_to_aim(c, aim, aim_param); @@ -774,7 +772,7 @@ static ssize_t remove_link_store(struct device_driver *drv, return ret; aim = match_module(aim_name); c = get_channel(mdev, mdev_ch); - if (IS_ERR(c)) + if (!c) return -ENODEV; if (aim->disconnect_channel(c->iface, c->channel_id)) @@ -1042,8 +1040,7 @@ static void most_write_completion(struct mbo *mbo) int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) { - struct most_inst_obj *inst = iface->priv; - struct most_channel *c = inst->channel[id]; + struct most_channel *c = iface->p->channel[id]; unsigned long flags; int empty; @@ -1075,11 +1072,10 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id, { struct mbo *mbo; struct most_channel *c; - struct most_inst_obj *inst = iface->priv; unsigned long flags; int *num_buffers_ptr; - c = inst->channel[id]; + c = iface->p->channel[id]; if (unlikely(!c)) return NULL; @@ -1181,8 +1177,7 @@ int most_start_channel(struct most_interface *iface, int id, { int num_buffer; int ret; - struct most_inst_obj *inst = iface->priv; - struct most_channel *c = inst->channel[id]; + struct most_channel *c = iface->p->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1250,15 +1245,13 @@ EXPORT_SYMBOL_GPL(most_start_channel); int most_stop_channel(struct most_interface *iface, int id, struct most_aim *aim) { - struct most_inst_obj *inst; struct most_channel *c; if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { pr_err("Bad interface or index out of range\n"); return -EINVAL; } - inst = iface->priv; - c = inst->channel[id]; + c = iface->p->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1320,33 +1313,38 @@ int most_register_aim(struct most_aim *aim) } EXPORT_SYMBOL_GPL(most_register_aim); +static int disconnect_channels(struct device *dev, void *data) +{ + struct most_interface *iface; + struct most_channel *c, *tmp; + struct most_aim *aim = data; + + iface = to_most_interface(dev); + list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { + if (c->pipe0.aim == aim || c->pipe1.aim == aim) + aim->disconnect_channel(c->iface, c->channel_id); + if (c->pipe0.aim == aim) + c->pipe0.aim = NULL; + if (c->pipe1.aim == aim) + c->pipe1.aim = NULL; + } + return 0; +} + /** * most_deregister_aim - deregisters an AIM (driver) with the core * @aim: AIM to be removed */ int most_deregister_aim(struct most_aim *aim) { - struct most_channel *c, *tmp; - struct most_inst_obj *i, *i_tmp; - if (!aim) { pr_err("Bad driver\n"); return -EINVAL; } - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (c->pipe0.aim == aim || c->pipe1.aim == aim) - aim->disconnect_channel( - c->iface, c->channel_id); - if (c->pipe0.aim == aim) - c->pipe0.aim = NULL; - if (c->pipe1.aim == aim) - c->pipe1.aim = NULL; - } - } + bus_for_each_dev(&mc.bus, NULL, aim, disconnect_channels); list_del(&aim->list); - pr_info("deregistering application interfacing module %s\n", aim->name); + pr_info("deregistering module %s\n", aim->name); return 0; } EXPORT_SYMBOL_GPL(most_deregister_aim); @@ -1372,10 +1370,8 @@ int most_register_interface(struct most_interface *iface) { unsigned int i; int id; - char name[STRING_SIZE]; char channel_name[STRING_SIZE]; struct most_channel *c; - struct most_inst_obj *inst; if (!iface || !iface->enqueue || !iface->configure || !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { @@ -1389,27 +1385,24 @@ int most_register_interface(struct most_interface *iface) return id; } - inst = kzalloc(sizeof(*inst), GFP_KERNEL); - if (!inst) { + iface->p = kzalloc(sizeof(*iface->p), GFP_KERNEL); + if (!iface->p) { pr_info("Failed to allocate interface instance\n"); ida_simple_remove(&mdev_id, id); return -ENOMEM; } - iface->priv = inst; - INIT_LIST_HEAD(&inst->channel_list); - inst->iface = iface; - inst->dev_id = id; - list_add_tail(&inst->list, &instance_list); - snprintf(name, STRING_SIZE, "mdev%d", id); - iface->dev.init_name = name; + INIT_LIST_HEAD(&iface->p->channel_list); + iface->p->dev_id = id; + snprintf(iface->p->name, STRING_SIZE, "mdev%d", id); + iface->dev.init_name = iface->p->name; iface->dev.bus = &mc.bus; iface->dev.parent = &mc.dev; iface->dev.groups = interface_attr_groups; iface->dev.release = release_interface; if (device_register(&iface->dev)) { pr_err("registering iface->dev failed\n"); - kfree(inst); + kfree(iface->p); ida_simple_remove(&mdev_id, id); return -ENOMEM; } @@ -1422,7 +1415,6 @@ int most_register_interface(struct most_interface *iface) else snprintf(channel_name, STRING_SIZE, "%s", name_suffix); - /* this increments the reference count of this instance */ c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) goto free_instance; @@ -1432,12 +1424,11 @@ int most_register_interface(struct most_interface *iface) c->dev.release = release_channel; if (device_register(&c->dev)) { pr_err("registering c->dev failed\n"); - goto free_instance; + goto free_instance_nodev; } - inst->channel[i] = c; + iface->p->channel[i] = c; c->is_starving = 0; c->iface = iface; - c->inst = inst; c->channel_id = i; c->keep_mbo = false; c->enqueue_halt = false; @@ -1456,14 +1447,22 @@ int most_register_interface(struct most_interface *iface) atomic_set(&c->mbo_ref, 0); mutex_init(&c->start_mutex); mutex_init(&c->nq_mutex); - list_add_tail(&c->list, &inst->channel_list); + list_add_tail(&c->list, &iface->p->channel_list); } pr_info("registered new MOST device mdev%d (%s)\n", id, iface->description); return 0; +free_instance_nodev: + kfree(c); + free_instance: - pr_info("Failed allocate channel(s)\n"); + while (i > 0) { + c = iface->p->channel[--i]; + device_unregister(&c->dev); + kfree(c); + } + kfree(iface->p); device_unregister(&iface->dev); ida_simple_remove(&mdev_id, id); return -ENOMEM; @@ -1481,12 +1480,10 @@ void most_deregister_interface(struct most_interface *iface) { int i; struct most_channel *c; - struct most_inst_obj *inst; pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description); - inst = iface->priv; for (i = 0; i < iface->num_channels; i++) { - c = inst->channel[i]; + c = iface->p->channel[i]; if (c->pipe0.aim) c->pipe0.aim->disconnect_channel(c->iface, c->channel_id); @@ -1500,8 +1497,8 @@ void most_deregister_interface(struct most_interface *iface) kfree(c); } - ida_simple_remove(&mdev_id, inst->dev_id); - kfree(inst); + ida_simple_remove(&mdev_id, iface->p->dev_id); + kfree(iface->p); device_unregister(&iface->dev); } EXPORT_SYMBOL_GPL(most_deregister_interface); @@ -1518,8 +1515,7 @@ EXPORT_SYMBOL_GPL(most_deregister_interface); */ void most_stop_enqueue(struct most_interface *iface, int id) { - struct most_inst_obj *inst = iface->priv; - struct most_channel *c = inst->channel[id]; + struct most_channel *c = iface->p->channel[id]; if (!c) return; @@ -1540,8 +1536,7 @@ EXPORT_SYMBOL_GPL(most_stop_enqueue); */ void most_resume_enqueue(struct most_interface *iface, int id) { - struct most_inst_obj *inst = iface->priv; - struct most_channel *c = inst->channel[id]; + struct most_channel *c = iface->p->channel[id]; if (!c) return; @@ -1564,7 +1559,6 @@ static int __init most_init(void) int err; pr_info("init()\n"); - INIT_LIST_HEAD(&instance_list); INIT_LIST_HEAD(&mc.mod_list); ida_init(&mdev_id); diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 2f61a69afb77..764f013d0db4 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -20,6 +20,7 @@ #include struct module; +struct interface_private; /** * Interface type @@ -248,6 +249,7 @@ struct most_interface { unsigned char link_stat, unsigned char *mac_addr)); void *priv; + struct interface_private *p; }; #define to_most_interface(d) container_of(d, struct most_interface, dev) -- cgit v1.2.3 From 845101bed867868f3c2e475341b9cd7cb1a86ab3 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:57 +0100 Subject: staging: most: core: put channel name in struct most_channel This patch stores a channel's name inside the most_channel structure. It is needed to have the channel attributes tied together. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 02772ce207f8..2b0c85c60c20 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -51,6 +51,7 @@ struct most_channel { atomic_t mbo_ref; atomic_t mbo_nq_level; u16 channel_id; + char name[STRING_SIZE]; bool is_poisoned; struct mutex start_mutex; struct mutex nq_mutex; /* nq thread synchronization */ @@ -1370,7 +1371,6 @@ int most_register_interface(struct most_interface *iface) { unsigned int i; int id; - char channel_name[STRING_SIZE]; struct most_channel *c; if (!iface || !iface->enqueue || !iface->configure || @@ -1410,15 +1410,14 @@ int most_register_interface(struct most_interface *iface) for (i = 0; i < iface->num_channels; i++) { const char *name_suffix = iface->channel_vector[i].name_suffix; - if (!name_suffix) - snprintf(channel_name, STRING_SIZE, "ch%d", i); - else - snprintf(channel_name, STRING_SIZE, "%s", name_suffix); - c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) goto free_instance; - c->dev.init_name = channel_name; + if (!name_suffix) + snprintf(c->name, STRING_SIZE, "ch%d", i); + else + snprintf(c->name, STRING_SIZE, "%s", name_suffix); + c->dev.init_name = c->name; c->dev.parent = &iface->dev; c->dev.groups = channel_attr_groups; c->dev.release = release_channel; -- cgit v1.2.3 From 9abfc8bb795b8d3c1323288f978c3718de843d64 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:58 +0100 Subject: staging: most: core: remove context pointer This patch removes the unused context pointer that was meant to provide the opportunity to store context information. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 764f013d0db4..718dab8b4b18 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -272,7 +272,6 @@ struct most_aim { int channel_idx); int (*rx_completion)(struct mbo *mbo); int (*tx_completion)(struct most_interface *iface, int channel_idx); - void *context; }; #define to_most_aim(d) container_of(d, struct most_aim, dev) -- cgit v1.2.3 From 66b468865ad83dc1bc48c6a74c84ddc218046ef4 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:04:59 +0100 Subject: staging: most: usb: remove pointer initialization This patch removes the initialization of the priv pointer of the most_interface structure. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/usb/usb.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index 7da7dd5e718d..87e7fec2af8a 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -1036,8 +1036,6 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) goto exit_free1; mdev->iface.channel_vector = mdev->cap; - mdev->iface.priv = NULL; - mdev->ep_address = kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL); if (!mdev->ep_address) -- cgit v1.2.3 From a12844410c4350305b9ae1c1e0c5d6bd87297e6b Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:00 +0100 Subject: staging: most: rename struct most_aim The designator of a module that proivdes means to interface userspace is called an AIM. Since this name seems to be unappropiate, this kind of moduels are going to be referred to as componetns. This is done because such modules function as components to enhance the core with new features. This patch renames the struct most_aim to core_component. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 4 ++-- drivers/staging/most/core.c | 30 +++++++++++++++--------------- drivers/staging/most/core.h | 16 +++++++--------- drivers/staging/most/net/net.c | 4 ++-- drivers/staging/most/sound/sound.c | 6 +++--- drivers/staging/most/video/video.c | 4 ++-- 6 files changed, 31 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index cd23db574d5f..a45a4dcbeb9b 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -22,7 +22,7 @@ static dev_t aim_devno; static struct class *aim_class; static struct ida minor_id; static unsigned int major; -static struct most_aim cdev_aim; +static struct core_component cdev_aim; struct aim_channel { wait_queue_head_t wq; @@ -489,7 +489,7 @@ error_alloc_channel: return retval; } -static struct most_aim cdev_aim = { +static struct core_component cdev_aim = { .name = "cdev", .probe_channel = aim_probe, .disconnect_channel = aim_disconnect_channel, diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 2b0c85c60c20..520b851c5bf8 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -40,7 +40,7 @@ static struct mostcore { #define to_driver(d) container_of(d, struct mostcore, drv); struct pipe { - struct most_aim *aim; + struct core_component *aim; int refs; int num_buffers; }; @@ -530,9 +530,9 @@ static const struct attribute_group *interface_attr_groups[] = { /* ___ ___ * ___A I M___ */ -static struct most_aim *match_module(char *name) +static struct core_component *match_module(char *name) { - struct most_aim *aim; + struct core_component *aim; list_for_each_entry(aim, &mc.mod_list, list) { if (!strcmp(aim->name, name)) @@ -577,7 +577,7 @@ static ssize_t links_show(struct device_driver *drv, char *buf) static ssize_t modules_show(struct device_driver *drv, char *buf) { - struct most_aim *aim; + struct core_component *aim; int offs = 0; list_for_each_entry(aim, &mc.mod_list, list) { @@ -660,11 +660,11 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) } static -inline int link_channel_to_aim(struct most_channel *c, struct most_aim *aim, +inline int link_channel_to_aim(struct most_channel *c, struct core_component *aim, char *aim_param) { int ret; - struct most_aim **aim_ptr; + struct core_component **aim_ptr; if (!c->pipe0.aim) aim_ptr = &c->pipe0.aim; @@ -711,7 +711,7 @@ static ssize_t add_link_store(struct device_driver *drv, size_t len) { struct most_channel *c; - struct most_aim *aim; + struct core_component *aim; char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; @@ -759,7 +759,7 @@ static ssize_t remove_link_store(struct device_driver *drv, size_t len) { struct most_channel *c; - struct most_aim *aim; + struct core_component *aim; char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; @@ -1039,7 +1039,7 @@ static void most_write_completion(struct mbo *mbo) arm_mbo(mbo); } -int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) +int channel_has_mbo(struct most_interface *iface, int id, struct core_component *aim) { struct most_channel *c = iface->p->channel[id]; unsigned long flags; @@ -1069,7 +1069,7 @@ EXPORT_SYMBOL_GPL(channel_has_mbo); * Returns a pointer to MBO on success or NULL otherwise. */ struct mbo *most_get_mbo(struct most_interface *iface, int id, - struct most_aim *aim) + struct core_component *aim) { struct mbo *mbo; struct most_channel *c; @@ -1174,7 +1174,7 @@ static void most_read_completion(struct mbo *mbo) * Returns 0 on success or error code otherwise. */ int most_start_channel(struct most_interface *iface, int id, - struct most_aim *aim) + struct core_component *aim) { int num_buffer; int ret; @@ -1244,7 +1244,7 @@ EXPORT_SYMBOL_GPL(most_start_channel); * @id: channel ID */ int most_stop_channel(struct most_interface *iface, int id, - struct most_aim *aim) + struct core_component *aim) { struct most_channel *c; @@ -1302,7 +1302,7 @@ EXPORT_SYMBOL_GPL(most_stop_channel); * most_register_aim - registers an AIM (driver) with the core * @aim: instance of AIM to be registered */ -int most_register_aim(struct most_aim *aim) +int most_register_aim(struct core_component *aim) { if (!aim) { pr_err("Bad driver\n"); @@ -1318,7 +1318,7 @@ static int disconnect_channels(struct device *dev, void *data) { struct most_interface *iface; struct most_channel *c, *tmp; - struct most_aim *aim = data; + struct core_component *aim = data; iface = to_most_interface(dev); list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { @@ -1336,7 +1336,7 @@ static int disconnect_channels(struct device *dev, void *data) * most_deregister_aim - deregisters an AIM (driver) with the core * @aim: AIM to be removed */ -int most_deregister_aim(struct most_aim *aim) +int most_deregister_aim(struct core_component *aim) { if (!aim) { pr_err("Bad driver\n"); diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 718dab8b4b18..4b6e47e78ccf 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -263,7 +263,7 @@ struct most_interface { * @tx_completion: completion handler for transmitted packets * @context: context pointer to be used by mostcore */ -struct most_aim { +struct core_component { struct list_head list; const char *name; int (*probe_channel)(struct most_interface *iface, int channel_idx, @@ -274,8 +274,6 @@ struct most_aim { int (*tx_completion)(struct most_interface *iface, int channel_idx); }; -#define to_most_aim(d) container_of(d, struct most_aim, dev) - /** * most_register_interface - Registers instance of the interface. * @iface: Pointer to the interface instance description. @@ -310,16 +308,16 @@ void most_stop_enqueue(struct most_interface *iface, int channel_idx); * in wait fifo. */ void most_resume_enqueue(struct most_interface *iface, int channel_idx); -int most_register_aim(struct most_aim *aim); -int most_deregister_aim(struct most_aim *aim); +int most_register_aim(struct core_component *comp); +int most_deregister_aim(struct core_component *comp); struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx, - struct most_aim *); + struct core_component *comp); void most_put_mbo(struct mbo *mbo); int channel_has_mbo(struct most_interface *iface, int channel_idx, - struct most_aim *aim); + struct core_component *comp); int most_start_channel(struct most_interface *iface, int channel_idx, - struct most_aim *); + struct core_component *comp); int most_stop_channel(struct most_interface *iface, int channel_idx, - struct most_aim *); + struct core_component *comp); #endif /* MOST_CORE_H_ */ diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index a9323e4afad7..edc12ad4de61 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -68,7 +68,7 @@ struct net_dev_context { static struct list_head net_devices = LIST_HEAD_INIT(net_devices); static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */ -static struct most_aim aim; +static struct core_component aim; static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) { @@ -494,7 +494,7 @@ put_nd: return ret; } -static struct most_aim aim = { +static struct core_component aim = { .name = "net", .probe_channel = aim_probe_channel, .disconnect_channel = aim_disconnect_channel, diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 5504f93aca39..e605cbe57511 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -21,7 +21,7 @@ #define DRIVER_NAME "sound" static struct list_head dev_list; -static struct most_aim audio_aim; +static struct core_component audio_aim; /** * struct channel - private structure to keep channel specific data @@ -717,9 +717,9 @@ static int audio_tx_completion(struct most_interface *iface, int channel_id) } /** - * Initialization of the struct most_aim + * Initialization of the struct core_component */ -static struct most_aim audio_aim = { +static struct core_component audio_aim = { .name = DRIVER_NAME, .probe_channel = audio_probe_channel, .disconnect_channel = audio_disconnect_channel, diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 25ae4887b04d..2b8b3aed1ec2 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -25,7 +25,7 @@ #define V4L2_AIM_MAX_INPUT 1 -static struct most_aim aim_info; +static struct core_component aim_info; struct most_video_dev { struct most_interface *iface; @@ -562,7 +562,7 @@ static int aim_disconnect_channel(struct most_interface *iface, return 0; } -static struct most_aim aim_info = { +static struct core_component aim_info = { .name = "v4l", .probe_channel = aim_probe_channel, .disconnect_channel = aim_disconnect_channel, -- cgit v1.2.3 From ed021a0f8e5b1ac2966a997e908c6a7824da6baa Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:01 +0100 Subject: staging: most: rename functions to register a driver with most_core This patch renames the functions to register and deregister a component module with the core. It is needed because the modules that interface the userspace are referred to as components. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 4 ++-- drivers/staging/most/core.c | 13 +++++++------ drivers/staging/most/core.h | 4 ++-- drivers/staging/most/net/net.c | 4 ++-- drivers/staging/most/sound/sound.c | 4 ++-- drivers/staging/most/video/video.c | 6 +++--- 6 files changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index a45a4dcbeb9b..2447fbfd201e 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -518,7 +518,7 @@ static int __init mod_init(void) err = PTR_ERR(aim_class); goto free_cdev; } - err = most_register_aim(&cdev_aim); + err = most_register_component(&cdev_aim); if (err) goto dest_class; return 0; @@ -538,7 +538,7 @@ static void __exit mod_exit(void) pr_info("exit module\n"); - most_deregister_aim(&cdev_aim); + most_deregister_component(&cdev_aim); list_for_each_entry_safe(c, tmp, &channel_list, list) { destroy_cdev(c); diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 520b851c5bf8..dd6cebf88e59 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -69,6 +69,7 @@ struct most_channel { struct list_head trash_fifo; struct task_struct *hdm_enqueue_task; wait_queue_head_t hdm_fifo_wq; + }; #define to_channel(d) container_of(d, struct most_channel, dev) @@ -1299,10 +1300,10 @@ out: EXPORT_SYMBOL_GPL(most_stop_channel); /** - * most_register_aim - registers an AIM (driver) with the core + * most_register_component - registers an AIM (driver) with the core * @aim: instance of AIM to be registered */ -int most_register_aim(struct core_component *aim) +int most_register_component(struct core_component *aim) { if (!aim) { pr_err("Bad driver\n"); @@ -1312,7 +1313,7 @@ int most_register_aim(struct core_component *aim) pr_info("registered new application interfacing module %s\n", aim->name); return 0; } -EXPORT_SYMBOL_GPL(most_register_aim); +EXPORT_SYMBOL_GPL(most_register_component); static int disconnect_channels(struct device *dev, void *data) { @@ -1333,10 +1334,10 @@ static int disconnect_channels(struct device *dev, void *data) } /** - * most_deregister_aim - deregisters an AIM (driver) with the core + * most_deregister_component - deregisters an AIM (driver) with the core * @aim: AIM to be removed */ -int most_deregister_aim(struct core_component *aim) +int most_deregister_component(struct core_component *aim) { if (!aim) { pr_err("Bad driver\n"); @@ -1348,7 +1349,7 @@ int most_deregister_aim(struct core_component *aim) pr_info("deregistering module %s\n", aim->name); return 0; } -EXPORT_SYMBOL_GPL(most_deregister_aim); +EXPORT_SYMBOL_GPL(most_deregister_component); static void release_interface(struct device *dev) { diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 4b6e47e78ccf..5a3a5c5c3347 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -308,8 +308,8 @@ void most_stop_enqueue(struct most_interface *iface, int channel_idx); * in wait fifo. */ void most_resume_enqueue(struct most_interface *iface, int channel_idx); -int most_register_aim(struct core_component *comp); -int most_deregister_aim(struct core_component *comp); +int most_register_component(struct core_component *comp); +int most_deregister_component(struct core_component *comp); struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx, struct core_component *comp); void most_put_mbo(struct mbo *mbo); diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index edc12ad4de61..cbe0dda011b4 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -506,12 +506,12 @@ static int __init most_net_init(void) { spin_lock_init(&list_lock); mutex_init(&probe_disc_mt); - return most_register_aim(&aim); + return most_register_component(&aim); } static void __exit most_net_exit(void) { - most_deregister_aim(&aim); + most_deregister_component(&aim); } /** diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index e605cbe57511..a3a46a269f43 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -733,7 +733,7 @@ static int __init audio_init(void) INIT_LIST_HEAD(&dev_list); - return most_register_aim(&audio_aim); + return most_register_component(&audio_aim); } static void __exit audio_exit(void) @@ -747,7 +747,7 @@ static void __exit audio_exit(void) snd_card_free(channel->card); } - most_deregister_aim(&audio_aim); + most_deregister_component(&audio_aim); } module_init(audio_init); diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 2b8b3aed1ec2..3a97a2443c0b 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -572,7 +572,7 @@ static struct core_component aim_info = { static int __init aim_init(void) { spin_lock_init(&list_lock); - return most_register_aim(&aim_info); + return most_register_component(&aim_info); } static void __exit aim_exit(void) @@ -581,7 +581,7 @@ static void __exit aim_exit(void) /* * As the mostcore currently doesn't call disconnect_channel() - * for linked channels while we call most_deregister_aim() + * for linked channels while we call most_deregister_component() * we simulate this call here. * This must be fixed in core. */ @@ -597,7 +597,7 @@ static void __exit aim_exit(void) } spin_unlock_irq(&list_lock); - most_deregister_aim(&aim_info); + most_deregister_component(&aim_info); BUG_ON(!list_empty(&video_devices)); } -- cgit v1.2.3 From 81ce26b7c4553496b10083b975f1560059c8d747 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:02 +0100 Subject: staging: most: core: rename mod_list This patch renames the variable mod_list to comp_list. It is needed because modules that interface userspace are referred to as components. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index dd6cebf88e59..c5b809b50247 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -34,7 +34,7 @@ static struct mostcore { struct device_driver drv; struct bus_type bus; struct class *class; - struct list_head mod_list; + struct list_head comp_list; } mc; #define to_driver(d) container_of(d, struct mostcore, drv); @@ -535,7 +535,7 @@ static struct core_component *match_module(char *name) { struct core_component *aim; - list_for_each_entry(aim, &mc.mod_list, list) { + list_for_each_entry(aim, &mc.comp_list, list) { if (!strcmp(aim->name, name)) return aim; } @@ -581,7 +581,7 @@ static ssize_t modules_show(struct device_driver *drv, char *buf) struct core_component *aim; int offs = 0; - list_for_each_entry(aim, &mc.mod_list, list) { + list_for_each_entry(aim, &mc.comp_list, list) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s\n", aim->name); } @@ -1309,7 +1309,7 @@ int most_register_component(struct core_component *aim) pr_err("Bad driver\n"); return -EINVAL; } - list_add_tail(&aim->list, &mc.mod_list); + list_add_tail(&aim->list, &mc.comp_list); pr_info("registered new application interfacing module %s\n", aim->name); return 0; } @@ -1559,7 +1559,7 @@ static int __init most_init(void) int err; pr_info("init()\n"); - INIT_LIST_HEAD(&mc.mod_list); + INIT_LIST_HEAD(&mc.comp_list); ida_init(&mdev_id); mc.bus.name = "most", -- cgit v1.2.3 From 5a5abf0200703f0148e04471e9fbe170d23be4ad Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:03 +0100 Subject: staging: most: core: rename aim variables This patch replaces the 'aim' substrings of variable names with 'comp'. It is needed because of the renaming of AIM modules to components. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 172 ++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index c5b809b50247..ebfa97c504a2 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -40,7 +40,7 @@ static struct mostcore { #define to_driver(d) container_of(d, struct mostcore, drv); struct pipe { - struct core_component *aim; + struct core_component *comp; int refs; int num_buffers; }; @@ -533,11 +533,11 @@ static const struct attribute_group *interface_attr_groups[] = { */ static struct core_component *match_module(char *name) { - struct core_component *aim; + struct core_component *comp; - list_for_each_entry(aim, &mc.comp_list, list) { - if (!strcmp(aim->name, name)) - return aim; + list_for_each_entry(comp, &mc.comp_list, list) { + if (!strcmp(comp->name, name)) + return comp; } return NULL; } @@ -550,19 +550,19 @@ int print_links(struct device *dev, void *data) struct most_interface *iface = to_most_interface(dev); list_for_each_entry(c, &iface->p->channel_list, list) { - if (c->pipe0.aim) { + if (c->pipe0.comp) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s:%s:%s\n", - c->pipe0.aim->name, + c->pipe0.comp->name, dev_name(&iface->dev), dev_name(&c->dev)); } - if (c->pipe1.aim) { + if (c->pipe1.comp) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s:%s:%s\n", - c->pipe1.aim->name, + c->pipe1.comp->name, dev_name(&iface->dev), dev_name(&c->dev)); } @@ -578,12 +578,12 @@ static ssize_t links_show(struct device_driver *drv, char *buf) static ssize_t modules_show(struct device_driver *drv, char *buf) { - struct core_component *aim; + struct core_component *comp; int offs = 0; - list_for_each_entry(aim, &mc.comp_list, list) { + list_for_each_entry(comp, &mc.comp_list, list) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s\n", - aim->name); + comp->name); } return offs; } @@ -661,24 +661,25 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) } static -inline int link_channel_to_aim(struct most_channel *c, struct core_component *aim, - char *aim_param) +inline int link_channel_to_aim(struct most_channel *c, + struct core_component *comp, + char *comp_param) { int ret; - struct core_component **aim_ptr; + struct core_component **comp_ptr; - if (!c->pipe0.aim) - aim_ptr = &c->pipe0.aim; - else if (!c->pipe1.aim) - aim_ptr = &c->pipe1.aim; + if (!c->pipe0.comp) + comp_ptr = &c->pipe0.comp; + else if (!c->pipe1.comp) + comp_ptr = &c->pipe1.comp; else return -ENOSPC; - *aim_ptr = aim; - ret = aim->probe_channel(c->iface, c->channel_id, - &c->cfg, aim_param); + *comp_ptr = comp; + ret = comp->probe_channel(c->iface, c->channel_id, + &c->cfg, comp_param); if (ret) { - *aim_ptr = NULL; + *comp_ptr = NULL; return ret; } @@ -712,33 +713,33 @@ static ssize_t add_link_store(struct device_driver *drv, size_t len) { struct most_channel *c; - struct core_component *aim; + struct core_component *comp; char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; - char *aim_name; - char *aim_param; + char *comp_name; + char *comp_param; char devnod_buf[STRING_SIZE]; int ret; size_t max_len = min_t(size_t, len + 1, STRING_SIZE); strlcpy(buffer, buf, max_len); - ret = split_string(buffer, &mdev, &mdev_ch, &aim_name, &aim_param); + ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, &comp_param); if (ret) return ret; - aim = match_module(aim_name); - if (!aim_param || *aim_param == 0) { + comp = match_module(comp_name); + if (!comp_param || *comp_param == 0) { snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, mdev_ch); - aim_param = devnod_buf; + comp_param = devnod_buf; } c = get_channel(mdev, mdev_ch); if (!c) return -ENODEV; - ret = link_channel_to_aim(c, aim, aim_param); + ret = link_channel_to_aim(c, comp, comp_param); if (ret) return ret; @@ -760,29 +761,29 @@ static ssize_t remove_link_store(struct device_driver *drv, size_t len) { struct most_channel *c; - struct core_component *aim; + struct core_component *comp; char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; - char *aim_name; + char *comp_name; int ret; size_t max_len = min_t(size_t, len + 1, STRING_SIZE); strlcpy(buffer, buf, max_len); - ret = split_string(buffer, &mdev, &mdev_ch, &aim_name, NULL); + ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, NULL); if (ret) return ret; - aim = match_module(aim_name); + comp = match_module(comp_name); c = get_channel(mdev, mdev_ch); if (!c) return -ENODEV; - if (aim->disconnect_channel(c->iface, c->channel_id)) + if (comp->disconnect_channel(c->iface, c->channel_id)) return -EIO; - if (c->pipe0.aim == aim) - c->pipe0.aim = NULL; - if (c->pipe1.aim == aim) - c->pipe1.aim = NULL; + if (c->pipe0.comp == comp) + c->pipe0.comp = NULL; + if (c->pipe1.comp == comp) + c->pipe1.comp = NULL; return len; } @@ -939,11 +940,11 @@ static void arm_mbo(struct mbo *mbo) list_add_tail(&mbo->list, &c->fifo); spin_unlock_irqrestore(&c->fifo_lock, flags); - if (c->pipe0.refs && c->pipe0.aim->tx_completion) - c->pipe0.aim->tx_completion(c->iface, c->channel_id); + if (c->pipe0.refs && c->pipe0.comp->tx_completion) + c->pipe0.comp->tx_completion(c->iface, c->channel_id); - if (c->pipe1.refs && c->pipe1.aim->tx_completion) - c->pipe1.aim->tx_completion(c->iface, c->channel_id); + if (c->pipe1.refs && c->pipe1.comp->tx_completion) + c->pipe1.comp->tx_completion(c->iface, c->channel_id); } /** @@ -1040,7 +1041,8 @@ static void most_write_completion(struct mbo *mbo) arm_mbo(mbo); } -int channel_has_mbo(struct most_interface *iface, int id, struct core_component *aim) +int channel_has_mbo(struct most_interface *iface, int id, + struct core_component *comp) { struct most_channel *c = iface->p->channel[id]; unsigned long flags; @@ -1050,8 +1052,8 @@ int channel_has_mbo(struct most_interface *iface, int id, struct core_component return -EINVAL; if (c->pipe0.refs && c->pipe1.refs && - ((aim == c->pipe0.aim && c->pipe0.num_buffers <= 0) || - (aim == c->pipe1.aim && c->pipe1.num_buffers <= 0))) + ((comp == c->pipe0.comp && c->pipe0.num_buffers <= 0) || + (comp == c->pipe1.comp && c->pipe1.num_buffers <= 0))) return 0; spin_lock_irqsave(&c->fifo_lock, flags); @@ -1070,7 +1072,7 @@ EXPORT_SYMBOL_GPL(channel_has_mbo); * Returns a pointer to MBO on success or NULL otherwise. */ struct mbo *most_get_mbo(struct most_interface *iface, int id, - struct core_component *aim) + struct core_component *comp) { struct mbo *mbo; struct most_channel *c; @@ -1082,13 +1084,13 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id, return NULL; if (c->pipe0.refs && c->pipe1.refs && - ((aim == c->pipe0.aim && c->pipe0.num_buffers <= 0) || - (aim == c->pipe1.aim && c->pipe1.num_buffers <= 0))) + ((comp == c->pipe0.comp && c->pipe0.num_buffers <= 0) || + (comp == c->pipe1.comp && c->pipe1.num_buffers <= 0))) return NULL; - if (aim == c->pipe0.aim) + if (comp == c->pipe0.comp) num_buffers_ptr = &c->pipe0.num_buffers; - else if (aim == c->pipe1.aim) + else if (comp == c->pipe1.comp) num_buffers_ptr = &c->pipe1.num_buffers; else num_buffers_ptr = &dummy_num_buffers; @@ -1153,12 +1155,12 @@ static void most_read_completion(struct mbo *mbo) if (atomic_sub_and_test(1, &c->mbo_nq_level)) c->is_starving = 1; - if (c->pipe0.refs && c->pipe0.aim->rx_completion && - c->pipe0.aim->rx_completion(mbo) == 0) + if (c->pipe0.refs && c->pipe0.comp->rx_completion && + c->pipe0.comp->rx_completion(mbo) == 0) return; - if (c->pipe1.refs && c->pipe1.aim->rx_completion && - c->pipe1.aim->rx_completion(mbo) == 0) + if (c->pipe1.refs && c->pipe1.comp->rx_completion && + c->pipe1.comp->rx_completion(mbo) == 0) return; most_put_mbo(mbo); @@ -1175,7 +1177,7 @@ static void most_read_completion(struct mbo *mbo) * Returns 0 on success or error code otherwise. */ int most_start_channel(struct most_interface *iface, int id, - struct core_component *aim) + struct core_component *comp) { int num_buffer; int ret; @@ -1186,7 +1188,7 @@ int most_start_channel(struct most_interface *iface, int id, mutex_lock(&c->start_mutex); if (c->pipe0.refs + c->pipe1.refs > 0) - goto out; /* already started by other aim */ + goto out; /* already started by other comp */ if (!try_module_get(iface->mod)) { pr_info("failed to acquire HDM lock\n"); @@ -1225,9 +1227,9 @@ int most_start_channel(struct most_interface *iface, int id, atomic_set(&c->mbo_ref, num_buffer); out: - if (aim == c->pipe0.aim) + if (comp == c->pipe0.comp) c->pipe0.refs++; - if (aim == c->pipe1.aim) + if (comp == c->pipe1.comp) c->pipe1.refs++; mutex_unlock(&c->start_mutex); return 0; @@ -1245,7 +1247,7 @@ EXPORT_SYMBOL_GPL(most_start_channel); * @id: channel ID */ int most_stop_channel(struct most_interface *iface, int id, - struct core_component *aim) + struct core_component *comp) { struct most_channel *c; @@ -1290,9 +1292,9 @@ int most_stop_channel(struct most_interface *iface, int id, c->is_poisoned = false; out: - if (aim == c->pipe0.aim) + if (comp == c->pipe0.comp) c->pipe0.refs--; - if (aim == c->pipe1.aim) + if (comp == c->pipe1.comp) c->pipe1.refs--; mutex_unlock(&c->start_mutex); return 0; @@ -1303,14 +1305,14 @@ EXPORT_SYMBOL_GPL(most_stop_channel); * most_register_component - registers an AIM (driver) with the core * @aim: instance of AIM to be registered */ -int most_register_component(struct core_component *aim) +int most_register_component(struct core_component *comp) { - if (!aim) { + if (!comp) { pr_err("Bad driver\n"); return -EINVAL; } - list_add_tail(&aim->list, &mc.comp_list); - pr_info("registered new application interfacing module %s\n", aim->name); + list_add_tail(&comp->list, &mc.comp_list); + pr_info("registered new application interfacing module %s\n", comp->name); return 0; } EXPORT_SYMBOL_GPL(most_register_component); @@ -1319,16 +1321,16 @@ static int disconnect_channels(struct device *dev, void *data) { struct most_interface *iface; struct most_channel *c, *tmp; - struct core_component *aim = data; + struct core_component *comp = data; iface = to_most_interface(dev); list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { - if (c->pipe0.aim == aim || c->pipe1.aim == aim) - aim->disconnect_channel(c->iface, c->channel_id); - if (c->pipe0.aim == aim) - c->pipe0.aim = NULL; - if (c->pipe1.aim == aim) - c->pipe1.aim = NULL; + if (c->pipe0.comp == comp || c->pipe1.comp == comp) + comp->disconnect_channel(c->iface, c->channel_id); + if (c->pipe0.comp == comp) + c->pipe0.comp = NULL; + if (c->pipe1.comp == comp) + c->pipe1.comp = NULL; } return 0; } @@ -1337,16 +1339,16 @@ static int disconnect_channels(struct device *dev, void *data) * most_deregister_component - deregisters an AIM (driver) with the core * @aim: AIM to be removed */ -int most_deregister_component(struct core_component *aim) +int most_deregister_component(struct core_component *comp) { - if (!aim) { + if (!comp) { pr_err("Bad driver\n"); return -EINVAL; } - bus_for_each_dev(&mc.bus, NULL, aim, disconnect_channels); - list_del(&aim->list); - pr_info("deregistering module %s\n", aim->name); + bus_for_each_dev(&mc.bus, NULL, comp, disconnect_channels); + list_del(&comp->list); + pr_info("deregistering module %s\n", comp->name); return 0; } EXPORT_SYMBOL_GPL(most_deregister_component); @@ -1484,14 +1486,14 @@ void most_deregister_interface(struct most_interface *iface) pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description); for (i = 0; i < iface->num_channels; i++) { c = iface->p->channel[i]; - if (c->pipe0.aim) - c->pipe0.aim->disconnect_channel(c->iface, + if (c->pipe0.comp) + c->pipe0.comp->disconnect_channel(c->iface, c->channel_id); - if (c->pipe1.aim) - c->pipe1.aim->disconnect_channel(c->iface, + if (c->pipe1.comp) + c->pipe1.comp->disconnect_channel(c->iface, c->channel_id); - c->pipe0.aim = NULL; - c->pipe1.aim = NULL; + c->pipe0.comp = NULL; + c->pipe1.comp = NULL; list_del(&c->list); device_unregister(&c->dev); kfree(c); -- cgit v1.2.3 From db09fe0d3ab0bada23cb7a0be991a158a8fc5dcc Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:04 +0100 Subject: staging: most: core: rename function link_channel_to_aim This patch renames the function link_channel_to_aim to link_channel_to_component. It is needed because userspace interfacing modules are referred to as components. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index ebfa97c504a2..174c88a4bd9e 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -661,9 +661,9 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) } static -inline int link_channel_to_aim(struct most_channel *c, - struct core_component *comp, - char *comp_param) +inline int link_channel_to_component(struct most_channel *c, + struct core_component *comp, + char *comp_param) { int ret; struct core_component **comp_ptr; @@ -739,7 +739,7 @@ static ssize_t add_link_store(struct device_driver *drv, if (!c) return -ENODEV; - ret = link_channel_to_aim(c, comp, comp_param); + ret = link_channel_to_component(c, comp, comp_param); if (ret) return ret; -- cgit v1.2.3 From 11b3348f3b21b749f8bbc966f61b6ea6c9019403 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:05 +0100 Subject: staging: most: net: remove aim designators This patch renames the all aim designators with comp. It is needed because userspace interfacing modules are referred to as components. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/net/net.c | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index cbe0dda011b4..38d6fe94ac6b 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Networking AIM - Networking Application Interface Module for MostCore + * Networking component - Networking Application Interface Module for MostCore * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG */ @@ -68,7 +68,7 @@ struct net_dev_context { static struct list_head net_devices = LIST_HEAD_INIT(net_devices); static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */ -static struct core_component aim; +static struct core_component comp; static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) { @@ -178,15 +178,15 @@ static int most_nd_open(struct net_device *dev) mutex_lock(&probe_disc_mt); - if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) { + if (most_start_channel(nd->iface, nd->rx.ch_id, &comp)) { netdev_err(dev, "most_start_channel() failed\n"); ret = -EBUSY; goto unlock; } - if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) { + if (most_start_channel(nd->iface, nd->tx.ch_id, &comp)) { netdev_err(dev, "most_start_channel() failed\n"); - most_stop_channel(nd->iface, nd->rx.ch_id, &aim); + most_stop_channel(nd->iface, nd->rx.ch_id, &comp); ret = -EBUSY; goto unlock; } @@ -212,8 +212,8 @@ static int most_nd_stop(struct net_device *dev) netif_stop_queue(dev); if (nd->iface->request_netinfo) nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL); - most_stop_channel(nd->iface, nd->rx.ch_id, &aim); - most_stop_channel(nd->iface, nd->tx.ch_id, &aim); + most_stop_channel(nd->iface, nd->rx.ch_id, &comp); + most_stop_channel(nd->iface, nd->tx.ch_id, &comp); return 0; } @@ -225,7 +225,7 @@ static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb, struct mbo *mbo; int ret; - mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim); + mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &comp); if (!mbo) { netif_stop_queue(dev); @@ -290,8 +290,8 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) return nd; } -static int aim_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, char *name) +static int comp_probe_channel(struct most_interface *iface, int channel_idx, + struct most_channel_config *ccfg, char *name) { struct net_dev_context *nd; struct net_dev_channel *ch; @@ -346,8 +346,8 @@ unlock: return ret; } -static int aim_disconnect_channel(struct most_interface *iface, - int channel_idx) +static int comp_disconnect_channel(struct most_interface *iface, + int channel_idx) { struct net_dev_context *nd; struct net_dev_channel *ch; @@ -393,8 +393,8 @@ unlock: return ret; } -static int aim_resume_tx_channel(struct most_interface *iface, - int channel_idx) +static int comp_resume_tx_channel(struct most_interface *iface, + int channel_idx) { struct net_dev_context *nd; @@ -412,7 +412,7 @@ put_nd: return 0; } -static int aim_rx_data(struct mbo *mbo) +static int comp_rx_data(struct mbo *mbo) { const u32 zero = 0; struct net_dev_context *nd; @@ -494,24 +494,24 @@ put_nd: return ret; } -static struct core_component aim = { +static struct core_component comp = { .name = "net", - .probe_channel = aim_probe_channel, - .disconnect_channel = aim_disconnect_channel, - .tx_completion = aim_resume_tx_channel, - .rx_completion = aim_rx_data, + .probe_channel = comp_probe_channel, + .disconnect_channel = comp_disconnect_channel, + .tx_completion = comp_resume_tx_channel, + .rx_completion = comp_rx_data, }; static int __init most_net_init(void) { spin_lock_init(&list_lock); mutex_init(&probe_disc_mt); - return most_register_component(&aim); + return most_register_component(&comp); } static void __exit most_net_exit(void) { - most_deregister_component(&aim); + most_deregister_component(&comp); } /** -- cgit v1.2.3 From 1f95cf02a32d500b7aaa846e197f90e2f8b1828d Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:06 +0100 Subject: staging: most: sound: remove aim designator This patch removes all 'aim' designators and replaces them with 'comp'. It is needd because userspace interfacing modules are referred to as components. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/sound/sound.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index a3a46a269f43..e93b8047561c 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * sound.c - Audio Application Interface Module for Mostcore + * sound.c - Sound component for Mostcore * * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG */ @@ -21,7 +21,7 @@ #define DRIVER_NAME "sound" static struct list_head dev_list; -static struct core_component audio_aim; +static struct core_component comp; /** * struct channel - private structure to keep channel specific data @@ -234,7 +234,7 @@ static int playback_thread(void *data) kthread_should_stop() || (channel->is_stream_running && (mbo = most_get_mbo(channel->iface, channel->id, - &audio_aim)))); + &comp)))); if (!mbo) continue; @@ -277,7 +277,7 @@ static int pcm_open(struct snd_pcm_substream *substream) } } - if (most_start_channel(channel->iface, channel->id, &audio_aim)) { + if (most_start_channel(channel->iface, channel->id, &comp)) { pr_err("most_start_channel() failed!\n"); if (cfg->direction == MOST_CH_TX) kthread_stop(channel->playback_task); @@ -304,7 +304,7 @@ static int pcm_close(struct snd_pcm_substream *substream) if (channel->cfg->direction == MOST_CH_TX) kthread_stop(channel->playback_task); - most_stop_channel(channel->iface, channel->id, &audio_aim); + most_stop_channel(channel->iface, channel->id, &comp); return 0; } @@ -719,7 +719,7 @@ static int audio_tx_completion(struct most_interface *iface, int channel_id) /** * Initialization of the struct core_component */ -static struct core_component audio_aim = { +static struct core_component comp = { .name = DRIVER_NAME, .probe_channel = audio_probe_channel, .disconnect_channel = audio_disconnect_channel, @@ -733,7 +733,7 @@ static int __init audio_init(void) INIT_LIST_HEAD(&dev_list); - return most_register_component(&audio_aim); + return most_register_component(&comp); } static void __exit audio_exit(void) @@ -747,7 +747,7 @@ static void __exit audio_exit(void) snd_card_free(channel->card); } - most_deregister_component(&audio_aim); + most_deregister_component(&comp); } module_init(audio_init); -- cgit v1.2.3 From 1b10a0316e2d5e278a3cff14adcfcde71792f016 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:07 +0100 Subject: staging: most: video: remove aim designators This patch takes the 'aim' prefixes and variable names off the module and uses component instead. It is needed because userspace interfacing modules are referred to as components. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/video/video.c | 152 ++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 3a97a2443c0b..62b789e71399 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * V4L2 AIM - V4L2 Application Interface Module for MostCore + * V4L2 Component - V4L2 Application Interface Module for MostCore * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG */ @@ -23,9 +23,9 @@ #include "most/core.h" -#define V4L2_AIM_MAX_INPUT 1 +#define V4L2_CMP_MAX_INPUT 1 -static struct core_component aim_info; +static struct core_component comp; struct most_video_dev { struct most_interface *iface; @@ -46,7 +46,7 @@ struct most_video_dev { wait_queue_head_t wait_data; }; -struct aim_fh { +struct comp_fh { /* must be the first field of this struct! */ struct v4l2_fh fh; struct most_video_dev *mdev; @@ -66,14 +66,14 @@ static inline struct mbo *get_top_mbo(struct most_video_dev *mdev) return list_first_entry(&mdev->pending_mbos, struct mbo, list); } -static int aim_vdev_open(struct file *filp) +static int comp_vdev_open(struct file *filp) { int ret; struct video_device *vdev = video_devdata(filp); struct most_video_dev *mdev = video_drvdata(filp); - struct aim_fh *fh; + struct comp_fh *fh; - v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_vdev_open()\n"); switch (vdev->vfl_type) { case VFL_TYPE_GRABBER: @@ -98,7 +98,7 @@ static int aim_vdev_open(struct file *filp) v4l2_fh_add(&fh->fh); - ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info); + ret = most_start_channel(mdev->iface, mdev->ch_idx, &comp); if (ret) { v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n"); goto err_rm; @@ -116,13 +116,13 @@ err_dec: return ret; } -static int aim_vdev_close(struct file *filp) +static int comp_vdev_close(struct file *filp) { - struct aim_fh *fh = filp->private_data; + struct comp_fh *fh = filp->private_data; struct most_video_dev *mdev = fh->mdev; struct mbo *mbo, *tmp; - v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_vdev_close()\n"); /* * We need to put MBOs back before we call most_stop_channel() @@ -142,7 +142,7 @@ static int aim_vdev_close(struct file *filp) spin_lock_irq(&mdev->list_lock); } spin_unlock_irq(&mdev->list_lock); - most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info); + most_stop_channel(mdev->iface, mdev->ch_idx, &comp); mdev->mute = false; v4l2_fh_del(&fh->fh); @@ -153,10 +153,10 @@ static int aim_vdev_close(struct file *filp) return 0; } -static ssize_t aim_vdev_read(struct file *filp, char __user *buf, - size_t count, loff_t *pos) +static ssize_t comp_vdev_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos) { - struct aim_fh *fh = filp->private_data; + struct comp_fh *fh = filp->private_data; struct most_video_dev *mdev = fh->mdev; int ret = 0; @@ -203,9 +203,9 @@ static ssize_t aim_vdev_read(struct file *filp, char __user *buf, return ret; } -static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait) +static unsigned int comp_vdev_poll(struct file *filp, poll_table *wait) { - struct aim_fh *fh = filp->private_data; + struct comp_fh *fh = filp->private_data; struct most_video_dev *mdev = fh->mdev; unsigned int mask = 0; @@ -218,7 +218,7 @@ static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait) return mask; } -static void aim_set_format_struct(struct v4l2_format *f) +static void comp_set_format_struct(struct v4l2_format *f) { f->fmt.pix.width = 8; f->fmt.pix.height = 8; @@ -230,8 +230,8 @@ static void aim_set_format_struct(struct v4l2_format *f) f->fmt.pix.priv = 0; } -static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, - struct v4l2_format *format) +static int comp_set_format(struct most_video_dev *mdev, unsigned int cmd, + struct v4l2_format *format) { if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG) return -EINVAL; @@ -239,7 +239,7 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, if (cmd == VIDIOC_TRY_FMT) return 0; - aim_set_format_struct(format); + comp_set_format_struct(format); return 0; } @@ -247,12 +247,12 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n"); - strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver)); + strlcpy(cap->driver, "v4l2_component", sizeof(cap->driver)); strlcpy(cap->card, "MOST", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "%s", mdev->iface->description); @@ -267,7 +267,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index); @@ -286,36 +286,36 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n"); - aim_set_format_struct(f); + comp_set_format_struct(f); return 0; } static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - return aim_set_format(mdev, VIDIOC_TRY_FMT, f); + return comp_set_format(mdev, VIDIOC_TRY_FMT, f); } static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - return aim_set_format(mdev, VIDIOC_S_FMT, f); + return comp_set_format(mdev, VIDIOC_S_FMT, f); } static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n"); @@ -327,10 +327,10 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *input) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - if (input->index >= V4L2_AIM_MAX_INPUT) + if (input->index >= V4L2_CMP_MAX_INPUT) return -EINVAL; strcpy(input->name, "MOST Video"); @@ -344,7 +344,7 @@ static int vidioc_enum_input(struct file *file, void *priv, static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; *i = mdev->ctrl_input; return 0; @@ -352,23 +352,23 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) static int vidioc_s_input(struct file *file, void *priv, unsigned int index) { - struct aim_fh *fh = priv; + struct comp_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index); - if (index >= V4L2_AIM_MAX_INPUT) + if (index >= V4L2_CMP_MAX_INPUT) return -EINVAL; mdev->ctrl_input = index; return 0; } -static const struct v4l2_file_operations aim_fops = { +static const struct v4l2_file_operations comp_fops = { .owner = THIS_MODULE, - .open = aim_vdev_open, - .release = aim_vdev_close, - .read = aim_vdev_read, - .poll = aim_vdev_poll, + .open = comp_vdev_open, + .release = comp_vdev_close, + .read = comp_vdev_read, + .poll = comp_vdev_poll, .unlocked_ioctl = video_ioctl2, }; @@ -384,8 +384,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static const struct video_device aim_videodev_template = { - .fops = &aim_fops, +static const struct video_device comp_videodev_template = { + .fops = &comp_fops, .release = video_device_release, .ioctl_ops = &video_ioctl_ops, .tvnorms = V4L2_STD_UNKNOWN, @@ -393,7 +393,7 @@ static const struct video_device aim_videodev_template = { /**************************************************************************/ -static struct most_video_dev *get_aim_dev( +static struct most_video_dev *get_comp_dev( struct most_interface *iface, int channel_idx) { struct most_video_dev *mdev; @@ -410,11 +410,11 @@ static struct most_video_dev *get_aim_dev( return NULL; } -static int aim_rx_data(struct mbo *mbo) +static int comp_rx_data(struct mbo *mbo) { unsigned long flags; struct most_video_dev *mdev = - get_aim_dev(mbo->ifp, mbo->hdm_channel_id); + get_comp_dev(mbo->ifp, mbo->hdm_channel_id); if (!mdev) return -EIO; @@ -431,11 +431,11 @@ static int aim_rx_data(struct mbo *mbo) return 0; } -static int aim_register_videodev(struct most_video_dev *mdev) +static int comp_register_videodev(struct most_video_dev *mdev) { int ret; - v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_register_videodev()\n"); init_waitqueue_head(&mdev->wait_data); @@ -445,7 +445,7 @@ static int aim_register_videodev(struct most_video_dev *mdev) return -ENOMEM; /* Fill the video capture device struct */ - *mdev->vdev = aim_videodev_template; + *mdev->vdev = comp_videodev_template; mdev->vdev->v4l2_dev = &mdev->v4l2_dev; mdev->vdev->lock = &mdev->lock; snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s", @@ -463,14 +463,14 @@ static int aim_register_videodev(struct most_video_dev *mdev) return ret; } -static void aim_unregister_videodev(struct most_video_dev *mdev) +static void comp_unregister_videodev(struct most_video_dev *mdev) { - v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_unregister_videodev()\n"); video_unregister_device(mdev->vdev); } -static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) +static void comp_v4l2_dev_release(struct v4l2_device *v4l2_dev) { struct most_video_dev *mdev = container_of(v4l2_dev, struct most_video_dev, v4l2_dev); @@ -479,13 +479,13 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) kfree(mdev); } -static int aim_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, char *name) +static int comp_probe_channel(struct most_interface *iface, int channel_idx, + struct most_channel_config *ccfg, char *name) { int ret; - struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); + struct most_video_dev *mdev = get_comp_dev(iface, channel_idx); - pr_info("aim_probe_channel(%s)\n", name); + pr_info("comp_probe_channel(%s)\n", name); if (mdev) { pr_err("channel already linked\n"); @@ -513,7 +513,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, INIT_LIST_HEAD(&mdev->pending_mbos); mdev->iface = iface; mdev->ch_idx = channel_idx; - mdev->v4l2_dev.release = aim_v4l2_dev_release; + mdev->v4l2_dev.release = comp_v4l2_dev_release; /* Create the v4l2_device */ strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name)); @@ -524,14 +524,14 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, return ret; } - ret = aim_register_videodev(mdev); + ret = comp_register_videodev(mdev); if (ret) goto err_unreg; spin_lock_irq(&list_lock); list_add(&mdev->list, &video_devices); spin_unlock_irq(&list_lock); - v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n"); + v4l2_info(&mdev->v4l2_dev, "comp_probe_channel() done\n"); return 0; err_unreg: @@ -540,42 +540,42 @@ err_unreg: return ret; } -static int aim_disconnect_channel(struct most_interface *iface, +static int comp_disconnect_channel(struct most_interface *iface, int channel_idx) { - struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); + struct most_video_dev *mdev = get_comp_dev(iface, channel_idx); if (!mdev) { pr_err("no such channel is linked\n"); return -ENOENT; } - v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n"); + v4l2_info(&mdev->v4l2_dev, "comp_disconnect_channel()\n"); spin_lock_irq(&list_lock); list_del(&mdev->list); spin_unlock_irq(&list_lock); - aim_unregister_videodev(mdev); + comp_unregister_videodev(mdev); v4l2_device_disconnect(&mdev->v4l2_dev); v4l2_device_put(&mdev->v4l2_dev); return 0; } -static struct core_component aim_info = { - .name = "v4l", - .probe_channel = aim_probe_channel, - .disconnect_channel = aim_disconnect_channel, - .rx_completion = aim_rx_data, +static struct core_component comp_info = { + .name = "video", + .probe_channel = comp_probe_channel, + .disconnect_channel = comp_disconnect_channel, + .rx_completion = comp_rx_data, }; -static int __init aim_init(void) +static int __init comp_init(void) { spin_lock_init(&list_lock); - return most_register_component(&aim_info); + return most_register_component(&comp); } -static void __exit aim_exit(void) +static void __exit comp_exit(void) { struct most_video_dev *mdev, *tmp; @@ -590,20 +590,20 @@ static void __exit aim_exit(void) list_del(&mdev->list); spin_unlock_irq(&list_lock); - aim_unregister_videodev(mdev); + comp_unregister_videodev(mdev); v4l2_device_disconnect(&mdev->v4l2_dev); v4l2_device_put(&mdev->v4l2_dev); spin_lock_irq(&list_lock); } spin_unlock_irq(&list_lock); - most_deregister_component(&aim_info); + most_deregister_component(&comp_info); BUG_ON(!list_empty(&video_devices)); } -module_init(aim_init); -module_exit(aim_exit); +module_init(comp_init); +module_exit(comp_exit); -MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore"); +MODULE_DESCRIPTION("V4L2 Component Module for MostCore"); MODULE_AUTHOR("Andrey Shvetsov "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ef0fbbbb9a6004af07bbb76aac718dd6dfc2d80e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:08 +0100 Subject: staging: most: cdev: rename struct aim_channel This patch renames the structure aim_channel to comp_channel. It is needed to complete the process of changing the module designator from AIM to Component. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 2447fbfd201e..7507b38f8e35 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -24,7 +24,7 @@ static struct ida minor_id; static unsigned int major; static struct core_component cdev_aim; -struct aim_channel { +struct comp_channel { wait_queue_head_t wq; spinlock_t unlink; /* synchronization lock to unlink channels */ struct cdev cdev; @@ -40,16 +40,16 @@ struct aim_channel { struct list_head list; }; -#define to_channel(d) container_of(d, struct aim_channel, cdev) +#define to_channel(d) container_of(d, struct comp_channel, cdev) static struct list_head channel_list; static spinlock_t ch_list_lock; -static inline bool ch_has_mbo(struct aim_channel *c) +static inline bool ch_has_mbo(struct comp_channel *c) { return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; } -static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) +static inline bool ch_get_mbo(struct comp_channel *c, struct mbo **mbo) { if (!kfifo_peek(&c->fifo, mbo)) { *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); @@ -59,9 +59,9 @@ static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) return *mbo; } -static struct aim_channel *get_channel(struct most_interface *iface, int id) +static struct comp_channel *get_channel(struct most_interface *iface, int id) { - struct aim_channel *c, *tmp; + struct comp_channel *c, *tmp; unsigned long flags; int found_channel = 0; @@ -78,7 +78,7 @@ static struct aim_channel *get_channel(struct most_interface *iface, int id) return c; } -static void stop_channel(struct aim_channel *c) +static void stop_channel(struct comp_channel *c) { struct mbo *mbo; @@ -87,7 +87,7 @@ static void stop_channel(struct aim_channel *c) most_stop_channel(c->iface, c->channel_id, &cdev_aim); } -static void destroy_cdev(struct aim_channel *c) +static void destroy_cdev(struct comp_channel *c) { unsigned long flags; @@ -98,7 +98,7 @@ static void destroy_cdev(struct aim_channel *c) spin_unlock_irqrestore(&ch_list_lock, flags); } -static void destroy_channel(struct aim_channel *c) +static void destroy_channel(struct comp_channel *c) { ida_simple_remove(&minor_id, MINOR(c->devno)); kfifo_free(&c->fifo); @@ -115,7 +115,7 @@ static void destroy_channel(struct aim_channel *c) */ static int aim_open(struct inode *inode, struct file *filp) { - struct aim_channel *c; + struct comp_channel *c; int ret; c = to_channel(inode->i_cdev); @@ -159,7 +159,7 @@ static int aim_open(struct inode *inode, struct file *filp) */ static int aim_close(struct inode *inode, struct file *filp) { - struct aim_channel *c = to_channel(inode->i_cdev); + struct comp_channel *c = to_channel(inode->i_cdev); mutex_lock(&c->io_mutex); spin_lock(&c->unlink); @@ -188,7 +188,7 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, int ret; size_t to_copy, left; struct mbo *mbo = NULL; - struct aim_channel *c = filp->private_data; + struct comp_channel *c = filp->private_data; mutex_lock(&c->io_mutex); while (c->dev && !ch_get_mbo(c, &mbo)) { @@ -241,7 +241,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { size_t to_copy, not_copied, copied; struct mbo *mbo; - struct aim_channel *c = filp->private_data; + struct comp_channel *c = filp->private_data; mutex_lock(&c->io_mutex); while (c->dev && !kfifo_peek(&c->fifo, &mbo)) { @@ -283,7 +283,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) static unsigned int aim_poll(struct file *filp, poll_table *wait) { - struct aim_channel *c = filp->private_data; + struct comp_channel *c = filp->private_data; unsigned int mask = 0; poll_wait(filp, &c->wq, wait); @@ -320,7 +320,7 @@ static const struct file_operations channel_fops = { */ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) { - struct aim_channel *c; + struct comp_channel *c; if (!iface) { pr_info("Bad interface pointer\n"); @@ -356,7 +356,7 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) */ static int aim_rx_completion(struct mbo *mbo) { - struct aim_channel *c; + struct comp_channel *c; if (!mbo) return -EINVAL; @@ -389,7 +389,7 @@ static int aim_rx_completion(struct mbo *mbo) */ static int aim_tx_completion(struct most_interface *iface, int channel_id) { - struct aim_channel *c; + struct comp_channel *c; if (!iface) { pr_info("Bad interface pointer\n"); @@ -421,7 +421,7 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) static int aim_probe(struct most_interface *iface, int channel_id, struct most_channel_config *cfg, char *name) { - struct aim_channel *c; + struct comp_channel *c; unsigned long cl_flags; int retval; int current_minor; @@ -534,7 +534,7 @@ dest_ida: static void __exit mod_exit(void) { - struct aim_channel *c, *tmp; + struct comp_channel *c, *tmp; pr_info("exit module\n"); -- cgit v1.2.3 From 90c8d77fcb24d7611cfff5931fcd8f0a3b756c3a Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:09 +0100 Subject: staging: most: cdev: rename variable aim_devno This patch renames the variable aim_devno to comp_devno. It is needed to complete the process of changing the module designator from AIM to Component. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 7507b38f8e35..e39fca614593 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -18,7 +18,7 @@ #include #include "most/core.h" -static dev_t aim_devno; +static dev_t comp_devno; static struct class *aim_class; static struct ida minor_id; static unsigned int major; @@ -507,10 +507,10 @@ static int __init mod_init(void) spin_lock_init(&ch_list_lock); ida_init(&minor_id); - err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev"); + err = alloc_chrdev_region(&comp_devno, 0, 50, "cdev"); if (err < 0) goto dest_ida; - major = MAJOR(aim_devno); + major = MAJOR(comp_devno); aim_class = class_create(THIS_MODULE, "most_cdev_aim"); if (IS_ERR(aim_class)) { @@ -526,7 +526,7 @@ static int __init mod_init(void) dest_class: class_destroy(aim_class); free_cdev: - unregister_chrdev_region(aim_devno, 1); + unregister_chrdev_region(comp_devno, 1); dest_ida: ida_destroy(&minor_id); return err; @@ -545,7 +545,7 @@ static void __exit mod_exit(void) destroy_channel(c); } class_destroy(aim_class); - unregister_chrdev_region(aim_devno, 1); + unregister_chrdev_region(comp_devno, 1); ida_destroy(&minor_id); } -- cgit v1.2.3 From eaf03a2875bdd85c3b0cf45cea5844bdf6f2dc79 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:10 +0100 Subject: staging: most: cdev: rename class instance aim_class This patch renames the instance aim_class of struct class to comp_class. It is needed to complete the process of changing the module designator from AIM to Component. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index e39fca614593..dfc6a6abbd54 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -19,7 +19,7 @@ #include "most/core.h" static dev_t comp_devno; -static struct class *aim_class; +static struct class *comp_class; static struct ida minor_id; static unsigned int major; static struct core_component cdev_aim; @@ -91,7 +91,7 @@ static void destroy_cdev(struct comp_channel *c) { unsigned long flags; - device_destroy(aim_class, c->devno); + device_destroy(comp_class, c->devno); cdev_del(&c->cdev); spin_lock_irqsave(&ch_list_lock, flags); list_del(&c->list); @@ -464,7 +464,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, spin_lock_irqsave(&ch_list_lock, cl_flags); list_add_tail(&c->list, &channel_list); spin_unlock_irqrestore(&ch_list_lock, cl_flags); - c->dev = device_create(aim_class, + c->dev = device_create(comp_class, NULL, c->devno, NULL, @@ -512,10 +512,10 @@ static int __init mod_init(void) goto dest_ida; major = MAJOR(comp_devno); - aim_class = class_create(THIS_MODULE, "most_cdev_aim"); - if (IS_ERR(aim_class)) { + comp_class = class_create(THIS_MODULE, "most_cdev_aim"); + if (IS_ERR(comp_class)) { pr_err("no udev support\n"); - err = PTR_ERR(aim_class); + err = PTR_ERR(comp_class); goto free_cdev; } err = most_register_component(&cdev_aim); @@ -524,7 +524,7 @@ static int __init mod_init(void) return 0; dest_class: - class_destroy(aim_class); + class_destroy(comp_class); free_cdev: unregister_chrdev_region(comp_devno, 1); dest_ida: @@ -544,7 +544,7 @@ static void __exit mod_exit(void) destroy_cdev(c); destroy_channel(c); } - class_destroy(aim_class); + class_destroy(comp_class); unregister_chrdev_region(comp_devno, 1); ida_destroy(&minor_id); } -- cgit v1.2.3 From 6822ba8a6739011f37a51f18c159ce5d35681cc6 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:11 +0100 Subject: staging: most: cdev: rename variable cdev_aim This patch renames the variable cdev_aim to cdev_comp. It is needed to complete the process of changing the module designator from AIM to Component. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index dfc6a6abbd54..8a4ed753beae 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -22,7 +22,7 @@ static dev_t comp_devno; static struct class *comp_class; static struct ida minor_id; static unsigned int major; -static struct core_component cdev_aim; +static struct core_component cdev_comp; struct comp_channel { wait_queue_head_t wq; @@ -46,13 +46,13 @@ static spinlock_t ch_list_lock; static inline bool ch_has_mbo(struct comp_channel *c) { - return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; + return channel_has_mbo(c->iface, c->channel_id, &cdev_comp) > 0; } static inline bool ch_get_mbo(struct comp_channel *c, struct mbo **mbo) { if (!kfifo_peek(&c->fifo, mbo)) { - *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_comp); if (*mbo) kfifo_in(&c->fifo, mbo, 1); } @@ -84,7 +84,7 @@ static void stop_channel(struct comp_channel *c) while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) most_put_mbo(mbo); - most_stop_channel(c->iface, c->channel_id, &cdev_aim); + most_stop_channel(c->iface, c->channel_id, &cdev_comp); } static void destroy_cdev(struct comp_channel *c) @@ -143,7 +143,7 @@ static int aim_open(struct inode *inode, struct file *filp) } c->mbo_offs = 0; - ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); + ret = most_start_channel(c->iface, c->channel_id, &cdev_comp); if (!ret) c->access_ref = 1; mutex_unlock(&c->io_mutex); @@ -489,7 +489,7 @@ error_alloc_channel: return retval; } -static struct core_component cdev_aim = { +static struct core_component cdev_comp = { .name = "cdev", .probe_channel = aim_probe, .disconnect_channel = aim_disconnect_channel, @@ -512,13 +512,13 @@ static int __init mod_init(void) goto dest_ida; major = MAJOR(comp_devno); - comp_class = class_create(THIS_MODULE, "most_cdev_aim"); + comp_class = class_create(THIS_MODULE, "most_cdev_comp"); if (IS_ERR(comp_class)) { pr_err("no udev support\n"); err = PTR_ERR(comp_class); goto free_cdev; } - err = most_register_component(&cdev_aim); + err = most_register_component(&cdev_comp); if (err) goto dest_class; return 0; @@ -538,7 +538,7 @@ static void __exit mod_exit(void) pr_info("exit module\n"); - most_deregister_component(&cdev_aim); + most_deregister_component(&cdev_comp); list_for_each_entry_safe(c, tmp, &channel_list, list) { destroy_cdev(c); -- cgit v1.2.3 From b7937dc41362f73cb1ed228fdd3ac32a69b17794 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:12 +0100 Subject: staging: most: fix comment sections This patch updates and corrects the comment sections of the code. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 4 +- drivers/staging/most/core.c | 108 ++++++++++++++++--------------------- drivers/staging/most/core.h | 39 ++++++-------- drivers/staging/most/net/net.c | 4 +- drivers/staging/most/sound/sound.c | 2 +- drivers/staging/most/video/video.c | 4 +- 6 files changed, 70 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 8a4ed753beae..266e2bb6ecf7 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * cdev.c - Application interfacing module for character devices + * cdev.c - Character device component for Mostcore * * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG */ @@ -553,4 +553,4 @@ module_init(mod_init); module_exit(mod_exit); MODULE_AUTHOR("Christian Gromm "); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("character device AIM for mostcore"); +MODULE_DESCRIPTION("character device component for mostcore"); diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 174c88a4bd9e..29dc89c85e33 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -103,14 +103,9 @@ static const struct { _mbo; \ }) -/* ___ ___ - * ___C H A N N E L___ - */ - /** * most_free_mbo_coherent - free an MBO and its coherent buffer - * @mbo: buffer to be released - * + * @mbo: most buffer */ static void most_free_mbo_coherent(struct mbo *mbo) { @@ -469,9 +464,6 @@ static const struct attribute_group *channel_attr_groups[] = { NULL, }; -/* ___ ___ - * ___I N S T A N C E___ - */ static ssize_t description_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -528,9 +520,6 @@ static const struct attribute_group *interface_attr_groups[] = { NULL, }; -/* ___ ___ - * ___A I M___ - */ static struct core_component *match_module(char *name) { struct core_component *comp; @@ -588,26 +577,26 @@ static ssize_t modules_show(struct device_driver *drv, char *buf) return offs; } /** - * split_string - parses and changes string in the buffer buf and - * splits it into two mandatory and one optional substrings. + * split_string - parses buf and extracts ':' separated substrings. * * @buf: complete string from attribute 'add_channel' - * @a: address of pointer to 1st substring (=instance name) - * @b: address of pointer to 2nd substring (=channel name) - * @c: optional address of pointer to 3rd substring (=user defined name) + * @a: storage for 1st substring (=interface name) + * @b: storage for 2nd substring (=channel name) + * @c: storage for 3rd substring (=component name) + * @d: storage optional 4th substring (=user defined name) * * Examples: * - * Input: "mdev0:ch6:my_channel\n" or - * "mdev0:ch6:my_channel" + * Input: "mdev0:ch6:cdev:my_channel\n" or + * "mdev0:ch6:cdev:my_channel" * - * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel" + * Output: *a -> "mdev0", *b -> "ch6", *c -> "cdev" *d -> "my_channel" * - * Input: "mdev1:ep81\n" - * Output: *a -> "mdev1", *b -> "ep81", *c -> "" + * Input: "mdev1:ep81:cdev\n" + * Output: *a -> "mdev1", *b -> "ep81", *c -> "cdev" *d -> "" * * Input: "mdev1:ep81" - * Output: *a -> "mdev1", *b -> "ep81", *c == NULL + * Output: *a -> "mdev1", *b -> "ep81", *c -> "cdev" *d == NULL */ static int split_string(char *buf, char **a, char **b, char **c, char **d) { @@ -637,11 +626,9 @@ static int match_bus_dev(struct device *dev, void *data) } /** - * get_channel - get pointer to channel object - * @mdev: name of the device instance - * @mdev_ch: name of the respective channel - * - * This retrieves the pointer to a channel object. + * get_channel - get pointer to channel + * @mdev: name of the device interface + * @mdev_ch: name of channel */ static struct most_channel *get_channel(char *mdev, char *mdev_ch) { @@ -687,23 +674,22 @@ inline int link_channel_to_component(struct most_channel *c, } /** - * add_link_store - store() function for add_link attribute - * @aim_obj: pointer to AIM object - * @attr: its attributes + * add_link_store - store function for add_link attribute + * @drv: device driver * @buf: buffer * @len: buffer length * * This parses the string given by buf and splits it into - * three substrings. Note: third substring is optional. In case a cdev - * AIM is loaded the optional 3rd substring will make up the name of + * four substrings. Note: last substring is optional. In case a cdev + * component is loaded the optional 4th substring will make up the name of * device node in the /dev directory. If omitted, the device node will * inherit the channel's name within sysfs. * - * Searches for a pair of device and channel and probes the AIM + * Searches for (device, channel) pair and probes the component * * Example: - * (1) echo "mdev0:ch6:my_rxchannel" >add_link - * (2) echo "mdev1:ep81" >add_link + * (1) echo "mdev0:ch6:cdev:my_rxchannel" >add_link + * (2) echo "mdev1:ep81:cdev" >add_link * * (1) would create the device node /dev/my_rxchannel * (2) would create the device node /dev/mdev1-ep81 @@ -748,8 +734,7 @@ static ssize_t add_link_store(struct device_driver *drv, /** * remove_link_store - store function for remove_link attribute - * @aim_obj: pointer to AIM object - * @attr: its attributes + * @drv: device driver * @buf: buffer * @len: buffer length * @@ -811,10 +796,6 @@ static const struct attribute_group *module_attr_groups[] = { NULL, }; -/* ___ ___ - * ___C O R E___ - */ - int most_match(struct device *dev, struct device_driver *drv) { if (!strcmp(dev_name(dev), "most")) @@ -913,14 +894,14 @@ static int run_enqueue_thread(struct most_channel *c, int channel_id) /** * arm_mbo - recycle MBO for further usage - * @mbo: buffer object + * @mbo: most buffer * * This puts an MBO back to the list to have it ready for up coming * tx transactions. * * In case the MBO belongs to a channel that recently has been * poisoned, the MBO is scheduled to be trashed. - * Calls the completion handler of an attached AIM. + * Calls the completion handler of an attached component. */ static void arm_mbo(struct mbo *mbo) { @@ -1007,7 +988,7 @@ _exit: /** * most_submit_mbo - submits an MBO to fifo - * @mbo: pointer to the MBO + * @mbo: most buffer */ void most_submit_mbo(struct mbo *mbo) { @@ -1021,7 +1002,7 @@ EXPORT_SYMBOL_GPL(most_submit_mbo); /** * most_write_completion - write completion handler - * @mbo: pointer to MBO + * @mbo: most buffer * * This recycles the MBO for further usage. In case the channel has been * poisoned, the MBO is scheduled to be trashed. @@ -1067,6 +1048,7 @@ EXPORT_SYMBOL_GPL(channel_has_mbo); * most_get_mbo - get pointer to an MBO of pool * @iface: pointer to interface instance * @id: channel ID + * @comp: driver component * * This attempts to get a free buffer out of the channel fifo. * Returns a pointer to MBO on success or NULL otherwise. @@ -1112,7 +1094,7 @@ EXPORT_SYMBOL_GPL(most_get_mbo); /** * most_put_mbo - return buffer to pool - * @mbo: buffer object + * @mbo: most buffer */ void most_put_mbo(struct mbo *mbo) { @@ -1129,13 +1111,13 @@ EXPORT_SYMBOL_GPL(most_put_mbo); /** * most_read_completion - read completion handler - * @mbo: pointer to MBO + * @mbo: most buffer * * This function is called by the HDM when data has been received from the * hardware and copied to the buffer of the MBO. * * In case the channel has been poisoned it puts the buffer in the trash queue. - * Otherwise, it passes the buffer to an AIM for further processing. + * Otherwise, it passes the buffer to an component for further processing. */ static void most_read_completion(struct mbo *mbo) { @@ -1170,6 +1152,7 @@ static void most_read_completion(struct mbo *mbo) * most_start_channel - prepares a channel for communication * @iface: pointer to interface instance * @id: channel ID + * @comp: driver component * * This prepares the channel for usage. Cross-checks whether the * channel's been properly configured. @@ -1188,7 +1171,7 @@ int most_start_channel(struct most_interface *iface, int id, mutex_lock(&c->start_mutex); if (c->pipe0.refs + c->pipe1.refs > 0) - goto out; /* already started by other comp */ + goto out; /* already started by another component */ if (!try_module_get(iface->mod)) { pr_info("failed to acquire HDM lock\n"); @@ -1245,6 +1228,7 @@ EXPORT_SYMBOL_GPL(most_start_channel); * most_stop_channel - stops a running channel * @iface: pointer to interface instance * @id: channel ID + * @comp: driver component */ int most_stop_channel(struct most_interface *iface, int id, struct core_component *comp) @@ -1302,17 +1286,17 @@ out: EXPORT_SYMBOL_GPL(most_stop_channel); /** - * most_register_component - registers an AIM (driver) with the core - * @aim: instance of AIM to be registered + * most_register_component - registers a driver component with the core + * @comp: driver component */ int most_register_component(struct core_component *comp) { if (!comp) { - pr_err("Bad driver\n"); + pr_err("Bad component\n"); return -EINVAL; } list_add_tail(&comp->list, &mc.comp_list); - pr_info("registered new application interfacing module %s\n", comp->name); + pr_info("registered new core component %s\n", comp->name); return 0; } EXPORT_SYMBOL_GPL(most_register_component); @@ -1336,19 +1320,19 @@ static int disconnect_channels(struct device *dev, void *data) } /** - * most_deregister_component - deregisters an AIM (driver) with the core - * @aim: AIM to be removed + * most_deregister_component - deregisters a driver component with the core + * @comp: driver component */ int most_deregister_component(struct core_component *comp) { if (!comp) { - pr_err("Bad driver\n"); + pr_err("Bad component\n"); return -EINVAL; } bus_for_each_dev(&mc.bus, NULL, comp, disconnect_channels); list_del(&comp->list); - pr_info("deregistering module %s\n", comp->name); + pr_info("deregistering component %s\n", comp->name); return 0; } EXPORT_SYMBOL_GPL(most_deregister_component); @@ -1365,7 +1349,7 @@ static void release_channel(struct device *dev) /** * most_register_interface - registers an interface with core - * @iface: pointer to the instance of the interface description. + * @iface: device interface * * Allocates and initializes a new interface instance and all of its channels. * Returns a pointer to kobject or an error pointer. @@ -1451,7 +1435,7 @@ int most_register_interface(struct most_interface *iface) mutex_init(&c->nq_mutex); list_add_tail(&c->list, &iface->p->channel_list); } - pr_info("registered new MOST device mdev%d (%s)\n", + pr_info("registered new device mdev%d (%s)\n", id, iface->description); return 0; @@ -1473,7 +1457,7 @@ EXPORT_SYMBOL_GPL(most_register_interface); /** * most_deregister_interface - deregisters an interface with core - * @iface: pointer to the interface instance description. + * @iface: device interface * * Before removing an interface instance from the list, all running * channels are stopped and poisoned. @@ -1483,7 +1467,7 @@ void most_deregister_interface(struct most_interface *iface) int i; struct most_channel *c; - pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description); + pr_info("deregistering device %s (%s)\n", dev_name(&iface->dev), iface->description); for (i = 0; i < iface->num_channels; i++) { c = iface->p->channel[i]; if (c->pipe0.comp) diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 5a3a5c5c3347..52db7fa15f65 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -1,18 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 /* - * most.h - Interface between MostCore, - * Hardware Dependent Module (HDM) and Application Interface Module (AIM). + * most.h - API for component and adapter drivers * * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG */ -/* - * Authors: - * Andrey Shvetsov - * Christian Gromm - * Sebastian Graf - */ - #ifndef __MOST_CORE_H__ #define __MOST_CORE_H__ @@ -74,22 +66,22 @@ enum mbo_status_flags { * The value is bitwise OR-combination of the values from the * enumeration most_channel_data_type. Zero is allowed value and means * "channel may not be used". - * @num_buffer_packet: Maximum number of buffers supported by this channel + * @num_buffers_packet: Maximum number of buffers supported by this channel * for packet data types (Async,Control,QoS) * @buffer_size_packet: Maximum buffer size supported by this channel * for packet data types (Async,Control,QoS) - * @num_buffer_streaming: Maximum number of buffers supported by this channel + * @num_buffers_streaming: Maximum number of buffers supported by this channel * for streaming data types (Sync,AV Packetized) * @buffer_size_streaming: Maximum buffer size supported by this channel * for streaming data types (Sync,AV Packetized) * @name_suffix: Optional suffix providean by an HDM that is attached to the * regular channel name. * - * Describes the capabilities of a MostCore channel like supported Data Types + * Describes the capabilities of a MOST channel like supported Data Types * and directions. This information is provided by an HDM for the MostCore. * * The Core creates read only sysfs attribute files in - * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the + * /sys/devices/most/mdev#// with the * following attributes: * -available_directions * -available_datatypes @@ -124,7 +116,7 @@ struct most_channel_capability { * @packets_per_xact: number of MOST frames that are packet inside one USB * packet. This is USB specific * - * Describes the configuration for a MostCore channel. This information is + * Describes the configuration for a MOST channel. This information is * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a * parameter of the "configure" function call. */ @@ -148,6 +140,7 @@ struct most_channel_config { * * @list: list head for use by the mbo's current owner * @ifp: (in) associated interface instance + * @num_buffers_ptr: amount of pool buffers * @hdm_channel_id: (in) HDM channel instance * @virt_address: (in) kernel virtual address of the buffer * @bus_address: (in) bus address of the buffer @@ -156,15 +149,15 @@ struct most_channel_config { * @status: (out) transfer status * @complete: (in) completion routine * - * The MostCore allocates and initializes the MBO. + * The core allocates and initializes the MBO. * - * The HDM receives MBO for transfer from MostCore with the call to enqueue(). + * The HDM receives MBO for transfer from the core with the call to enqueue(). * The HDM copies the data to- or from the buffer depending on configured * channel direction, set "processed_length" and "status" and completes * the transfer procedure by calling the completion routine. * - * At the end the MostCore deallocates the MBO or recycles it for further - * transfers for the same or different HDM. + * Finally, the MBO is being deallocated or recycled for further + * transfers of the same or a different HDM. * * Directions of usage: * The core driver should never access any MBO fields (even if marked @@ -197,10 +190,12 @@ struct mbo { /** * Interface instance description. * - * Describes one instance of an interface like Medusa PCIe or Vantage USB. + * Describes an interface of a MOST device the core driver is bound to. * This structure is allocated and initialized in the HDM. MostCore may not * modify this structure. * + * @dev: the actual device + * @mod: module * @interface Interface type. \sa most_interface_type. * @description PRELIMINARY. * Unique description of the device instance from point of view of the @@ -255,13 +250,13 @@ struct most_interface { #define to_most_interface(d) container_of(d, struct most_interface, dev) /** - * struct most_aim - identifies MOST device driver to mostcore - * @name: Driver name + * struct core_component - identifies a loadable component for the mostcore + * @list: list_head + * @name: component name * @probe_channel: function for core to notify driver about channel connection * @disconnect_channel: callback function to disconnect a certain channel * @rx_completion: completion handler for received packets * @tx_completion: completion handler for transmitted packets - * @context: context pointer to be used by mostcore */ struct core_component { struct list_head list; diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index 38d6fe94ac6b..33606584e50e 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Networking component - Networking Application Interface Module for MostCore + * net.c - Networking component for Mostcore * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG */ @@ -557,4 +557,4 @@ module_init(most_net_init); module_exit(most_net_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Andrey Shvetsov "); -MODULE_DESCRIPTION("Networking Application Interface Module for MostCore"); +MODULE_DESCRIPTION("Networking Component Module for Mostcore"); diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index e93b8047561c..83cec21c85b8 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -755,4 +755,4 @@ module_exit(audio_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Gromm "); -MODULE_DESCRIPTION("Audio Application Interface Module for MostCore"); +MODULE_DESCRIPTION("Sound Component Module for Mostcore"); diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 62b789e71399..4be1e0dc9dd2 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * V4L2 Component - V4L2 Application Interface Module for MostCore + * video.c - V4L2 component for Mostcore * * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG */ @@ -604,6 +604,6 @@ static void __exit comp_exit(void) module_init(comp_init); module_exit(comp_exit); -MODULE_DESCRIPTION("V4L2 Component Module for MostCore"); +MODULE_DESCRIPTION("V4L2 Component Module for Mostcore"); MODULE_AUTHOR("Andrey Shvetsov "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From fdbdc0e6fe496ad3690be5b3c5c2dba1953ed976 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:13 +0100 Subject: staging: most: core: denote modules as components Substrings containing 'module' are replaced with 'component' by this patch. It is needed to complete the process of changing the module designator from AIM to Component. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 29dc89c85e33..600007e7f55c 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -520,7 +520,7 @@ static const struct attribute_group *interface_attr_groups[] = { NULL, }; -static struct core_component *match_module(char *name) +static struct core_component *match_component(char *name) { struct core_component *comp; @@ -565,7 +565,7 @@ static ssize_t links_show(struct device_driver *drv, char *buf) return strlen(buf); } -static ssize_t modules_show(struct device_driver *drv, char *buf) +static ssize_t components_show(struct device_driver *drv, char *buf) { struct core_component *comp; int offs = 0; @@ -714,7 +714,7 @@ static ssize_t add_link_store(struct device_driver *drv, ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, &comp_param); if (ret) return ret; - comp = match_module(comp_name); + comp = match_component(comp_name); if (!comp_param || *comp_param == 0) { snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, mdev_ch); @@ -758,7 +758,7 @@ static ssize_t remove_link_store(struct device_driver *drv, ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, NULL); if (ret) return ret; - comp = match_module(comp_name); + comp = match_component(comp_name); c = get_channel(mdev, mdev_ch); if (!c) return -ENODEV; @@ -775,24 +775,24 @@ static ssize_t remove_link_store(struct device_driver *drv, #define DRV_ATTR(_name) (&driver_attr_##_name.attr) static DRIVER_ATTR_RO(links); -static DRIVER_ATTR_RO(modules); +static DRIVER_ATTR_RO(components); static DRIVER_ATTR_WO(add_link); static DRIVER_ATTR_WO(remove_link); -static struct attribute *module_attrs[] = { +static struct attribute *mc_attrs[] = { DRV_ATTR(links), - DRV_ATTR(modules), + DRV_ATTR(components), DRV_ATTR(add_link), DRV_ATTR(remove_link), NULL, }; -static struct attribute_group module_attr_group = { - .attrs = module_attrs, +static struct attribute_group mc_attr_group = { + .attrs = mc_attrs, }; -static const struct attribute_group *module_attr_groups[] = { - &module_attr_group, +static const struct attribute_group *mc_attr_groups[] = { + &mc_attr_group, NULL, }; @@ -1552,7 +1552,7 @@ static int __init most_init(void) mc.bus.match = most_match, mc.drv.name = "most_core", mc.drv.bus = &mc.bus, - mc.drv.groups = module_attr_groups; + mc.drv.groups = mc_attr_groups; err = bus_register(&mc.bus); if (err) { -- cgit v1.2.3 From 7e0d35423350d118982096d151140616bbad147d Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:14 +0100 Subject: staging: most: core: fix formatting This patch fixes coding style violations. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 7 +------ drivers/staging/most/video/video.c | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 600007e7f55c..839e6cf4fbc0 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -277,7 +277,6 @@ static ssize_t set_number_of_buffers_store(struct device *dev, size_t count) { struct most_channel *c = to_channel(dev); - int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); if (ret) @@ -663,13 +662,11 @@ inline int link_channel_to_component(struct most_channel *c, return -ENOSPC; *comp_ptr = comp; - ret = comp->probe_channel(c->iface, c->channel_id, - &c->cfg, comp_param); + ret = comp->probe_channel(c->iface, c->channel_id, &c->cfg, comp_param); if (ret) { *comp_ptr = NULL; return ret; } - return 0; } @@ -710,7 +707,6 @@ static ssize_t add_link_store(struct device_driver *drv, size_t max_len = min_t(size_t, len + 1, STRING_SIZE); strlcpy(buffer, buf, max_len); - ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, &comp_param); if (ret) return ret; @@ -728,7 +724,6 @@ static ssize_t add_link_store(struct device_driver *drv, ret = link_channel_to_component(c, comp, comp_param); if (ret) return ret; - return len; } diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 4be1e0dc9dd2..098873851646 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -541,7 +541,7 @@ err_unreg: } static int comp_disconnect_channel(struct most_interface *iface, - int channel_idx) + int channel_idx) { struct most_video_dev *mdev = get_comp_dev(iface, channel_idx); -- cgit v1.2.3 From 8f20f2dca8b390b4fe9e40ed6196c805a3f07b66 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:15 +0100 Subject: staging: most: usb: clear functional stall on OUT endpoint For the MOST packet channel there are two dedicated USB endpoints. But internally the hardware has actually one channel for data forwarding from and to MOST. To have the hardware clean up its state machine correctly in case of an error, both USB pipes need to be reset. This patch triggers the host to also clear the OUT endpoint's halt condition in case an IN endpoint has signaled to be stalled. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/usb/usb.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index 87e7fec2af8a..1169635454f3 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -809,6 +809,21 @@ static void wq_clear_halt(struct work_struct *wq_obj) if (usb_clear_halt(mdev->usb_device, pipe)) dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); + /* If the functional Stall condition has been set on an + * asynchronous rx channel, we need to clear the tx channel + * too, since the hardware runs its clean-up sequence on both + * channels, as they are physically one on the network. + * + * The USB interface that exposes the asynchronous channels + * contains always two endpoints, and two only. + */ + if (mdev->conf[channel].data_type == MOST_CH_ASYNC && + mdev->conf[channel].direction == MOST_CH_RX) { + int peer = 1 - channel; + int snd_pipe = usb_sndbulkpipe(mdev->usb_device, + mdev->ep_address[peer]); + usb_clear_halt(mdev->usb_device, snd_pipe); + } mdev->is_channel_healthy[channel] = true; most_resume_enqueue(&mdev->iface, channel); mutex_unlock(&mdev->io_mutex); -- cgit v1.2.3 From 4e6d561d51f91ad465e127b6b5fabf1f1db01fc5 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:16 +0100 Subject: staging: most: core: fix data type This patch fixes the type used to manage the channels of an registered MOST interface. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 52db7fa15f65..74a29163b68a 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -232,7 +232,7 @@ struct most_interface { struct module *mod; enum most_interface_type interface; const char *description; - int num_channels; + unsigned int num_channels; struct most_channel_capability *channel_vector; int (*configure)(struct most_interface *iface, int channel_idx, struct most_channel_config *channel_config); -- cgit v1.2.3 From 3ba5515bf4eecbec08fedde5e35bdabb153c83be Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:17 +0100 Subject: staging: most: core: check value returned by match function This patch adds a check for the pointer returned by the function match_component. It is needed to prevent a NULL pointer dereference in case the provided component name does not match any list entry. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 839e6cf4fbc0..6e7dcb5999bd 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -711,6 +711,8 @@ static ssize_t add_link_store(struct device_driver *drv, if (ret) return ret; comp = match_component(comp_name); + if (!comp) + return -ENODEV; if (!comp_param || *comp_param == 0) { snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, mdev_ch); @@ -754,6 +756,8 @@ static ssize_t remove_link_store(struct device_driver *drv, if (ret) return ret; comp = match_component(comp_name); + if (!comp) + return -ENODEV; c = get_channel(mdev, mdev_ch); if (!c) return -ENODEV; -- cgit v1.2.3 From 2525ef557c731d463914db2e52fc48fa6a407fe5 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 21 Nov 2017 15:05:18 +0100 Subject: staging: most: update driver usage file This patch keeps the usage file up to date. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- .../staging/most/Documentation/driver_usage.txt | 192 +++++++++++---------- 1 file changed, 105 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/Documentation/driver_usage.txt b/drivers/staging/most/Documentation/driver_usage.txt index a4dc0c348fbc..bb9b4e870199 100644 --- a/drivers/staging/most/Documentation/driver_usage.txt +++ b/drivers/staging/most/Documentation/driver_usage.txt @@ -23,20 +23,29 @@ audio/video streaming. Therefore, the driver perfectly fits to the mission of Automotive Grade Linux to create open source software solutions for automotive applications. -The driver consists basically of three layers. The hardware layer, the -core layer and the application layer. The core layer consists of the core -module only. This module handles the communication flow through all three -layers, the configuration of the driver, the configuration interface -representation in sysfs, and the buffer management. -For each of the other two layers a selection of modules is provided. These -modules can arbitrarily be combined to meet the needs of the desired -system architecture. A module of the hardware layer is referred to as an -HDM (hardware dependent module). Each module of this layer handles exactly -one of the peripheral interfaces of a network interface controller (e.g. -USB, MediaLB, I2C). A module of the application layer is referred to as an -AIM (application interfacing module). The modules of this layer give access -to MOST via one the following ways: character devices, ALSA, Networking or -V4L2. +The MOST driver uses module stacking to divide the associated modules into +three layers. From bottom up these layers are: the adapter layer, the core +layer and the application layer. The core layer implements the MOST +subsystem and consists basically of the module core.c and its API. It +registers the MOST bus with the kernel's device model, handles the data +routing through all three layers, the configuration of the driver, the +representation of the configuration interface in sysfs and the buffer +management. + +For each of the other two layers a set of modules is provided. Those can be +arbitrarily combined with the core to meet the connectivity of the desired +system architecture. + +A module of the adapter layer is basically a device driver for a different +subsystem. It is registered with the core to connect the MOST subsystem to +the attached network interface controller hardware. Hence, a given module +of this layer is designed to handle exactly one of the peripheral +interfaces (e.g. USB, MediaLB, I2C) the hardware provides. + +A module of the application layer is referred to as a core comoponent, +which kind of extends the core by providing connectivity to the user space. +Applications, then, can access a MOST network via character devices, an +ALSA soundcard, a Network adapter or a V4L2 capture device. To physically access MOST, an Intelligent Network Interface Controller (INIC) is needed. For more information on available controllers visit: @@ -44,15 +53,14 @@ www.microchip.com - Section 1.1 Hardware Layer + Section 1.1 Adapter Layer -The hardware layer contains so called hardware dependent modules (HDM). For each -peripheral interface the hardware supports the driver has a suitable module -that handles the interface. - -The HDMs encapsulate the peripheral interface specific knowledge of the driver -and provides an easy way of extending the number of supported interfaces. -Currently the following HDMs are available: +The adapter layer contains a pool of device drivers. For each peripheral +interface the hardware supports there is one suitable module that handles +the interface. Adapter drivers encapsulate the peripheral interface +specific knowledge of the MOST driver stack and provide an easy way of +extending the number of supported interfaces. Currently the following +interfaces are available: 1) MediaLB (DIM2) Host wants to communicate with hardware via MediaLB. @@ -63,26 +71,34 @@ Currently the following HDMs are available: 3) USB Host wants to communicate with the hardware via USB. +Once an adapter driver recognizes a MOST device being attached, it +registers it with the core, which, in turn, assigns the necessary members +of the embedded struct device (e.g. the bus this device belongs to and +attribute groups) and registers it with the kernel's device model. - Section 1.2 Core Layer - -The core layer contains the mostcore module only, which processes the driver -configuration via sysfs, buffer management and data forwarding. + Section 1.2 Core Layer +This layer implements the MOST subsystem. It contains the core module and +the header file most.h that exposes the API of the core. When inserted in +the kernel, it registers the MOST bus_type with the kernel's device model +and registers itself as a device driver for this bus. Besides these meta +tasks the core populates the configuration directory for a registered MOST +device (represented by struct most_interface) in sysfs and processes the +configuration of the device's interface. The core layer also handles the +buffer management and the data/message routing. - Section 1.2 Application Layer -The application layer contains so called application interfacing modules (AIM). -Depending on how the driver should interface to the application, one or more -suitable modules can be selected. + Section 1.3 Application Layer -The AIMs encapsulate the application interface specific knowledge of the driver -and provides access to user space or other kernel subsystems. -Currently the following AIMs are available +This layer contains a pool of device drivers that are components of the +core designed to make up the userspace experience of the MOST driver stack. +Depending on how an application is meant to interface the driver, one or +more modules of this pool can be registered with the core. Currently the +following components are available 1) Character Device - Applications can access the driver by means of character devices. + Userspace can access the driver by means of character devices. 2) Networking Standard networking applications (e.g. iperf) can by used to access @@ -97,84 +113,86 @@ Currently the following AIMs are available used to access the driver via the ALSA subsystem. + Section 2 Usage of the MOST Driver - Section 2 Configuration + Section 2.1 Configuration -See ABI/sysfs-class-most.txt +See ABI/sysfs-bus-most.txt + Section 2.2 Routing Channels - Section 3 USB Padding +To connect a configured channel to a certain core component and make it +accessible for user space applications, the driver attribute 'add_link' is +used. The configuration string passed to it has the following format: -When transceiving synchronous or isochronous data, the number of packets per USB -transaction and the sub-buffer size need to be configured. These values -are needed for the driver to process buffer padding, as expected by hardware, -which is for performance optimization purposes of the USB transmission. + "device_name:channel_name:component_name:link_name[.param]" -When transmitting synchronous data the allocated channel width needs to be -written to 'set_subbuffer_size'. Additionally, the number of MOST frames that -should travel to the host within one USB transaction need to be written to -'packets_per_xact'. +It is the concatenation of up to four substrings separated by a colon. The +substrings contain the names of the MOST interface, the channel, the +component driver and a custom name with which the link is going to be +referenced with. Since some components need additional information, the +link name can be extended with a component-specific parameter (separated by +a dot). In case the character device component is loaded, the handle would +also appear as a device node in the /dev directory. -Internally the synchronous threshold is calculated as follows: +Cdev component example: + $ echo "mdev0:ep_81:cdev:my_rx_channel" >$(DRV_DIR)/add_link - frame_size = set_subbuffer_size * packets_per_xact -In case 'packets_per_xact' is set to 0xFF the maximum number of packets, -allocated within one MOST frame, is calculated that fit into _one_ 512 byte -USB full packet. +Sound component example: - frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync +The sound component needs an additional parameter to determine the audio +resolution that is going to be used. The following formats are available: -This frame_size is the number of synchronous data within an USB transaction, -which renders MTU_USB - frame_size bytes for padding. + - "1x8" (Mono) + - "2x16" (16-bit stereo) + - "2x24" (24-bit stereo) + - "2x32" (32-bit stereo) + - "6x16" (16-bit surround 5.1) -When transmitting isochronous AVP data the desired packet size needs to be -written to 'set_subbuffer_size' and hardware will always expect two isochronous -packets within one USB transaction. This renders + $ echo "mdev0:ep_81:sound:most51_playback.6x16" >$(DRV_DIR)/add_link - MTU_USB - (2 * set_subbuffer_size) -bytes for padding. - -Note that at least 2 times set_subbuffer_size bytes for isochronous data or -set_subbuffer_size times packts_per_xact bytes for synchronous data need to be -put in the transmission buffer and passed to the driver. -Since HDMs are allowed to change a chosen configuration to best fit its -constraints, it is recommended to always double check the configuration and read -back the previously written files. + Section 2.3 USB Padding +When transceiving synchronous or isochronous data, the number of packets +per USB transaction and the sub-buffer size need to be configured. These +values are needed for the driver to process buffer padding, as expected by +hardware, which is for performance optimization purposes of the USB +transmission. +When transmitting synchronous data the allocated channel width needs to be +written to 'set_subbuffer_size'. Additionally, the number of MOST frames +that should travel to the host within one USB transaction need to be +written to 'packets_per_xact'. - Section 4 Routing Channels +The driver, then, calculates the synchronous threshold as follows: -To connect a channel that has been configured as outlined above to an AIM and -make it accessible to user space applications, the attribute file 'add_link' is -used. To actually bind a channel to the AIM a string needs to be written to the -file that complies with the following syntax: + frame_size = set_subbuffer_size * packets_per_xact - "most_device:channel_name:link_name[.param]" +In case 'packets_per_xact' is set to 0xFF the maximum number of packets, +allocated within one MOST frame, is calculated that fit into _one_ 512 byte +USB full packet. -The example above links the channel "channel_name" of the device "most_device" -to the AIM. In case the AIM interfaces the VFS this would also create a device -node "link_name" in the /dev directory. The parameter "param" is an AIM dependent -string, which can be omitted in case the used AIM does not make any use of it. + frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync -Cdev AIM example: - $ echo "mdev0:ep_81:my_rx_channel" >add_link - $ echo "mdev0:ep_81" >add_link +This frame_size is the number of synchronous data within an USB +transaction, which renders MTU_USB - frame_size bytes for padding. +When transmitting isochronous AVP data the desired packet size needs to be +written to 'set_subbuffer_size' and hardware will always expect two +isochronous packets within one USB transaction. This renders -Sound/ALSA AIM example: + MTU_USB - (2 * set_subbuffer_size) -The sound/ALSA AIM needs an additional parameter to determine the audio resolution -that is going to be used. The following strings can be used: +bytes for padding. - - "1x8" (Mono) - - "2x16" (16-bit stereo) - - "2x24" (24-bit stereo) - - "2x32" (32-bit stereo) +Note that at least (2 * set_subbuffer_size) bytes for isochronous data or +(set_subbuffer_size * packts_per_xact) bytes for synchronous data need to +be put in the transmission buffer and passed to the driver. - $ echo "mdev0:ep_81:audio_rx.2x16" >add_link - $ echo "mdev0:ep_81" >add_link +Since adapter drivers are allowed to change a chosen configuration to best +fit its constraints, it is recommended to always double check the +configuration and read back the previously written files. -- cgit v1.2.3 From 1fd923f38610a802f4b6f4dc30ada9c80cd52d9e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:19 +0100 Subject: staging: most: cdev: replace function prefix This patch replaces the function prefixes aim_* with comp_*. It is needed to complete the process of changing the module designator from AIM to Component. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 266e2bb6ecf7..6f58eee5c8d5 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -106,14 +106,14 @@ static void destroy_channel(struct comp_channel *c) } /** - * aim_open - implements the syscall to open the device + * comp_open - implements the syscall to open the device * @inode: inode pointer * @filp: file pointer * * This stores the channel pointer in the private data field of * the file structure and activates the channel within the core. */ -static int aim_open(struct inode *inode, struct file *filp) +static int comp_open(struct inode *inode, struct file *filp) { struct comp_channel *c; int ret; @@ -151,13 +151,13 @@ static int aim_open(struct inode *inode, struct file *filp) } /** - * aim_close - implements the syscall to close the device + * comp_close - implements the syscall to close the device * @inode: inode pointer * @filp: file pointer * * This stops the channel within the core. */ -static int aim_close(struct inode *inode, struct file *filp) +static int comp_close(struct inode *inode, struct file *filp) { struct comp_channel *c = to_channel(inode->i_cdev); @@ -176,14 +176,14 @@ static int aim_close(struct inode *inode, struct file *filp) } /** - * aim_write - implements the syscall to write to the device + * comp_write - implements the syscall to write to the device * @filp: file pointer * @buf: pointer to user buffer * @count: number of bytes to write * @offset: offset from where to start writing */ -static ssize_t aim_write(struct file *filp, const char __user *buf, - size_t count, loff_t *offset) +static ssize_t comp_write(struct file *filp, const char __user *buf, + size_t count, loff_t *offset) { int ret; size_t to_copy, left; @@ -230,14 +230,14 @@ unlock: } /** - * aim_read - implements the syscall to read from the device + * comp_read - implements the syscall to read from the device * @filp: file pointer * @buf: pointer to user buffer * @count: number of bytes to read * @offset: offset from where to start reading */ static ssize_t -aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) +comp_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { size_t to_copy, not_copied, copied; struct mbo *mbo; @@ -281,7 +281,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) return copied; } -static unsigned int aim_poll(struct file *filp, poll_table *wait) +static unsigned int comp_poll(struct file *filp, poll_table *wait) { struct comp_channel *c = filp->private_data; unsigned int mask = 0; @@ -303,22 +303,22 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait) */ static const struct file_operations channel_fops = { .owner = THIS_MODULE, - .read = aim_read, - .write = aim_write, - .open = aim_open, - .release = aim_close, - .poll = aim_poll, + .read = comp_read, + .write = comp_write, + .open = comp_open, + .release = comp_close, + .poll = comp_poll, }; /** - * aim_disconnect_channel - disconnect a channel + * comp_disconnect_channel - disconnect a channel * @iface: pointer to interface instance * @channel_id: channel index * * This frees allocated memory and removes the cdev that represents this * channel in user space. */ -static int aim_disconnect_channel(struct most_interface *iface, int channel_id) +static int comp_disconnect_channel(struct most_interface *iface, int channel_id) { struct comp_channel *c; @@ -348,13 +348,13 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) } /** - * aim_rx_completion - completion handler for rx channels + * comp_rx_completion - completion handler for rx channels * @mbo: pointer to buffer object that has completed * * This searches for the channel linked to this MBO and stores it in the local * fifo buffer. */ -static int aim_rx_completion(struct mbo *mbo) +static int comp_rx_completion(struct mbo *mbo) { struct comp_channel *c; @@ -381,13 +381,13 @@ static int aim_rx_completion(struct mbo *mbo) } /** - * aim_tx_completion - completion handler for tx channels + * comp_tx_completion - completion handler for tx channels * @iface: pointer to interface instance * @channel_id: channel index/ID * * This wakes sleeping processes in the wait-queue. */ -static int aim_tx_completion(struct most_interface *iface, int channel_id) +static int comp_tx_completion(struct most_interface *iface, int channel_id) { struct comp_channel *c; @@ -408,7 +408,7 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) } /** - * aim_probe - probe function of the driver module + * comp_probe - probe function of the driver module * @iface: pointer to interface instance * @channel_id: channel index/ID * @cfg: pointer to actual channel configuration @@ -418,8 +418,8 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) * * Returns 0 on success or error code otherwise. */ -static int aim_probe(struct most_interface *iface, int channel_id, - struct most_channel_config *cfg, char *name) +static int comp_probe(struct most_interface *iface, int channel_id, + struct most_channel_config *cfg, char *name) { struct comp_channel *c; unsigned long cl_flags; @@ -427,7 +427,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, int current_minor; if ((!iface) || (!cfg) || (!name)) { - pr_info("Probing AIM with bad arguments"); + pr_info("Probing component with bad arguments"); return -EINVAL; } c = get_channel(iface, channel_id); @@ -491,10 +491,10 @@ error_alloc_channel: static struct core_component cdev_comp = { .name = "cdev", - .probe_channel = aim_probe, - .disconnect_channel = aim_disconnect_channel, - .rx_completion = aim_rx_completion, - .tx_completion = aim_tx_completion, + .probe_channel = comp_probe, + .disconnect_channel = comp_disconnect_channel, + .rx_completion = comp_rx_completion, + .tx_completion = comp_tx_completion, }; static int __init mod_init(void) -- cgit v1.2.3 From c73d915dd293a42f45df1d1c19fc85f93ba48784 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:20 +0100 Subject: staging: most: cdev: bundle module variables in structure This patch creates the structure comp to put the module variables for encapsulation purposes. For an improved readability some variables are renamed. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 88 ++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 6f58eee5c8d5..dd9456fd2cd6 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -18,11 +18,13 @@ #include #include "most/core.h" -static dev_t comp_devno; -static struct class *comp_class; -static struct ida minor_id; -static unsigned int major; -static struct core_component cdev_comp; +static struct cdev_component { + dev_t devno; + struct ida minor_id; + unsigned int major; + struct class *class; + struct core_component cc; +} comp; struct comp_channel { wait_queue_head_t wq; @@ -46,13 +48,13 @@ static spinlock_t ch_list_lock; static inline bool ch_has_mbo(struct comp_channel *c) { - return channel_has_mbo(c->iface, c->channel_id, &cdev_comp) > 0; + return channel_has_mbo(c->iface, c->channel_id, &comp.cc) > 0; } static inline bool ch_get_mbo(struct comp_channel *c, struct mbo **mbo) { if (!kfifo_peek(&c->fifo, mbo)) { - *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_comp); + *mbo = most_get_mbo(c->iface, c->channel_id, &comp.cc); if (*mbo) kfifo_in(&c->fifo, mbo, 1); } @@ -84,14 +86,14 @@ static void stop_channel(struct comp_channel *c) while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) most_put_mbo(mbo); - most_stop_channel(c->iface, c->channel_id, &cdev_comp); + most_stop_channel(c->iface, c->channel_id, &comp.cc); } static void destroy_cdev(struct comp_channel *c) { unsigned long flags; - device_destroy(comp_class, c->devno); + device_destroy(comp.class, c->devno); cdev_del(&c->cdev); spin_lock_irqsave(&ch_list_lock, flags); list_del(&c->list); @@ -100,7 +102,7 @@ static void destroy_cdev(struct comp_channel *c) static void destroy_channel(struct comp_channel *c) { - ida_simple_remove(&minor_id, MINOR(c->devno)); + ida_simple_remove(&comp.minor_id, MINOR(c->devno)); kfifo_free(&c->fifo); kfree(c); } @@ -143,7 +145,7 @@ static int comp_open(struct inode *inode, struct file *filp) } c->mbo_offs = 0; - ret = most_start_channel(c->iface, c->channel_id, &cdev_comp); + ret = most_start_channel(c->iface, c->channel_id, &comp.cc); if (!ret) c->access_ref = 1; mutex_unlock(&c->io_mutex); @@ -434,7 +436,7 @@ static int comp_probe(struct most_interface *iface, int channel_id, if (c) return -EEXIST; - current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL); + current_minor = ida_simple_get(&comp.minor_id, 0, 0, GFP_KERNEL); if (current_minor < 0) return current_minor; @@ -444,7 +446,7 @@ static int comp_probe(struct most_interface *iface, int channel_id, goto error_alloc_channel; } - c->devno = MKDEV(major, current_minor); + c->devno = MKDEV(comp.major, current_minor); cdev_init(&c->cdev, &channel_fops); c->cdev.owner = THIS_MODULE; cdev_add(&c->cdev, c->devno, 1); @@ -464,11 +466,7 @@ static int comp_probe(struct most_interface *iface, int channel_id, spin_lock_irqsave(&ch_list_lock, cl_flags); list_add_tail(&c->list, &channel_list); spin_unlock_irqrestore(&ch_list_lock, cl_flags); - c->dev = device_create(comp_class, - NULL, - c->devno, - NULL, - "%s", name); + c->dev = device_create(comp.class, NULL, c->devno, NULL, "%s", name); if (IS_ERR(c->dev)) { retval = PTR_ERR(c->dev); @@ -485,16 +483,18 @@ error_alloc_kfifo: cdev_del(&c->cdev); kfree(c); error_alloc_channel: - ida_simple_remove(&minor_id, current_minor); + ida_simple_remove(&comp.minor_id, current_minor); return retval; } -static struct core_component cdev_comp = { - .name = "cdev", - .probe_channel = comp_probe, - .disconnect_channel = comp_disconnect_channel, - .rx_completion = comp_rx_completion, - .tx_completion = comp_tx_completion, +static struct cdev_component comp = { + .cc = { + .name = "cdev", + .probe_channel = comp_probe, + .disconnect_channel = comp_disconnect_channel, + .rx_completion = comp_rx_completion, + .tx_completion = comp_tx_completion, + }, }; static int __init mod_init(void) @@ -503,32 +503,30 @@ static int __init mod_init(void) pr_info("init()\n"); + comp.class = class_create(THIS_MODULE, "most_cdev"); + if (IS_ERR(comp.class)) { + pr_info("No udev support.\n"); + return PTR_ERR(comp.class); + } + INIT_LIST_HEAD(&channel_list); spin_lock_init(&ch_list_lock); - ida_init(&minor_id); + ida_init(&comp.minor_id); - err = alloc_chrdev_region(&comp_devno, 0, 50, "cdev"); + err = alloc_chrdev_region(&comp.devno, 0, 50, "cdev"); if (err < 0) goto dest_ida; - major = MAJOR(comp_devno); - - comp_class = class_create(THIS_MODULE, "most_cdev_comp"); - if (IS_ERR(comp_class)) { - pr_err("no udev support\n"); - err = PTR_ERR(comp_class); - goto free_cdev; - } - err = most_register_component(&cdev_comp); + comp.major = MAJOR(comp.devno); + err = most_register_component(&comp.cc); if (err) - goto dest_class; + goto free_cdev; return 0; -dest_class: - class_destroy(comp_class); free_cdev: - unregister_chrdev_region(comp_devno, 1); + unregister_chrdev_region(comp.devno, 1); dest_ida: - ida_destroy(&minor_id); + ida_destroy(&comp.minor_id); + class_destroy(comp.class); return err; } @@ -538,15 +536,15 @@ static void __exit mod_exit(void) pr_info("exit module\n"); - most_deregister_component(&cdev_comp); + most_deregister_component(&comp.cc); list_for_each_entry_safe(c, tmp, &channel_list, list) { destroy_cdev(c); destroy_channel(c); } - class_destroy(comp_class); - unregister_chrdev_region(comp_devno, 1); - ida_destroy(&minor_id); + unregister_chrdev_region(comp.devno, 1); + ida_destroy(&comp.minor_id); + class_destroy(comp.class); } module_init(mod_init); -- cgit v1.2.3 From eb9e2bc80d1451b116f9964a84a49f89d38b1e05 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:21 +0100 Subject: staging: most: core: remove class generation This patch stops the core from generating a module owned class and registering it with the kernel. It is needed, because there is no need for a default MOST class to be present in the kernel. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 6e7dcb5999bd..bfd1a028ccad 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -33,7 +33,6 @@ static struct mostcore { struct device dev; struct device_driver drv; struct bus_type bus; - struct class *class; struct list_head comp_list; } mc; @@ -1558,17 +1557,10 @@ static int __init most_init(void) pr_info("Cannot register most bus\n"); return err; } - mc.class = class_create(THIS_MODULE, "most"); - if (IS_ERR(mc.class)) { - pr_info("No udev support.\n"); - err = PTR_ERR(mc.class); - goto exit_bus; - } - err = driver_register(&mc.drv); if (err) { pr_info("Cannot register core driver\n"); - goto exit_class; + goto exit_bus; } mc.dev.init_name = "most_bus"; mc.dev.release = release_most_sub; @@ -1581,8 +1573,6 @@ static int __init most_init(void) exit_driver: driver_unregister(&mc.drv); -exit_class: - class_destroy(mc.class); exit_bus: bus_unregister(&mc.bus); return err; @@ -1593,7 +1583,6 @@ static void __exit most_exit(void) pr_info("exit core module\n"); device_unregister(&mc.dev); driver_unregister(&mc.drv); - class_destroy(mc.class); bus_unregister(&mc.bus); ida_destroy(&mdev_id); } -- cgit v1.2.3 From e7e3ce04588c7f4919627f0742bc6cbe832036a4 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Tue, 21 Nov 2017 15:05:22 +0100 Subject: staging: most: core: fix list traversing This patch fixes the offset and data handling when traversing the list of devices that are attached to the bus. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index bfd1a028ccad..c1fba5ba7541 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -529,10 +529,16 @@ static struct core_component *match_component(char *name) return NULL; } +struct show_links_data { + int offs; + char *buf; +}; + int print_links(struct device *dev, void *data) { - int offs = 0; - char *buf = data; + struct show_links_data *d = data; + int offs = d->offs; + char *buf = d->buf; struct most_channel *c; struct most_interface *iface = to_most_interface(dev); @@ -554,13 +560,16 @@ int print_links(struct device *dev, void *data) dev_name(&c->dev)); } } + d->offs = offs; return 0; } static ssize_t links_show(struct device_driver *drv, char *buf) { - bus_for_each_dev(&mc.bus, NULL, buf, print_links); - return strlen(buf); + struct show_links_data d = { .buf = buf }; + + bus_for_each_dev(&mc.bus, NULL, &d, print_links); + return d.offs; } static ssize_t components_show(struct device_driver *drv, char *buf) -- cgit v1.2.3 From b7ed2ff0bb4a896ec4e470a1c4faa88de1a589cc Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:23 +0100 Subject: staging: most: add ABI documentation This patchg adds the sysfs-bus-most.txt file to the source tree. It is needed to have an ABI description of the driver's sysfs interface. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- .../most/Documentation/ABI/sysfs-bus-most.txt | 313 +++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt (limited to 'drivers') diff --git a/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt new file mode 100644 index 000000000000..d8fa841e3742 --- /dev/null +++ b/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt @@ -0,0 +1,313 @@ +What: /sys/bus/most/devices/.../description +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Provides information about the interface type and the physical + location of the device. Hardware attached via USB, for instance, + might return +Users: + +What: /sys/bus/most/devices/.../interface +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the type of peripheral interface the device uses. +Users: + +What: /sys/bus/most/devices/.../dci +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + If the network interface controller is attached via USB, a dci + directory is created that allows applications to read and + write the controller's DCI registers. +Users: + +What: /sys/bus/most/devices/.../dci/arb_address +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to set an arbitrary DCI register address an + application wants to read from or write to. +Users: + +What: /sys/bus/most/devices/.../dci/arb_value +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to read and write the DCI register whose address + is stored in arb_address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_eui48_hi +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_eui48_lo +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_eui48_mi +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_filter +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP filter address. +Users: + +What: /sys/bus/most/devices/.../dci/mep_hash0 +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/bus/most/devices/.../dci/mep_hash1 +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/bus/most/devices/.../dci/mep_hash2 +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/bus/most/devices/.../dci/mep_hash3 +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/bus/most/devices/.../dci/ni_state +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the current network interface state. +Users: + +What: /sys/bus/most/devices/.../dci/node_address +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the current node address. +Users: + +What: /sys/bus/most/devices/.../dci/node_position +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the current node position. +Users: + +What: /sys/bus/most/devices/.../dci/packet_bandwidth +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the configured packet bandwidth. +Users: + +What: /sys/bus/most/devices/.../dci/sync_ep +Date: June 2016 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Triggers the controller's synchronization process for a certain + endpoint. +Users: + +What: /sys/bus/most/devices/...// +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + For every channel of the device a directory is created, whose + name is dictated by the HDM. This enables an application to + collect information about the channel's capabilities and + configure it. +Users: + +What: /sys/bus/most/devices/...//available_datatypes +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the data types the current channel can transport. +Users: + +What: /sys/bus/most/devices/...//available_directions +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the directions the current channel is capable of. +Users: + +What: /sys/bus/most/devices/...//number_of_packet_buffers +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the number of packet buffers the current channel can + handle. +Users: + +What: /sys/bus/most/devices/...//number_of_stream_buffers +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the number of streaming buffers the current channel can + handle. +Users: + +What: /sys/bus/most/devices/...//size_of_packet_buffer +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the size of a packet buffer the current channel can + handle. +Users: + +What: /sys/bus/most/devices/...//size_of_stream_buffer +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates the size of a streaming buffer the current channel can + handle. +Users: + +What: /sys/bus/most/devices/...//set_number_of_buffers +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is to configure the number of buffers of the current channel. +Users: + +What: /sys/bus/most/devices/...//set_buffer_size +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is to configure the size of a buffer of the current channel. +Users: + +What: /sys/bus/most/devices/...//set_direction +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is to configure the direction of the current channel. + The following strings will be accepted: + 'dir_tx', + 'dir_rx' +Users: + +What: /sys/bus/most/devices/...//set_datatype +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is to configure the data type of the current channel. + The following strings will be accepted: + 'control', + 'async', + 'sync', + 'isoc_avp' +Users: + +What: /sys/bus/most/devices/...//set_subbuffer_size +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is to configure the subbuffer size of the current channel. +Users: + +What: /sys/bus/most/devices/...//set_packets_per_xact +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is to configure the number of packets per transaction of + the current channel. This is only needed network interface + controller is attached via USB. +Users: + +What: /sys/bus/most/devices/...//channel_starving +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + Indicates whether current channel ran out of buffers. +Users: + +What: /sys/bus/most/drivers/mostcore/add_link +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to link a channel to a component of the + mostcore. A link created by writing to this file is + referred to as pipe. +Users: + +What: /sys/bus/most/drivers/mostcore/remove_link +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to unlink a channel from a component. +Users: + +What: /sys/bus/most/drivers/mostcore/components +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to retrieve a list of registered components. +Users: + +What: /sys/bus/most/drivers/mostcore/links +Date: March 2017 +KernelVersion: 4.15 +Contact: Christian Gromm +Description: + This is used to retrieve a list of established links. +Users: -- cgit v1.2.3 From 3d9c54b5f9177049f9edeb1227bdab7adf77686f Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 21 Nov 2017 15:05:24 +0100 Subject: staging: most: usb: fix show/store function names This patch renames the show/store functions of the USB module. It is needed to make the module meet the established naming convention. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/usb/usb.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index 1169635454f3..c72e9c3bacec 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -887,7 +887,7 @@ static int get_stat_reg_addr(const struct regs *regs, int size, #define get_static_reg_addr(regs, name, reg_addr) \ get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr) -static ssize_t show_value(struct device *dev, struct device_attribute *attr, +static ssize_t value_show(struct device *dev, struct device_attribute *attr, char *buf) { const char *name = attr->attr.name; @@ -912,7 +912,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%04x\n", val); } -static ssize_t store_value(struct device *dev, struct device_attribute *attr, +static ssize_t value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u16 val; @@ -945,21 +945,21 @@ static ssize_t store_value(struct device *dev, struct device_attribute *attr, return count; } -DEVICE_ATTR(ni_state, 0444, show_value, NULL); -DEVICE_ATTR(packet_bandwidth, 0444, show_value, NULL); -DEVICE_ATTR(node_address, 0444, show_value, NULL); -DEVICE_ATTR(node_position, 0444, show_value, NULL); -DEVICE_ATTR(sync_ep, 0200, NULL, store_value); -DEVICE_ATTR(mep_filter, 0644, show_value, store_value); -DEVICE_ATTR(mep_hash0, 0644, show_value, store_value); -DEVICE_ATTR(mep_hash1, 0644, show_value, store_value); -DEVICE_ATTR(mep_hash2, 0644, show_value, store_value); -DEVICE_ATTR(mep_hash3, 0644, show_value, store_value); -DEVICE_ATTR(mep_eui48_hi, 0644, show_value, store_value); -DEVICE_ATTR(mep_eui48_mi, 0644, show_value, store_value); -DEVICE_ATTR(mep_eui48_lo, 0644, show_value, store_value); -DEVICE_ATTR(arb_address, 0644, show_value, store_value); -DEVICE_ATTR(arb_value, 0644, show_value, store_value); +DEVICE_ATTR(ni_state, 0444, value_show, NULL); +DEVICE_ATTR(packet_bandwidth, 0444, value_show, NULL); +DEVICE_ATTR(node_address, 0444, value_show, NULL); +DEVICE_ATTR(node_position, 0444, value_show, NULL); +DEVICE_ATTR(sync_ep, 0200, NULL, value_store); +DEVICE_ATTR(mep_filter, 0644, value_show, value_store); +DEVICE_ATTR(mep_hash0, 0644, value_show, value_store); +DEVICE_ATTR(mep_hash1, 0644, value_show, value_store); +DEVICE_ATTR(mep_hash2, 0644, value_show, value_store); +DEVICE_ATTR(mep_hash3, 0644, value_show, value_store); +DEVICE_ATTR(mep_eui48_hi, 0644, value_show, value_store); +DEVICE_ATTR(mep_eui48_mi, 0644, value_show, value_store); +DEVICE_ATTR(mep_eui48_lo, 0644, value_show, value_store); +DEVICE_ATTR(arb_address, 0644, value_show, value_store); +DEVICE_ATTR(arb_value, 0644, value_show, value_store); static struct attribute *dci_attrs[] = { &dev_attr_ni_state.attr, -- cgit v1.2.3 From ef7e70ae9943c92ea09b2200c0e43aba0d47c4b7 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 30 Oct 2017 15:59:27 +1100 Subject: staging: lustre: ldlm: use list_first_entry in ldlm_lock This make the code (slightly) more readable. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 7cb61e2e7d3b..48363a80dade 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1687,7 +1687,7 @@ ldlm_work_bl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) if (list_empty(arg->list)) return -ENOENT; - lock = list_entry(arg->list->next, struct ldlm_lock, l_bl_ast); + lock = list_first_entry(arg->list, struct ldlm_lock, l_bl_ast); /* nobody should touch l_bl_ast */ lock_res_and_lock(lock); @@ -1723,7 +1723,7 @@ ldlm_work_cp_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) if (list_empty(arg->list)) return -ENOENT; - lock = list_entry(arg->list->next, struct ldlm_lock, l_cp_ast); + lock = list_first_entry(arg->list, struct ldlm_lock, l_cp_ast); /* It's possible to receive a completion AST before we've set * the l_completion_ast pointer: either because the AST arrived @@ -1769,7 +1769,7 @@ ldlm_work_revoke_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) if (list_empty(arg->list)) return -ENOENT; - lock = list_entry(arg->list->next, struct ldlm_lock, l_rk_ast); + lock = list_first_entry(arg->list, struct ldlm_lock, l_rk_ast); list_del_init(&lock->l_rk_ast); /* the desc just pretend to exclusive */ @@ -1796,7 +1796,7 @@ static int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) if (list_empty(arg->list)) return -ENOENT; - gl_work = list_entry(arg->list->next, struct ldlm_glimpse_work, + gl_work = list_first_entry(arg->list, struct ldlm_glimpse_work, gl_list); list_del_init(&gl_work->gl_list); -- cgit v1.2.3 From 557d001aa51fd6171d7a68dec21f8327fc824173 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 30 Oct 2017 15:59:27 +1100 Subject: staging: lustre: ldlm: use list_for_each_entry in ldlm_lock.c This makes some slightly-confusing code a bit clearer, and avoids the need for 'tmp'. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 48363a80dade..7cbc6a06afec 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -886,17 +886,15 @@ static void search_granted_lock(struct list_head *queue, struct ldlm_lock *req, struct sl_insert_point *prev) { - struct list_head *tmp; struct ldlm_lock *lock, *mode_end, *policy_end; - list_for_each(tmp, queue) { - lock = list_entry(tmp, struct ldlm_lock, l_res_link); + list_for_each_entry(lock, queue, l_res_link) { mode_end = list_prev_entry(lock, l_sl_mode); if (lock->l_req_mode != req->l_req_mode) { /* jump to last lock of mode group */ - tmp = &mode_end->l_res_link; + lock = mode_end; continue; } @@ -933,9 +931,7 @@ static void search_granted_lock(struct list_head *queue, break; /* go to next policy group within mode group */ - tmp = policy_end->l_res_link.next; - lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + lock = list_next_entry(policy_end, l_res_link); } /* loop over policy groups within the mode group */ /* insert point is last lock of the mode group, -- cgit v1.2.3 From dff162689a4061ff30d3a05f9d790e375c06ab8f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 30 Oct 2017 15:59:27 +1100 Subject: staging: lustre: simplfy lov_finish_set() When deleting everything from a list, a while loop is cleaner than list_for_each_safe(). Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_request.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 3bdf48e4edb4..cfa1d7f92b0f 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -49,15 +49,13 @@ static void lov_init_set(struct lov_request_set *set) static void lov_finish_set(struct lov_request_set *set) { - struct list_head *pos, *n; + struct lov_request *req; LASSERT(set); - list_for_each_safe(pos, n, &set->set_list) { - struct lov_request *req = list_entry(pos, - struct lov_request, - rq_link); + while ((req = list_first_entry_or_null(&set->set_list, + struct lov_request, + rq_link)) != NULL) { list_del_init(&req->rq_link); - kfree(req->rq_oi.oi_osfs); kfree(req); } -- cgit v1.2.3 From 988b9ea9129bc24baf36ee421feb823285f234c4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 30 Oct 2017 15:59:27 +1100 Subject: staging: lustre: obdclass: simplify cl_lock_fini() Using list_first_entry_or_null() makes this (slightly) simpler. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/cl_lock.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index d415f8396038..3b683b774fef 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -79,13 +79,12 @@ EXPORT_SYMBOL(cl_lock_slice_add); void cl_lock_fini(const struct lu_env *env, struct cl_lock *lock) { + struct cl_lock_slice *slice; cl_lock_trace(D_DLMTRACE, env, "destroy lock", lock); - while (!list_empty(&lock->cll_layers)) { - struct cl_lock_slice *slice; - - slice = list_entry(lock->cll_layers.next, - struct cl_lock_slice, cls_linkage); + while ((slice = list_first_entry_or_null(&lock->cll_layers, + struct cl_lock_slice, + cls_linkage)) != NULL) { list_del_init(lock->cll_layers.next); slice->cls_ops->clo_fini(env, slice); } -- cgit v1.2.3 From e1cb54fd3721d4dfcfe82dc4f48c1d69433cc7f1 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:10 +0000 Subject: staging: ccree: make long func call sites readable The driver was using a function naming scheme including common prefixes for driver global functions based on the code module they came from. The combination of long names with long common prefixes made the whole thing too long for a human to parse. Switch to simple and shorter function naming scheme. Where required, realign parameters and add paranthesis for better code readability. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 32 +-- drivers/staging/ccree/ssi_buffer_mgr.c | 430 ++++++++++++++------------------ drivers/staging/ccree/ssi_buffer_mgr.h | 49 ++-- drivers/staging/ccree/ssi_cipher.c | 13 +- drivers/staging/ccree/ssi_driver.c | 18 +- drivers/staging/ccree/ssi_hash.c | 116 +++++---- drivers/staging/ccree/ssi_ivgen.c | 2 +- drivers/staging/ccree/ssi_pm.c | 26 +- drivers/staging/ccree/ssi_pm.h | 12 +- drivers/staging/ccree/ssi_request_mgr.c | 16 +- drivers/staging/ccree/ssi_request_mgr.h | 6 +- drivers/staging/ccree/ssi_sram_mgr.c | 11 +- drivers/staging/ccree/ssi_sram_mgr.h | 6 +- 13 files changed, 345 insertions(+), 392 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index ba0954e4d2e5..0b5b23036961 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -233,7 +233,7 @@ static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *c struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); int err = 0; - ssi_buffer_mgr_unmap_aead_request(dev, areq); + cc_unmap_aead_request(dev, areq); /* Restore ordinary iv pointer */ areq->iv = areq_ctx->backup_iv; @@ -246,17 +246,20 @@ static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *c /* In case of payload authentication failure, MUST NOT * revealed the decrypted message --> zero its memory. */ - ssi_buffer_mgr_zero_sgl(areq->dst, areq_ctx->cryptlen); + cc_zero_sgl(areq->dst, areq_ctx->cryptlen); err = -EBADMSG; } } else { /*ENCRYPT*/ - if (unlikely(areq_ctx->is_icv_fragmented)) - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->mac_buf, areq_ctx->dst_sgl, - areq->cryptlen + areq_ctx->dst_offset, - (areq->cryptlen + areq_ctx->dst_offset + - ctx->authsize), - SSI_SG_FROM_BUF); + if (unlikely(areq_ctx->is_icv_fragmented)) { + cc_copy_sg_portion(dev, areq_ctx->mac_buf, + areq_ctx->dst_sgl, + (areq->cryptlen + + areq_ctx->dst_offset), + (areq->cryptlen + + areq_ctx->dst_offset + + ctx->authsize), + SSI_SG_FROM_BUF); + } /* If an IV was generated, copy it back to the user provided buffer. */ if (areq_ctx->backup_giv) { @@ -2053,7 +2056,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction } #endif /*SSI_CC_HAS_AES_GCM*/ - rc = ssi_buffer_mgr_map_aead_request(ctx->drvdata, req); + rc = cc_map_aead_request(ctx->drvdata, req); if (unlikely(rc != 0)) { dev_err(dev, "map_request() failed\n"); goto exit; @@ -2112,7 +2115,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction #endif default: dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode); - ssi_buffer_mgr_unmap_aead_request(dev, req); + cc_unmap_aead_request(dev, req); rc = -ENOTSUPP; goto exit; } @@ -2123,7 +2126,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_aead_request(dev, req); + cc_unmap_aead_request(dev, req); } exit: @@ -2753,8 +2756,9 @@ int ssi_aead_alloc(struct ssi_drvdata *drvdata) INIT_LIST_HEAD(&aead_handle->aead_list); drvdata->aead_handle = aead_handle; - aead_handle->sram_workspace_addr = ssi_sram_mgr_alloc( - drvdata, MAX_HMAC_DIGEST_SIZE); + aead_handle->sram_workspace_addr = cc_sram_alloc(drvdata, + MAX_HMAC_DIGEST_SIZE); + if (aead_handle->sram_workspace_addr == NULL_SRAM_ADDR) { dev_err(dev, "SRAM pool exhausted\n"); rc = -ENOMEM; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 1f8a225530a8..2d971f244bcb 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -65,13 +65,13 @@ struct buffer_array { }; /** - * ssi_buffer_mgr_get_sgl_nents() - Get scatterlist number of entries. + * cc_get_sgl_nents() - Get scatterlist number of entries. * * @sg_list: SG list * @nbytes: [IN] Total SGL data bytes. * @lbytes: [OUT] Returns the amount of bytes at the last entry */ -static unsigned int ssi_buffer_mgr_get_sgl_nents( +static unsigned int cc_get_sgl_nents( struct device *dev, struct scatterlist *sg_list, unsigned int nbytes, u32 *lbytes, bool *is_chained) { @@ -95,11 +95,11 @@ static unsigned int ssi_buffer_mgr_get_sgl_nents( } /** - * ssi_buffer_mgr_zero_sgl() - Zero scatter scatter list data. + * cc_zero_sgl() - Zero scatter scatter list data. * * @sgl: */ -void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len) +void cc_zero_sgl(struct scatterlist *sgl, u32 data_len) { struct scatterlist *current_sg = sgl; int sg_index = 0; @@ -116,7 +116,7 @@ void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len) } /** - * ssi_buffer_mgr_copy_scatterlist_portion() - Copy scatter list data, + * cc_copy_sg_portion() - Copy scatter list data, * from to_skip to end, to dest and vice versa * * @dest: @@ -125,19 +125,19 @@ void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len) * @end: * @direct: */ -void ssi_buffer_mgr_copy_scatterlist_portion( +void cc_copy_sg_portion( struct device *dev, u8 *dest, struct scatterlist *sg, u32 to_skip, u32 end, enum ssi_sg_cpy_direct direct) { u32 nents, lbytes; - nents = ssi_buffer_mgr_get_sgl_nents(dev, sg, end, &lbytes, NULL); + nents = cc_get_sgl_nents(dev, sg, end, &lbytes, NULL); sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip + 1), to_skip, (direct == SSI_SG_TO_BUF)); } -static inline int ssi_buffer_mgr_render_buff_to_mlli( +static inline int cc_render_buff_to_mlli( struct device *dev, dma_addr_t buff_dma, u32 buff_size, u32 *curr_nents, u32 **mlli_entry_pp) { @@ -173,7 +173,7 @@ static inline int ssi_buffer_mgr_render_buff_to_mlli( return 0; } -static inline int ssi_buffer_mgr_render_scatterlist_to_mlli( +static inline int cc_render_sg_to_mlli( struct device *dev, struct scatterlist *sgl, u32 sgl_data_len, u32 sgl_offset, u32 *curr_nents, u32 **mlli_entry_pp) @@ -189,9 +189,9 @@ static inline int ssi_buffer_mgr_render_scatterlist_to_mlli( sg_dma_len(curr_sgl) - sgl_offset : sgl_data_len; sgl_data_len -= entry_data_len; - rc = ssi_buffer_mgr_render_buff_to_mlli( - dev, sg_dma_address(curr_sgl) + sgl_offset, - entry_data_len, curr_nents, &mlli_entry_p); + rc = cc_render_buff_to_mlli(dev, sg_dma_address(curr_sgl) + + sgl_offset, entry_data_len, + curr_nents, &mlli_entry_p); if (rc != 0) return rc; @@ -201,7 +201,7 @@ static inline int ssi_buffer_mgr_render_scatterlist_to_mlli( return 0; } -static int ssi_buffer_mgr_generate_mlli( +static int cc_generate_mlli( struct device *dev, struct buffer_array *sg_data, struct mlli_params *mlli_params) @@ -226,15 +226,15 @@ static int ssi_buffer_mgr_generate_mlli( /* go over all SG's and link it to one MLLI table */ for (i = 0; i < sg_data->num_of_buffers; i++) { if (sg_data->type[i] == DMA_SGL_TYPE) - rc = ssi_buffer_mgr_render_scatterlist_to_mlli( - dev, sg_data->entry[i].sgl, - sg_data->total_data_len[i], sg_data->offset[i], - &total_nents, &mlli_p); + rc = cc_render_sg_to_mlli(dev, sg_data->entry[i].sgl, + sg_data->total_data_len[i], + sg_data->offset[i], + &total_nents, &mlli_p); else /*DMA_BUFF_TYPE*/ - rc = ssi_buffer_mgr_render_buff_to_mlli( - dev, sg_data->entry[i].buffer_dma, - sg_data->total_data_len[i], &total_nents, - &mlli_p); + rc = cc_render_buff_to_mlli(dev, + sg_data->entry[i].buffer_dma, + sg_data->total_data_len[i], + &total_nents, &mlli_p); if (rc != 0) return rc; @@ -260,7 +260,7 @@ build_mlli_exit: return rc; } -static inline void ssi_buffer_mgr_add_buffer_entry( +static inline void cc_add_buffer_entry( struct device *dev, struct buffer_array *sgl_data, dma_addr_t buffer_dma, unsigned int buffer_len, bool is_last_entry, u32 *mlli_nents) @@ -281,7 +281,7 @@ static inline void ssi_buffer_mgr_add_buffer_entry( sgl_data->num_of_buffers++; } -static inline void ssi_buffer_mgr_add_scatterlist_entry( +static inline void cc_add_sg_entry( struct device *dev, struct buffer_array *sgl_data, unsigned int nents, @@ -308,8 +308,8 @@ static inline void ssi_buffer_mgr_add_scatterlist_entry( } static int -ssi_buffer_mgr_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents, - enum dma_data_direction direction) +cc_dma_map_sg(struct device *dev, struct scatterlist *sg, u32 nents, + enum dma_data_direction direction) { u32 i, j; struct scatterlist *l_sg = sg; @@ -336,7 +336,7 @@ err: return 0; } -static int ssi_buffer_mgr_map_scatterlist( +static int cc_map_sg( struct device *dev, struct scatterlist *sg, unsigned int nbytes, int direction, u32 *nents, u32 max_sg_nents, @@ -357,8 +357,8 @@ static int ssi_buffer_mgr_map_scatterlist( *nents = 1; *mapped_nents = 1; } else { /*sg_is_last*/ - *nents = ssi_buffer_mgr_get_sgl_nents(dev, sg, nbytes, lbytes, - &is_chained); + *nents = cc_get_sgl_nents(dev, sg, nbytes, lbytes, + &is_chained); if (*nents > max_sg_nents) { *nents = 0; dev_err(dev, "Too many fragments. current %d max %d\n", @@ -379,10 +379,8 @@ static int ssi_buffer_mgr_map_scatterlist( /*In this case the driver maps entry by entry so it * must have the same nents before and after map */ - *mapped_nents = ssi_buffer_mgr_dma_map_sg(dev, - sg, - *nents, - direction); + *mapped_nents = cc_dma_map_sg(dev, sg, *nents, + direction); if (unlikely(*mapped_nents != *nents)) { *nents = *mapped_nents; dev_err(dev, "dma_map_sg() sg buffer failed\n"); @@ -416,10 +414,9 @@ ssi_aead_handle_config_buf(struct device *dev, areq_ctx->ccm_adata_sg.offset, areq_ctx->ccm_adata_sg.length); /* prepare for case of MLLI */ if (assoclen > 0) { - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, 1, - &areq_ctx->ccm_adata_sg, - (AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size), - 0, false, NULL); + cc_add_sg_entry(dev, sg_data, 1, &areq_ctx->ccm_adata_sg, + (AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size), + 0, false, NULL); } return 0; } @@ -446,12 +443,12 @@ static inline int ssi_ahash_handle_curr_buf(struct device *dev, areq_ctx->curr_sg = areq_ctx->buff_sg; areq_ctx->in_nents = 0; /* prepare for case of MLLI */ - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, 1, areq_ctx->buff_sg, - curr_buff_cnt, 0, false, NULL); + cc_add_sg_entry(dev, sg_data, 1, areq_ctx->buff_sg, curr_buff_cnt, 0, + false, NULL); return 0; } -void ssi_buffer_mgr_unmap_blkcipher_request( +void cc_unmap_blkcipher_request( struct device *dev, void *ctx, unsigned int ivsize, @@ -484,7 +481,7 @@ void ssi_buffer_mgr_unmap_blkcipher_request( } } -int ssi_buffer_mgr_map_blkcipher_request( +int cc_map_blkcipher_request( struct ssi_drvdata *drvdata, void *ctx, unsigned int ivsize, @@ -527,11 +524,8 @@ int ssi_buffer_mgr_map_blkcipher_request( } /* Map the src SGL */ - rc = ssi_buffer_mgr_map_scatterlist(dev, src, - nbytes, DMA_BIDIRECTIONAL, - &req_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, - &mapped_nents); + rc = cc_map_sg(dev, src, nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); if (unlikely(rc != 0)) { rc = -ENOMEM; goto ablkcipher_exit; @@ -543,19 +537,16 @@ int ssi_buffer_mgr_map_blkcipher_request( /* Handle inplace operation */ if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) { req_ctx->out_nents = 0; - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - req_ctx->in_nents, - src, nbytes, 0, - true, - &req_ctx->in_mlli_nents); + cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src, + nbytes, 0, true, + &req_ctx->in_mlli_nents); } } else { /* Map the dst sg */ - if (unlikely(ssi_buffer_mgr_map_scatterlist( - dev, dst, nbytes, - DMA_BIDIRECTIONAL, &req_ctx->out_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, - &mapped_nents))){ + if (unlikely(cc_map_sg(dev, dst, nbytes, DMA_BIDIRECTIONAL, + &req_ctx->out_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, + &mapped_nents))) { rc = -ENOMEM; goto ablkcipher_exit; } @@ -563,22 +554,18 @@ int ssi_buffer_mgr_map_blkcipher_request( req_ctx->dma_buf_type = SSI_DMA_BUF_MLLI; if (unlikely((req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI))) { - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - req_ctx->in_nents, - src, nbytes, 0, - true, - &req_ctx->in_mlli_nents); - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - req_ctx->out_nents, - dst, nbytes, 0, - true, - &req_ctx->out_mlli_nents); + cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src, + nbytes, 0, true, + &req_ctx->in_mlli_nents); + cc_add_sg_entry(dev, &sg_data, req_ctx->out_nents, dst, + nbytes, 0, true, + &req_ctx->out_mlli_nents); } } if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; - rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params); + rc = cc_generate_mlli(dev, &sg_data, mlli_params); if (unlikely(rc != 0)) goto ablkcipher_exit; } @@ -589,12 +576,11 @@ int ssi_buffer_mgr_map_blkcipher_request( return 0; ablkcipher_exit: - ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); + cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); return rc; } -void ssi_buffer_mgr_unmap_aead_request( - struct device *dev, struct aead_request *req) +void cc_unmap_aead_request(struct device *dev, struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); unsigned int hw_iv_size = areq_ctx->hw_iv_size; @@ -668,16 +654,15 @@ void ssi_buffer_mgr_unmap_aead_request( size_to_unmap += crypto_aead_ivsize(tfm); dma_unmap_sg(dev, req->src, - ssi_buffer_mgr_get_sgl_nents(dev, req->src, size_to_unmap, - &dummy, &chained), + cc_get_sgl_nents(dev, req->src, size_to_unmap, + &dummy, &chained), DMA_BIDIRECTIONAL); if (unlikely(req->src != req->dst)) { dev_dbg(dev, "Unmapping dst sgl: req->dst=%pK\n", sg_virt(req->dst)); dma_unmap_sg(dev, req->dst, - ssi_buffer_mgr_get_sgl_nents(dev, req->dst, - size_to_unmap, - &dummy, &chained), + cc_get_sgl_nents(dev, req->dst, size_to_unmap, + &dummy, &chained), DMA_BIDIRECTIONAL); } if (drvdata->coherent && @@ -691,14 +676,15 @@ void ssi_buffer_mgr_unmap_aead_request( /* copy mac to a temporary location to deal with possible * data memory overriding that caused by cache coherence problem. */ - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->backup_mac, req->src, - size_to_skip + req->cryptlen - areq_ctx->req_authsize, - size_to_skip + req->cryptlen, SSI_SG_FROM_BUF); + cc_copy_sg_portion(dev, areq_ctx->backup_mac, req->src, + (size_to_skip + req->cryptlen - + areq_ctx->req_authsize), + (size_to_skip + req->cryptlen), + SSI_SG_FROM_BUF); } } -static inline int ssi_buffer_mgr_get_aead_icv_nents( +static inline int cc_get_aead_icv_nents( struct device *dev, struct scatterlist *sgl, unsigned int sgl_nents, @@ -748,7 +734,7 @@ static inline int ssi_buffer_mgr_get_aead_icv_nents( return nents; } -static inline int ssi_buffer_mgr_aead_chain_iv( +static inline int cc_aead_chain_iv( struct ssi_drvdata *drvdata, struct aead_request *req, struct buffer_array *sg_data, @@ -780,11 +766,10 @@ static inline int ssi_buffer_mgr_aead_chain_iv( unsigned int iv_size_to_authenc = crypto_aead_ivsize(tfm); unsigned int iv_ofs = GCM_BLOCK_RFC4_IV_OFFSET; /* Chain to given list */ - ssi_buffer_mgr_add_buffer_entry( - dev, sg_data, - areq_ctx->gen_ctx.iv_dma_addr + iv_ofs, - iv_size_to_authenc, is_last, - &areq_ctx->assoc.mlli_nents); + cc_add_buffer_entry(dev, sg_data, + (areq_ctx->gen_ctx.iv_dma_addr + iv_ofs), + iv_size_to_authenc, is_last, + &areq_ctx->assoc.mlli_nents); areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI; } @@ -792,7 +777,7 @@ chain_iv_exit: return rc; } -static inline int ssi_buffer_mgr_aead_chain_assoc( +static inline int cc_aead_chain_assoc( struct ssi_drvdata *drvdata, struct aead_request *req, struct buffer_array *sg_data, @@ -874,10 +859,9 @@ static inline int ssi_buffer_mgr_aead_chain_assoc( dev_dbg(dev, "Chain assoc: buff_type=%s nents=%u\n", GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), areq_ctx->assoc.nents); - ssi_buffer_mgr_add_scatterlist_entry( - dev, sg_data, areq_ctx->assoc.nents, - req->src, req->assoclen, 0, is_last, - &areq_ctx->assoc.mlli_nents); + cc_add_sg_entry(dev, sg_data, areq_ctx->assoc.nents, req->src, + req->assoclen, 0, is_last, + &areq_ctx->assoc.mlli_nents); areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI; } @@ -885,7 +869,7 @@ chain_assoc_exit: return rc; } -static inline void ssi_buffer_mgr_prepare_aead_data_dlli( +static inline void cc_prepare_aead_data_dlli( struct aead_request *req, u32 *src_last_bytes, u32 *dst_last_bytes) { @@ -921,7 +905,7 @@ static inline void ssi_buffer_mgr_prepare_aead_data_dlli( } } -static inline int ssi_buffer_mgr_prepare_aead_data_mlli( +static inline int cc_prepare_aead_data_mlli( struct ssi_drvdata *drvdata, struct aead_request *req, struct buffer_array *sg_data, @@ -937,20 +921,15 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( if (likely(req->src == req->dst)) { /*INPLACE*/ - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->src.nents, - areq_ctx->src_sgl, - areq_ctx->cryptlen, - areq_ctx->src_offset, - is_last_table, - &areq_ctx->src.mlli_nents); - - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev, - areq_ctx->src_sgl, - areq_ctx->src.nents, - authsize, - *src_last_bytes, - &areq_ctx->is_icv_fragmented); + cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents, + areq_ctx->src_sgl, areq_ctx->cryptlen, + areq_ctx->src_offset, is_last_table, + &areq_ctx->src.mlli_nents); + + icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->src_sgl, + areq_ctx->src.nents, + authsize, *src_last_bytes, + &areq_ctx->is_icv_fragmented); if (unlikely(icv_nents < 0)) { rc = -ENOTSUPP; goto prepare_data_mlli_exit; @@ -973,13 +952,12 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( if (areq_ctx->is_gcm4543) skip += crypto_aead_ivsize(tfm); - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->backup_mac, - req->src, - (skip + req->cryptlen - - areq_ctx->req_authsize), - skip + req->cryptlen, - SSI_SG_TO_BUF); + cc_copy_sg_portion(dev, + areq_ctx->backup_mac, + req->src, + (skip + req->cryptlen - areq_ctx->req_authsize), + (skip + req->cryptlen), + SSI_SG_TO_BUF); } areq_ctx->icv_virt_addr = areq_ctx->backup_mac; } else { @@ -998,27 +976,19 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( } else if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) { /*NON-INPLACE and DECRYPT*/ - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->src.nents, - areq_ctx->src_sgl, - areq_ctx->cryptlen, - areq_ctx->src_offset, - is_last_table, - &areq_ctx->src.mlli_nents); - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->dst.nents, - areq_ctx->dst_sgl, - areq_ctx->cryptlen, - areq_ctx->dst_offset, - is_last_table, - &areq_ctx->dst.mlli_nents); - - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev, - areq_ctx->src_sgl, - areq_ctx->src.nents, - authsize, - *src_last_bytes, - &areq_ctx->is_icv_fragmented); + cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents, + areq_ctx->src_sgl, areq_ctx->cryptlen, + areq_ctx->src_offset, is_last_table, + &areq_ctx->src.mlli_nents); + cc_add_sg_entry(dev, sg_data, areq_ctx->dst.nents, + areq_ctx->dst_sgl, areq_ctx->cryptlen, + areq_ctx->dst_offset, is_last_table, + &areq_ctx->dst.mlli_nents); + + icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->src_sgl, + areq_ctx->src.nents, + authsize, *src_last_bytes, + &areq_ctx->is_icv_fragmented); if (unlikely(icv_nents < 0)) { rc = -ENOTSUPP; goto prepare_data_mlli_exit; @@ -1034,10 +1004,11 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( if (areq_ctx->is_gcm4543) size_to_skip += crypto_aead_ivsize(tfm); - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->backup_mac, req->src, - size_to_skip + req->cryptlen - areq_ctx->req_authsize, - size_to_skip + req->cryptlen, SSI_SG_TO_BUF); + cc_copy_sg_portion(dev, areq_ctx->backup_mac, + req->src, + (size_to_skip + req->cryptlen - areq_ctx->req_authsize), + (size_to_skip + req->cryptlen), + SSI_SG_TO_BUF); areq_ctx->icv_virt_addr = areq_ctx->backup_mac; } else { /* Contig. ICV */ /*Should hanlde if the sg is not contig.*/ @@ -1051,27 +1022,19 @@ static inline int ssi_buffer_mgr_prepare_aead_data_mlli( } else { /*NON-INPLACE and ENCRYPT*/ - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->dst.nents, - areq_ctx->dst_sgl, - areq_ctx->cryptlen, - areq_ctx->dst_offset, - is_last_table, - &areq_ctx->dst.mlli_nents); - ssi_buffer_mgr_add_scatterlist_entry(dev, sg_data, - areq_ctx->src.nents, - areq_ctx->src_sgl, - areq_ctx->cryptlen, - areq_ctx->src_offset, - is_last_table, - &areq_ctx->src.mlli_nents); - - icv_nents = ssi_buffer_mgr_get_aead_icv_nents(dev, - areq_ctx->dst_sgl, - areq_ctx->dst.nents, - authsize, - *dst_last_bytes, - &areq_ctx->is_icv_fragmented); + cc_add_sg_entry(dev, sg_data, areq_ctx->dst.nents, + areq_ctx->dst_sgl, areq_ctx->cryptlen, + areq_ctx->dst_offset, is_last_table, + &areq_ctx->dst.mlli_nents); + cc_add_sg_entry(dev, sg_data, areq_ctx->src.nents, + areq_ctx->src_sgl, areq_ctx->cryptlen, + areq_ctx->src_offset, is_last_table, + &areq_ctx->src.mlli_nents); + + icv_nents = cc_get_aead_icv_nents(dev, areq_ctx->dst_sgl, + areq_ctx->dst.nents, + authsize, *dst_last_bytes, + &areq_ctx->is_icv_fragmented); if (unlikely(icv_nents < 0)) { rc = -ENOTSUPP; goto prepare_data_mlli_exit; @@ -1095,7 +1058,7 @@ prepare_data_mlli_exit: return rc; } -static inline int ssi_buffer_mgr_aead_chain_data( +static inline int cc_aead_chain_data( struct ssi_drvdata *drvdata, struct aead_request *req, struct buffer_array *sg_data, @@ -1131,10 +1094,8 @@ static inline int ssi_buffer_mgr_aead_chain_data( size_for_map += crypto_aead_ivsize(tfm); size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0; - src_mapped_nents = ssi_buffer_mgr_get_sgl_nents(dev, req->src, - size_for_map, - &src_last_bytes, - &chained); + src_mapped_nents = cc_get_sgl_nents(dev, req->src, size_for_map, + &src_last_bytes, &chained); sg_index = areq_ctx->src_sgl->length; //check where the data starts while (sg_index <= size_to_skip) { @@ -1164,22 +1125,18 @@ static inline int ssi_buffer_mgr_aead_chain_data( if (is_gcm4543) size_for_map += crypto_aead_ivsize(tfm); - rc = ssi_buffer_mgr_map_scatterlist(dev, req->dst, size_for_map, - DMA_BIDIRECTIONAL, - &areq_ctx->dst.nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, - &dst_last_bytes, - &dst_mapped_nents); + rc = cc_map_sg(dev, req->dst, size_for_map, DMA_BIDIRECTIONAL, + &areq_ctx->dst.nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes, + &dst_mapped_nents); if (unlikely(rc != 0)) { rc = -ENOMEM; goto chain_data_exit; } } - dst_mapped_nents = ssi_buffer_mgr_get_sgl_nents(dev, req->dst, - size_for_map, - &dst_last_bytes, - &chained); + dst_mapped_nents = cc_get_sgl_nents(dev, req->dst, size_for_map, + &dst_last_bytes, &chained); sg_index = areq_ctx->dst_sgl->length; offset = size_to_skip; @@ -1206,23 +1163,21 @@ static inline int ssi_buffer_mgr_aead_chain_data( (dst_mapped_nents > 1) || do_chain) { areq_ctx->data_buff_type = SSI_DMA_BUF_MLLI; - rc = ssi_buffer_mgr_prepare_aead_data_mlli(drvdata, req, - sg_data, - &src_last_bytes, - &dst_last_bytes, - is_last_table); + rc = cc_prepare_aead_data_mlli(drvdata, req, sg_data, + &src_last_bytes, + &dst_last_bytes, is_last_table); } else { areq_ctx->data_buff_type = SSI_DMA_BUF_DLLI; - ssi_buffer_mgr_prepare_aead_data_dlli( - req, &src_last_bytes, &dst_last_bytes); + cc_prepare_aead_data_dlli(req, &src_last_bytes, + &dst_last_bytes); } chain_data_exit: return rc; } -static void ssi_buffer_mgr_update_aead_mlli_nents(struct ssi_drvdata *drvdata, - struct aead_request *req) +static void cc_update_aead_mlli_nents(struct ssi_drvdata *drvdata, + struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); u32 curr_mlli_size = 0; @@ -1272,7 +1227,7 @@ static void ssi_buffer_mgr_update_aead_mlli_nents(struct ssi_drvdata *drvdata, } } -int ssi_buffer_mgr_map_aead_request( +int cc_map_aead_request( struct ssi_drvdata *drvdata, struct aead_request *req) { struct aead_req_ctx *areq_ctx = aead_request_ctx(req); @@ -1303,10 +1258,10 @@ int ssi_buffer_mgr_map_aead_request( /* copy mac to a temporary location to deal with possible * data memory overriding that caused by cache coherence problem. */ - ssi_buffer_mgr_copy_scatterlist_portion( - dev, areq_ctx->backup_mac, req->src, - size_to_skip + req->cryptlen - areq_ctx->req_authsize, - size_to_skip + req->cryptlen, SSI_SG_TO_BUF); + cc_copy_sg_portion(dev, areq_ctx->backup_mac, req->src, + (size_to_skip + req->cryptlen - areq_ctx->req_authsize), + (size_to_skip + req->cryptlen), + SSI_SG_TO_BUF); } /* cacluate the size for cipher remove ICV in decrypt*/ @@ -1406,9 +1361,11 @@ int ssi_buffer_mgr_map_aead_request( if (is_gcm4543) size_to_map += crypto_aead_ivsize(tfm); - rc = ssi_buffer_mgr_map_scatterlist(dev, req->src, - size_to_map, DMA_BIDIRECTIONAL, &areq_ctx->src.nents, - LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); + rc = cc_map_sg(dev, req->src, size_to_map, DMA_BIDIRECTIONAL, + &areq_ctx->src.nents, + (LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + + LLI_MAX_NUM_OF_DATA_ENTRIES), + &dummy, &mapped_nents); if (unlikely(rc != 0)) { rc = -ENOMEM; goto aead_map_failure; @@ -1421,13 +1378,13 @@ int ssi_buffer_mgr_map_aead_request( * (2) Src/Dst SGLs * Note: IV is contg. buffer (not an SGL) */ - rc = ssi_buffer_mgr_aead_chain_assoc(drvdata, req, &sg_data, true, false); + rc = cc_aead_chain_assoc(drvdata, req, &sg_data, true, false); if (unlikely(rc != 0)) goto aead_map_failure; - rc = ssi_buffer_mgr_aead_chain_iv(drvdata, req, &sg_data, true, false); + rc = cc_aead_chain_iv(drvdata, req, &sg_data, true, false); if (unlikely(rc != 0)) goto aead_map_failure; - rc = ssi_buffer_mgr_aead_chain_data(drvdata, req, &sg_data, true, false); + rc = cc_aead_chain_data(drvdata, req, &sg_data, true, false); if (unlikely(rc != 0)) goto aead_map_failure; } else { /* DOUBLE-PASS flow */ @@ -1451,13 +1408,13 @@ int ssi_buffer_mgr_map_aead_request( * (3) MLLI for src * (4) MLLI for dst */ - rc = ssi_buffer_mgr_aead_chain_assoc(drvdata, req, &sg_data, false, true); + rc = cc_aead_chain_assoc(drvdata, req, &sg_data, false, true); if (unlikely(rc != 0)) goto aead_map_failure; - rc = ssi_buffer_mgr_aead_chain_iv(drvdata, req, &sg_data, false, true); + rc = cc_aead_chain_iv(drvdata, req, &sg_data, false, true); if (unlikely(rc != 0)) goto aead_map_failure; - rc = ssi_buffer_mgr_aead_chain_data(drvdata, req, &sg_data, true, true); + rc = cc_aead_chain_data(drvdata, req, &sg_data, true, true); if (unlikely(rc != 0)) goto aead_map_failure; } @@ -1467,11 +1424,11 @@ int ssi_buffer_mgr_map_aead_request( (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) || (areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI))) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; - rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params); + rc = cc_generate_mlli(dev, &sg_data, mlli_params); if (unlikely(rc != 0)) goto aead_map_failure; - ssi_buffer_mgr_update_aead_mlli_nents(drvdata, req); + cc_update_aead_mlli_nents(drvdata, req); dev_dbg(dev, "assoc params mn %d\n", areq_ctx->assoc.mlli_nents); dev_dbg(dev, "src params mn %d\n", areq_ctx->src.mlli_nents); @@ -1480,12 +1437,13 @@ int ssi_buffer_mgr_map_aead_request( return 0; aead_map_failure: - ssi_buffer_mgr_unmap_aead_request(dev, req); + cc_unmap_aead_request(dev, req); return rc; } -int ssi_buffer_mgr_map_hash_request_final( - struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update) +int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + bool do_update) { struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx; struct device *dev = drvdata_to_dev(drvdata); @@ -1522,12 +1480,10 @@ int ssi_buffer_mgr_map_hash_request_final( } if (src && (nbytes > 0) && do_update) { - if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src, nbytes, - DMA_TO_DEVICE, - &areq_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, - &dummy, - &mapped_nents))){ + if (unlikely(cc_map_sg(dev, src, nbytes, DMA_TO_DEVICE, + &areq_ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, + &dummy, &mapped_nents))) { goto unmap_curr_buff; } if (src && (mapped_nents == 1) @@ -1546,12 +1502,9 @@ int ssi_buffer_mgr_map_hash_request_final( if (unlikely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI)) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; /* add the src data to the sg_data */ - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - areq_ctx->in_nents, - src, nbytes, 0, true, - &areq_ctx->mlli_nents); - if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data, - mlli_params) != 0)) { + cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, nbytes, + 0, true, &areq_ctx->mlli_nents); + if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params) != 0)) { goto fail_unmap_din; } } @@ -1571,8 +1524,9 @@ unmap_curr_buff: return -ENOMEM; } -int ssi_buffer_mgr_map_hash_request_update( - struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, unsigned int block_size) +int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + unsigned int block_size) { struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx; struct device *dev = drvdata_to_dev(drvdata); @@ -1606,8 +1560,7 @@ int ssi_buffer_mgr_map_hash_request_update( dev_dbg(dev, " less than one block: curr_buff=%pK *curr_buff_cnt=0x%X copy_to=%pK\n", curr_buff, *curr_buff_cnt, &curr_buff[*curr_buff_cnt]); areq_ctx->in_nents = - ssi_buffer_mgr_get_sgl_nents(dev, src, nbytes, &dummy, - NULL); + cc_get_sgl_nents(dev, src, nbytes, &dummy, NULL); sg_copy_to_buffer(src, areq_ctx->in_nents, &curr_buff[*curr_buff_cnt], nbytes); *curr_buff_cnt += nbytes; @@ -1627,9 +1580,9 @@ int ssi_buffer_mgr_map_hash_request_update( dev_dbg(dev, " handle residue: next buff %pK skip data %u residue %u\n", next_buff, (update_data_len - *curr_buff_cnt), *next_buff_cnt); - ssi_buffer_mgr_copy_scatterlist_portion(dev, next_buff, src, - (update_data_len - *curr_buff_cnt), - nbytes, SSI_SG_TO_BUF); + cc_copy_sg_portion(dev, next_buff, src, + (update_data_len - *curr_buff_cnt), + nbytes, SSI_SG_TO_BUF); /* change the buffer index for next operation */ swap_index = 1; } @@ -1644,13 +1597,11 @@ int ssi_buffer_mgr_map_hash_request_update( } if (update_data_len > *curr_buff_cnt) { - if (unlikely(ssi_buffer_mgr_map_scatterlist(dev, src, - (update_data_len - *curr_buff_cnt), - DMA_TO_DEVICE, - &areq_ctx->in_nents, - LLI_MAX_NUM_OF_DATA_ENTRIES, - &dummy, - &mapped_nents))){ + if (unlikely(cc_map_sg(dev, src, + (update_data_len - *curr_buff_cnt), + DMA_TO_DEVICE, &areq_ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, + &mapped_nents))) { goto unmap_curr_buff; } if ((mapped_nents == 1) @@ -1669,15 +1620,10 @@ int ssi_buffer_mgr_map_hash_request_update( if (unlikely(areq_ctx->data_dma_buf_type == SSI_DMA_BUF_MLLI)) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; /* add the src data to the sg_data */ - ssi_buffer_mgr_add_scatterlist_entry(dev, &sg_data, - areq_ctx->in_nents, - src, - (update_data_len - *curr_buff_cnt), - 0, - true, - &areq_ctx->mlli_nents); - if (unlikely(ssi_buffer_mgr_generate_mlli(dev, &sg_data, - mlli_params) != 0)) { + cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, + (update_data_len - *curr_buff_cnt), 0, true, + &areq_ctx->mlli_nents); + if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params) != 0)) { goto fail_unmap_din; } } @@ -1695,8 +1641,8 @@ unmap_curr_buff: return -ENOMEM; } -void ssi_buffer_mgr_unmap_hash_request( - struct device *dev, void *ctx, struct scatterlist *src, bool do_revert) +void cc_unmap_hash_request(struct device *dev, void *ctx, + struct scatterlist *src, bool do_revert) { struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx; u32 *prev_len = areq_ctx->buff_index ? &areq_ctx->buff0_cnt : @@ -1736,7 +1682,7 @@ void ssi_buffer_mgr_unmap_hash_request( } } -int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata) +int cc_buffer_mgr_init(struct ssi_drvdata *drvdata) { struct buff_mgr_handle *buff_mgr_handle; struct device *dev = drvdata_to_dev(drvdata); @@ -1759,11 +1705,11 @@ int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata) return 0; error: - ssi_buffer_mgr_fini(drvdata); + cc_buffer_mgr_fini(drvdata); return -ENOMEM; } -int ssi_buffer_mgr_fini(struct ssi_drvdata *drvdata) +int cc_buffer_mgr_fini(struct ssi_drvdata *drvdata) { struct buff_mgr_handle *buff_mgr_handle = drvdata->buff_mgr_handle; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.h b/drivers/staging/ccree/ssi_buffer_mgr.h index 1032f25edcab..f6411de3f8de 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.h +++ b/drivers/staging/ccree/ssi_buffer_mgr.h @@ -50,42 +50,39 @@ struct mlli_params { u32 mlli_len; }; -int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata); +int cc_buffer_mgr_init(struct ssi_drvdata *drvdata); -int ssi_buffer_mgr_fini(struct ssi_drvdata *drvdata); +int cc_buffer_mgr_fini(struct ssi_drvdata *drvdata); -int ssi_buffer_mgr_map_blkcipher_request( - struct ssi_drvdata *drvdata, - void *ctx, - unsigned int ivsize, - unsigned int nbytes, - void *info, - struct scatterlist *src, - struct scatterlist *dst); +int cc_map_blkcipher_request(struct ssi_drvdata *drvdata, void *ctx, + unsigned int ivsize, unsigned int nbytes, + void *info, struct scatterlist *src, + struct scatterlist *dst); -void ssi_buffer_mgr_unmap_blkcipher_request( - struct device *dev, - void *ctx, - unsigned int ivsize, - struct scatterlist *src, - struct scatterlist *dst); +void cc_unmap_blkcipher_request(struct device *dev, void *ctx, + unsigned int ivsize, + struct scatterlist *src, + struct scatterlist *dst); -int ssi_buffer_mgr_map_aead_request(struct ssi_drvdata *drvdata, struct aead_request *req); +int cc_map_aead_request(struct ssi_drvdata *drvdata, struct aead_request *req); -void ssi_buffer_mgr_unmap_aead_request(struct device *dev, struct aead_request *req); +void cc_unmap_aead_request(struct device *dev, struct aead_request *req); -int ssi_buffer_mgr_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update); +int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + bool do_update); -int ssi_buffer_mgr_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, unsigned int block_size); +int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + unsigned int block_size); -void ssi_buffer_mgr_unmap_hash_request(struct device *dev, void *ctx, struct scatterlist *src, bool do_revert); +void cc_unmap_hash_request(struct device *dev, void *ctx, + struct scatterlist *src, bool do_revert); -void ssi_buffer_mgr_copy_scatterlist_portion(struct device *dev, u8 *dest, - struct scatterlist *sg, - u32 to_skip, u32 end, - enum ssi_sg_cpy_direct direct); +void cc_copy_sg_portion(struct device *dev, u8 *dest, struct scatterlist *sg, + u32 to_skip, u32 end, enum ssi_sg_cpy_direct direct); -void ssi_buffer_mgr_zero_sgl(struct scatterlist *sgl, u32 data_len); +void cc_zero_sgl(struct scatterlist *sgl, u32 data_len); #endif /*__BUFFER_MGR_H__*/ diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index ee85cbf7c9ae..721acf4fb5ef 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -694,7 +694,7 @@ static int ssi_blkcipher_complete(struct device *dev, int completion_error = 0; struct ablkcipher_request *req = (struct ablkcipher_request *)areq; - ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); + cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); kfree(req_ctx->iv); if (areq) { @@ -786,9 +786,8 @@ static int ssi_blkcipher_process( /* STAT_PHASE_1: Map buffers */ - rc = ssi_buffer_mgr_map_blkcipher_request(ctx_p->drvdata, req_ctx, - ivsize, nbytes, req_ctx->iv, - src, dst); + rc = cc_map_blkcipher_request(ctx_p->drvdata, req_ctx, ivsize, nbytes, + req_ctx->iv, src, dst); if (unlikely(rc != 0)) { dev_err(dev, "map_request() failed\n"); goto exit_process; @@ -823,12 +822,14 @@ static int ssi_blkcipher_process( if (areq) { if (unlikely(rc != -EINPROGRESS)) { /* Failed to send the request or request completed synchronously */ - ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); + cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, + dst); } } else { if (rc != 0) { - ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); + cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, + dst); } else { rc = ssi_blkcipher_complete(dev, ctx_p, req_ctx, dst, src, ivsize, NULL, diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index 1a3c481fa92a..b9d13520b4d4 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -317,7 +317,7 @@ static int init_cc_resources(struct platform_device *plat_dev) } new_drvdata->mlli_sram_addr = - ssi_sram_mgr_alloc(new_drvdata, MAX_MLLI_BUFF_SIZE); + cc_sram_alloc(new_drvdata, MAX_MLLI_BUFF_SIZE); if (unlikely(new_drvdata->mlli_sram_addr == NULL_SRAM_ADDR)) { dev_err(dev, "Failed to alloc MLLI Sram buffer\n"); rc = -ENOMEM; @@ -330,15 +330,15 @@ static int init_cc_resources(struct platform_device *plat_dev) goto post_sram_mgr_err; } - rc = ssi_buffer_mgr_init(new_drvdata); + rc = cc_buffer_mgr_init(new_drvdata); if (unlikely(rc != 0)) { dev_err(dev, "buffer_mgr_init failed\n"); goto post_req_mgr_err; } - rc = ssi_power_mgr_init(new_drvdata); + rc = cc_pm_init(new_drvdata); if (unlikely(rc != 0)) { - dev_err(dev, "ssi_power_mgr_init failed\n"); + dev_err(dev, "cc_pm_init failed\n"); goto post_buf_mgr_err; } @@ -383,9 +383,9 @@ post_cipher_err: post_ivgen_err: ssi_ivgen_fini(new_drvdata); post_power_mgr_err: - ssi_power_mgr_fini(new_drvdata); + cc_pm_fini(new_drvdata); post_buf_mgr_err: - ssi_buffer_mgr_fini(new_drvdata); + cc_buffer_mgr_fini(new_drvdata); post_req_mgr_err: request_mgr_fini(new_drvdata); post_sram_mgr_err: @@ -418,8 +418,8 @@ static void cleanup_cc_resources(struct platform_device *plat_dev) ssi_hash_free(drvdata); ssi_ablkcipher_free(drvdata); ssi_ivgen_fini(drvdata); - ssi_power_mgr_fini(drvdata); - ssi_buffer_mgr_fini(drvdata); + cc_pm_fini(drvdata); + cc_buffer_mgr_fini(drvdata); request_mgr_fini(drvdata); ssi_sram_mgr_fini(drvdata); ssi_fips_fini(drvdata); @@ -500,7 +500,7 @@ static int cc7x_remove(struct platform_device *plat_dev) #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) static const struct dev_pm_ops arm_cc7x_driver_pm = { - SET_RUNTIME_PM_OPS(ssi_power_mgr_runtime_suspend, ssi_power_mgr_runtime_resume, NULL) + SET_RUNTIME_PM_OPS(cc_pm_suspend, cc_pm_resume, NULL) }; #endif diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index d79090ed7f9c..d18d2d9c4cf4 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -364,7 +364,7 @@ static void ssi_hash_update_complete(struct device *dev, void *ssi_req, void __i dev_dbg(dev, "req=%pK\n", req); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false); + cc_unmap_hash_request(dev, state, req->src, false); req->base.complete(&req->base, 0); } @@ -378,7 +378,7 @@ static void ssi_hash_digest_complete(struct device *dev, void *ssi_req, void __i dev_dbg(dev, "req=%pK\n", req); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false); + cc_unmap_hash_request(dev, state, req->src, false); ssi_hash_unmap_result(dev, state, digestsize, req->result); ssi_hash_unmap_request(dev, state, ctx); req->base.complete(&req->base, 0); @@ -394,7 +394,7 @@ static void ssi_hash_complete(struct device *dev, void *ssi_req, void __iomem *c dev_dbg(dev, "req=%pK\n", req); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, false); + cc_unmap_hash_request(dev, state, req->src, false); ssi_hash_unmap_result(dev, state, digestsize, req->result); ssi_hash_unmap_request(dev, state, ctx); req->base.complete(&req->base, 0); @@ -429,7 +429,8 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, return -ENOMEM; } - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1) != 0)) { + if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, + src, nbytes, 1) != 0)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -548,7 +549,7 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); ssi_hash_unmap_request(dev, state, ctx); } @@ -556,9 +557,9 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); if (rc != 0) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); } else { - ssi_buffer_mgr_unmap_hash_request(dev, state, src, false); + cc_unmap_hash_request(dev, state, src, false); } ssi_hash_unmap_result(dev, state, digestsize, result); ssi_hash_unmap_request(dev, state, ctx); @@ -587,7 +588,8 @@ static int ssi_hash_update(struct ahash_req_ctx *state, return 0; } - rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, src, nbytes, block_size); + rc = cc_map_hash_request_update(ctx->drvdata, state, src, nbytes, + block_size); if (unlikely(rc)) { if (rc == 1) { dev_dbg(dev, " data size not require HW update %x\n", @@ -648,15 +650,15 @@ static int ssi_hash_update(struct ahash_req_ctx *state, rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); if (rc != 0) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); } else { - ssi_buffer_mgr_unmap_hash_request(dev, state, src, false); + cc_unmap_hash_request(dev, state, src, false); } } return rc; @@ -680,7 +682,8 @@ static int ssi_hash_finup(struct ahash_req_ctx *state, dev_dbg(dev, "===== %s-finup (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1) != 0)) { + if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, src, + nbytes, 1) != 0)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -779,17 +782,17 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); if (rc != 0) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); } else { - ssi_buffer_mgr_unmap_hash_request(dev, state, src, false); + cc_unmap_hash_request(dev, state, src, false); ssi_hash_unmap_result(dev, state, digestsize, result); ssi_hash_unmap_request(dev, state, ctx); } @@ -815,7 +818,8 @@ static int ssi_hash_final(struct ahash_req_ctx *state, dev_dbg(dev, "===== %s-final (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, src, nbytes, 0) != 0)) { + if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, src, + nbytes, 0) != 0)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -924,17 +928,17 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); if (rc != 0) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, src, true); + cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); } else { - ssi_buffer_mgr_unmap_hash_request(dev, state, src, false); + cc_unmap_hash_request(dev, state, src, false); ssi_hash_unmap_result(dev, state, digestsize, result); ssi_hash_unmap_request(dev, state, ctx); } @@ -1372,7 +1376,8 @@ static int ssi_mac_update(struct ahash_request *req) state->xcbc_count++; - rc = ssi_buffer_mgr_map_hash_request_update(ctx->drvdata, state, req->src, req->nbytes, block_size); + rc = cc_map_hash_request_update(ctx->drvdata, state, req->src, + req->nbytes, block_size); if (unlikely(rc)) { if (rc == 1) { dev_dbg(dev, " data size not require HW update %x\n", @@ -1408,7 +1413,7 @@ static int ssi_mac_update(struct ahash_request *req) rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true); + cc_unmap_hash_request(dev, state, req->src, true); } return rc; } @@ -1440,7 +1445,8 @@ static int ssi_mac_final(struct ahash_request *req) dev_dbg(dev, "===== final xcbc reminder (%d) ====\n", rem_cnt); - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 0) != 0)) { + if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, req->src, + req->nbytes, 0) != 0)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -1518,7 +1524,7 @@ static int ssi_mac_final(struct ahash_request *req) rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true); + cc_unmap_hash_request(dev, state, req->src, true); ssi_hash_unmap_result(dev, state, digestsize, req->result); } return rc; @@ -1543,7 +1549,8 @@ static int ssi_mac_finup(struct ahash_request *req) return ssi_mac_final(req); } - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 1) != 0)) { + if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, req->src, + req->nbytes, 1) != 0)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -1589,7 +1596,7 @@ static int ssi_mac_finup(struct ahash_request *req) rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true); + cc_unmap_hash_request(dev, state, req->src, true); ssi_hash_unmap_result(dev, state, digestsize, req->result); } return rc; @@ -1619,7 +1626,8 @@ static int ssi_mac_digest(struct ahash_request *req) return -ENOMEM; } - if (unlikely(ssi_buffer_mgr_map_hash_request_final(ctx->drvdata, state, req->src, req->nbytes, 1) != 0)) { + if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, req->src, + req->nbytes, 1) != 0)) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -1661,7 +1669,7 @@ static int ssi_mac_digest(struct ahash_request *req) rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 1); if (unlikely(rc != -EINPROGRESS)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); - ssi_buffer_mgr_unmap_hash_request(dev, state, req->src, true); + cc_unmap_hash_request(dev, state, req->src, true); ssi_hash_unmap_result(dev, state, digestsize, req->result); ssi_hash_unmap_request(dev, state, ctx); } @@ -2102,9 +2110,9 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) #endif /* Copy-to-sram digest-len */ - ssi_sram_mgr_const2sram_desc(digest_len_init, sram_buff_ofs, - ARRAY_SIZE(digest_len_init), - larval_seq, &larval_seq_len); + cc_set_sram_desc(digest_len_init, sram_buff_ofs, + ARRAY_SIZE(digest_len_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); if (unlikely(rc != 0)) goto init_digest_const_err; @@ -2114,9 +2122,9 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) #if (DX_DEV_SHA_MAX > 256) /* Copy-to-sram digest-len for sha384/512 */ - ssi_sram_mgr_const2sram_desc(digest_len_sha512_init, sram_buff_ofs, - ARRAY_SIZE(digest_len_sha512_init), - larval_seq, &larval_seq_len); + cc_set_sram_desc(digest_len_sha512_init, sram_buff_ofs, + ARRAY_SIZE(digest_len_sha512_init), + larval_seq, &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); if (unlikely(rc != 0)) goto init_digest_const_err; @@ -2129,36 +2137,36 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) hash_handle->larval_digest_sram_addr = sram_buff_ofs; /* Copy-to-sram initial SHA* digests */ - ssi_sram_mgr_const2sram_desc(md5_init, sram_buff_ofs, - ARRAY_SIZE(md5_init), larval_seq, - &larval_seq_len); + cc_set_sram_desc(md5_init, sram_buff_ofs, + ARRAY_SIZE(md5_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); if (unlikely(rc != 0)) goto init_digest_const_err; sram_buff_ofs += sizeof(md5_init); larval_seq_len = 0; - ssi_sram_mgr_const2sram_desc(sha1_init, sram_buff_ofs, - ARRAY_SIZE(sha1_init), larval_seq, - &larval_seq_len); + cc_set_sram_desc(sha1_init, sram_buff_ofs, + ARRAY_SIZE(sha1_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); if (unlikely(rc != 0)) goto init_digest_const_err; sram_buff_ofs += sizeof(sha1_init); larval_seq_len = 0; - ssi_sram_mgr_const2sram_desc(sha224_init, sram_buff_ofs, - ARRAY_SIZE(sha224_init), larval_seq, - &larval_seq_len); + cc_set_sram_desc(sha224_init, sram_buff_ofs, + ARRAY_SIZE(sha224_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); if (unlikely(rc != 0)) goto init_digest_const_err; sram_buff_ofs += sizeof(sha224_init); larval_seq_len = 0; - ssi_sram_mgr_const2sram_desc(sha256_init, sram_buff_ofs, - ARRAY_SIZE(sha256_init), larval_seq, - &larval_seq_len); + cc_set_sram_desc(sha256_init, sram_buff_ofs, + ARRAY_SIZE(sha256_init), larval_seq, + &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); if (unlikely(rc != 0)) goto init_digest_const_err; @@ -2171,11 +2179,11 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) const u32 const0 = ((u32 *)((u64 *)&sha384_init[i]))[1]; const u32 const1 = ((u32 *)((u64 *)&sha384_init[i]))[0]; - ssi_sram_mgr_const2sram_desc(&const0, sram_buff_ofs, 1, - larval_seq, &larval_seq_len); + cc_set_sram_desc(&const0, sram_buff_ofs, 1, larval_seq, + &larval_seq_len); sram_buff_ofs += sizeof(u32); - ssi_sram_mgr_const2sram_desc(&const1, sram_buff_ofs, 1, - larval_seq, &larval_seq_len); + cc_set_sram_desc(&const1, sram_buff_ofs, 1, larval_seq, + &larval_seq_len); sram_buff_ofs += sizeof(u32); } rc = send_request_init(drvdata, larval_seq, larval_seq_len); @@ -2189,11 +2197,11 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) const u32 const0 = ((u32 *)((u64 *)&sha512_init[i]))[1]; const u32 const1 = ((u32 *)((u64 *)&sha512_init[i]))[0]; - ssi_sram_mgr_const2sram_desc(&const0, sram_buff_ofs, 1, - larval_seq, &larval_seq_len); + cc_set_sram_desc(&const0, sram_buff_ofs, 1, larval_seq, + &larval_seq_len); sram_buff_ofs += sizeof(u32); - ssi_sram_mgr_const2sram_desc(&const1, sram_buff_ofs, 1, - larval_seq, &larval_seq_len); + cc_set_sram_desc(&const1, sram_buff_ofs, 1, larval_seq, + &larval_seq_len); sram_buff_ofs += sizeof(u32); } rc = send_request_init(drvdata, larval_seq, larval_seq_len); @@ -2234,7 +2242,7 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata) sizeof(sha224_init) + sizeof(sha256_init); - sram_buff = ssi_sram_mgr_alloc(drvdata, sram_size_to_alloc); + sram_buff = cc_sram_alloc(drvdata, sram_size_to_alloc); if (sram_buff == NULL_SRAM_ADDR) { dev_err(dev, "SRAM pool exhausted\n"); rc = -ENOMEM; diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c index 3f082f41ae8f..0d85bce36e3a 100644 --- a/drivers/staging/ccree/ssi_ivgen.c +++ b/drivers/staging/ccree/ssi_ivgen.c @@ -209,7 +209,7 @@ int ssi_ivgen_init(struct ssi_drvdata *drvdata) goto out; } /* Allocate IV pool in SRAM */ - ivgen_ctx->pool = ssi_sram_mgr_alloc(drvdata, SSI_IVPOOL_SIZE); + ivgen_ctx->pool = cc_sram_alloc(drvdata, SSI_IVPOOL_SIZE); if (ivgen_ctx->pool == NULL_SRAM_ADDR) { dev_err(device, "SRAM pool exhausted\n"); rc = -ENOMEM; diff --git a/drivers/staging/ccree/ssi_pm.c b/drivers/staging/ccree/ssi_pm.c index 36a498098a70..e1bc4c556248 100644 --- a/drivers/staging/ccree/ssi_pm.c +++ b/drivers/staging/ccree/ssi_pm.c @@ -34,7 +34,7 @@ #define POWER_DOWN_ENABLE 0x01 #define POWER_DOWN_DISABLE 0x00 -int ssi_power_mgr_runtime_suspend(struct device *dev) +int cc_pm_suspend(struct device *dev) { struct ssi_drvdata *drvdata = (struct ssi_drvdata *)dev_get_drvdata(dev); @@ -42,9 +42,9 @@ int ssi_power_mgr_runtime_suspend(struct device *dev) dev_dbg(dev, "set HOST_POWER_DOWN_EN\n"); cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE); - rc = ssi_request_mgr_runtime_suspend_queue(drvdata); + rc = cc_suspend_req_queue(drvdata); if (rc != 0) { - dev_err(dev, "ssi_request_mgr_runtime_suspend_queue (%x)\n", + dev_err(dev, "cc_suspend_req_queue (%x)\n", rc); return rc; } @@ -53,7 +53,7 @@ int ssi_power_mgr_runtime_suspend(struct device *dev) return 0; } -int ssi_power_mgr_runtime_resume(struct device *dev) +int cc_pm_resume(struct device *dev) { int rc; struct ssi_drvdata *drvdata = @@ -74,9 +74,9 @@ int ssi_power_mgr_runtime_resume(struct device *dev) return rc; } - rc = ssi_request_mgr_runtime_resume_queue(drvdata); + rc = cc_resume_req_queue(drvdata); if (rc != 0) { - dev_err(dev, "ssi_request_mgr_runtime_resume_queue (%x)\n", rc); + dev_err(dev, "cc_resume_req_queue (%x)\n", rc); return rc; } @@ -87,12 +87,11 @@ int ssi_power_mgr_runtime_resume(struct device *dev) return 0; } -int ssi_power_mgr_runtime_get(struct device *dev) +int cc_pm_get(struct device *dev) { int rc = 0; - if (ssi_request_mgr_is_queue_runtime_suspend( - (struct ssi_drvdata *)dev_get_drvdata(dev))) { + if (cc_req_queue_suspended((struct ssi_drvdata *)dev_get_drvdata(dev))) { rc = pm_runtime_get_sync(dev); } else { pm_runtime_get_noresume(dev); @@ -100,12 +99,11 @@ int ssi_power_mgr_runtime_get(struct device *dev) return rc; } -int ssi_power_mgr_runtime_put_suspend(struct device *dev) +int cc_pm_put_suspend(struct device *dev) { int rc = 0; - if (!ssi_request_mgr_is_queue_runtime_suspend( - (struct ssi_drvdata *)dev_get_drvdata(dev))) { + if (!cc_req_queue_suspended((struct ssi_drvdata *)dev_get_drvdata(dev))) { pm_runtime_mark_last_busy(dev); rc = pm_runtime_put_autosuspend(dev); } else { @@ -118,7 +116,7 @@ int ssi_power_mgr_runtime_put_suspend(struct device *dev) #endif -int ssi_power_mgr_init(struct ssi_drvdata *drvdata) +int cc_pm_init(struct ssi_drvdata *drvdata) { int rc = 0; #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) @@ -137,7 +135,7 @@ int ssi_power_mgr_init(struct ssi_drvdata *drvdata) return rc; } -void ssi_power_mgr_fini(struct ssi_drvdata *drvdata) +void cc_pm_fini(struct ssi_drvdata *drvdata) { #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) pm_runtime_disable(drvdata_to_dev(drvdata)); diff --git a/drivers/staging/ccree/ssi_pm.h b/drivers/staging/ccree/ssi_pm.h index 63673f60d2d8..557ec98b2d23 100644 --- a/drivers/staging/ccree/ssi_pm.h +++ b/drivers/staging/ccree/ssi_pm.h @@ -25,18 +25,18 @@ #define SSI_SUSPEND_TIMEOUT 3000 -int ssi_power_mgr_init(struct ssi_drvdata *drvdata); +int cc_pm_init(struct ssi_drvdata *drvdata); -void ssi_power_mgr_fini(struct ssi_drvdata *drvdata); +void cc_pm_fini(struct ssi_drvdata *drvdata); #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) -int ssi_power_mgr_runtime_suspend(struct device *dev); +int cc_pm_suspend(struct device *dev); -int ssi_power_mgr_runtime_resume(struct device *dev); +int cc_pm_resume(struct device *dev); -int ssi_power_mgr_runtime_get(struct device *dev); +int cc_pm_get(struct device *dev); -int ssi_power_mgr_runtime_put_suspend(struct device *dev); +int cc_pm_put_suspend(struct device *dev); #endif #endif /*__POWER_MGR_H__*/ diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index a8a7dc672d4c..f5d51c185cbd 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -274,9 +274,9 @@ int send_request( (!is_dout ? 1 : 0)); #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) - rc = ssi_power_mgr_runtime_get(dev); + rc = cc_pm_get(dev); if (rc != 0) { - dev_err(dev, "ssi_power_mgr_runtime_get returned %x\n", rc); + dev_err(dev, "cc_pm_get returned %x\n", rc); return rc; } #endif @@ -301,7 +301,7 @@ int send_request( * (SW queue is full) */ #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) - ssi_power_mgr_runtime_put_suspend(dev); + cc_pm_put_suspend(dev); #endif return rc; } @@ -337,7 +337,7 @@ int send_request( dev_err(dev, "Failed to generate IV (rc=%d)\n", rc); spin_unlock_bh(&req_mgr_h->hw_lock); #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) - ssi_power_mgr_runtime_put_suspend(dev); + cc_pm_put_suspend(dev); #endif return rc; } @@ -499,7 +499,7 @@ static void proc_completions(struct ssi_drvdata *drvdata) dev_dbg(dev, "Request completed. axi_completed=%d\n", request_mgr_handle->axi_completed); #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) - rc = ssi_power_mgr_runtime_put_suspend(dev); + rc = cc_pm_put_suspend(dev); if (rc != 0) dev_err(dev, "Failed to set runtime suspension %d\n", rc); @@ -565,7 +565,7 @@ static void comp_handler(unsigned long devarg) * the spin lock protection */ #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) -int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata) +int cc_resume_req_queue(struct ssi_drvdata *drvdata) { struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; @@ -580,7 +580,7 @@ int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata) * suspend the queue configuration. Since it is used for the runtime suspend * only verify that the queue can be suspended. */ -int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata) +int cc_suspend_req_queue(struct ssi_drvdata *drvdata) { struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; @@ -598,7 +598,7 @@ int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata) return 0; } -bool ssi_request_mgr_is_queue_runtime_suspend(struct ssi_drvdata *drvdata) +bool cc_req_queue_suspended(struct ssi_drvdata *drvdata) { struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; diff --git a/drivers/staging/ccree/ssi_request_mgr.h b/drivers/staging/ccree/ssi_request_mgr.h index bdbbf89e5367..ba44ab4ebe7b 100644 --- a/drivers/staging/ccree/ssi_request_mgr.h +++ b/drivers/staging/ccree/ssi_request_mgr.h @@ -50,11 +50,11 @@ void complete_request(struct ssi_drvdata *drvdata); void request_mgr_fini(struct ssi_drvdata *drvdata); #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) -int ssi_request_mgr_runtime_resume_queue(struct ssi_drvdata *drvdata); +int cc_resume_req_queue(struct ssi_drvdata *drvdata); -int ssi_request_mgr_runtime_suspend_queue(struct ssi_drvdata *drvdata); +int cc_suspend_req_queue(struct ssi_drvdata *drvdata); -bool ssi_request_mgr_is_queue_runtime_suspend(struct ssi_drvdata *drvdata); +bool cc_req_queue_suspended(struct ssi_drvdata *drvdata); #endif #endif /*__REQUEST_MGR_H__*/ diff --git a/drivers/staging/ccree/ssi_sram_mgr.c b/drivers/staging/ccree/ssi_sram_mgr.c index 07260d168c91..5151324823f7 100644 --- a/drivers/staging/ccree/ssi_sram_mgr.c +++ b/drivers/staging/ccree/ssi_sram_mgr.c @@ -69,7 +69,7 @@ int ssi_sram_mgr_init(struct ssi_drvdata *drvdata) * \param drvdata * \param size The requested bytes to allocate */ -ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size) +ssi_sram_addr_t cc_sram_alloc(struct ssi_drvdata *drvdata, u32 size) { struct ssi_sram_mgr_ctx *smgr_ctx = drvdata->sram_mgr_handle; struct device *dev = drvdata_to_dev(drvdata); @@ -93,7 +93,7 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size) } /** - * ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to + * cc_set_sram_desc() - Create const descriptors sequence to * set values in given array into SRAM. * Note: each const value can't exceed word size. * @@ -103,10 +103,9 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size) * @seq: A pointer to the given IN/OUT descriptor sequence * @seq_len: A pointer to the given IN/OUT sequence length */ -void ssi_sram_mgr_const2sram_desc( - const u32 *src, ssi_sram_addr_t dst, - unsigned int nelement, - struct cc_hw_desc *seq, unsigned int *seq_len) +void cc_set_sram_desc(const u32 *src, ssi_sram_addr_t dst, + unsigned int nelement, struct cc_hw_desc *seq, + unsigned int *seq_len) { u32 i; unsigned int idx = *seq_len; diff --git a/drivers/staging/ccree/ssi_sram_mgr.h b/drivers/staging/ccree/ssi_sram_mgr.h index 9ba1d59a0bae..9e392622962a 100644 --- a/drivers/staging/ccree/ssi_sram_mgr.h +++ b/drivers/staging/ccree/ssi_sram_mgr.h @@ -58,10 +58,10 @@ void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata); * \param drvdata * \param size The requested bytes to allocate */ -ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size); +ssi_sram_addr_t cc_sram_alloc(struct ssi_drvdata *drvdata, u32 size); /** - * ssi_sram_mgr_const2sram_desc() - Create const descriptors sequence to + * cc_set_sram_desc() - Create const descriptors sequence to * set values in given array into SRAM. * Note: each const value can't exceed word size. * @@ -71,7 +71,7 @@ ssi_sram_addr_t ssi_sram_mgr_alloc(struct ssi_drvdata *drvdata, u32 size); * @seq: A pointer to the given IN/OUT descriptor sequence * @seq_len: A pointer to the given IN/OUT sequence length */ -void ssi_sram_mgr_const2sram_desc( +void cc_set_sram_desc( const u32 *src, ssi_sram_addr_t dst, unsigned int nelement, struct cc_hw_desc *seq, unsigned int *seq_len); -- cgit v1.2.3 From d30a396964afdb7f236c476f966cfbd76880e513 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:11 +0000 Subject: staging: ccree: simplify AEAD using local var Make the code more readable by using a local variable for commonly use expression in the AEAD part of the driver. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 0b5b23036961..a8e1371772a3 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -251,13 +251,11 @@ static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *c } } else { /*ENCRYPT*/ if (unlikely(areq_ctx->is_icv_fragmented)) { + u32 skip = areq->cryptlen + areq_ctx->dst_offset; + cc_copy_sg_portion(dev, areq_ctx->mac_buf, - areq_ctx->dst_sgl, - (areq->cryptlen + - areq_ctx->dst_offset), - (areq->cryptlen + - areq_ctx->dst_offset + - ctx->authsize), + areq_ctx->dst_sgl, skip, + (skip + ctx->authsize), SSI_SG_FROM_BUF); } -- cgit v1.2.3 From 33bb30c3a9d6ee72e5fa4f514e316b6d807e40e1 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:12 +0000 Subject: staging: ccree: simplify buf mgr using local vars Make the code more readable by using a local variables for commonly use expressions in the buffer manager part of the driver. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 2d971f244bcb..b3ca249b941f 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -225,16 +225,18 @@ static int cc_generate_mlli( mlli_p = (u32 *)mlli_params->mlli_virt_addr; /* go over all SG's and link it to one MLLI table */ for (i = 0; i < sg_data->num_of_buffers; i++) { + union buffer_array_entry *entry = &sg_data->entry[i]; + u32 tot_len = sg_data->total_data_len[i]; + u32 offset = sg_data->offset[i]; + if (sg_data->type[i] == DMA_SGL_TYPE) - rc = cc_render_sg_to_mlli(dev, sg_data->entry[i].sgl, - sg_data->total_data_len[i], - sg_data->offset[i], - &total_nents, &mlli_p); + rc = cc_render_sg_to_mlli(dev, entry->sgl, tot_len, + offset, &total_nents, + &mlli_p); else /*DMA_BUFF_TYPE*/ - rc = cc_render_buff_to_mlli(dev, - sg_data->entry[i].buffer_dma, - sg_data->total_data_len[i], - &total_nents, &mlli_p); + rc = cc_render_buff_to_mlli(dev, entry->buffer_dma, + tot_len, &total_nents, + &mlli_p); if (rc != 0) return rc; -- cgit v1.2.3 From 02e6f40c34d6135827532e1425391a7461117b68 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:13 +0000 Subject: staging: ccree: fold common code into function Fold common code copying MAC to/from a temp. buffer into an inline function instead of keeping multiple open coded versions of same. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 89 ++++++++++++++-------------------- 1 file changed, 37 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index b3ca249b941f..48c0b02a7d52 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -64,6 +64,27 @@ struct buffer_array { u32 *mlli_nents[MAX_NUM_OF_BUFFERS_IN_MLLI]; }; +/** + * cc_copy_mac() - Copy MAC to temporary location + * + * @dev: device object + * @req: aead request object + * @dir: [IN] copy from/to sgl + */ +static inline void cc_copy_mac(struct device *dev, struct aead_request *req, + enum ssi_sg_cpy_direct dir) +{ + struct aead_req_ctx *areq_ctx = aead_request_ctx(req); + struct crypto_aead *tfm = crypto_aead_reqtfm(req); + u32 skip = req->assoclen + req->cryptlen; + + if (areq_ctx->is_gcm4543) + skip += crypto_aead_ivsize(tfm); + + cc_copy_sg_portion(dev, areq_ctx->backup_mac, req->src, + (skip - areq_ctx->req_authsize), skip, dir); +} + /** * cc_get_sgl_nents() - Get scatterlist number of entries. * @@ -670,19 +691,11 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req) if (drvdata->coherent && (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && likely(req->src == req->dst)) { - u32 size_to_skip = req->assoclen; - - if (areq_ctx->is_gcm4543) - size_to_skip += crypto_aead_ivsize(tfm); - /* copy mac to a temporary location to deal with possible + /* copy back mac from temporary location to deal with possible * data memory overriding that caused by cache coherence problem. */ - cc_copy_sg_portion(dev, areq_ctx->backup_mac, req->src, - (size_to_skip + req->cryptlen - - areq_ctx->req_authsize), - (size_to_skip + req->cryptlen), - SSI_SG_FROM_BUF); + cc_copy_mac(dev, req, SSI_SG_FROM_BUF); } } @@ -918,7 +931,6 @@ static inline int cc_prepare_aead_data_mlli( enum drv_crypto_direction direct = areq_ctx->gen_ctx.op_type; unsigned int authsize = areq_ctx->req_authsize; int rc = 0, icv_nents; - struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct device *dev = drvdata_to_dev(drvdata); if (likely(req->src == req->dst)) { @@ -943,24 +955,14 @@ static inline int cc_prepare_aead_data_mlli( * MAC verification upon request completion */ if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) { - if (!drvdata->coherent) { /* In coherent platforms (e.g. ACP) * already copying ICV for any * INPLACE-DECRYPT operation, hence * we must neglect this code. */ - u32 skip = req->assoclen; - - if (areq_ctx->is_gcm4543) - skip += crypto_aead_ivsize(tfm); - - cc_copy_sg_portion(dev, - areq_ctx->backup_mac, - req->src, - (skip + req->cryptlen - areq_ctx->req_authsize), - (skip + req->cryptlen), - SSI_SG_TO_BUF); - } + if (!drvdata->coherent) + cc_copy_mac(dev, req, SSI_SG_TO_BUF); + areq_ctx->icv_virt_addr = areq_ctx->backup_mac; } else { areq_ctx->icv_virt_addr = areq_ctx->mac_buf; @@ -996,22 +998,14 @@ static inline int cc_prepare_aead_data_mlli( goto prepare_data_mlli_exit; } + /* Backup happens only when ICV is fragmented, ICV + * verification is made by CPU compare in order to simplify + * MAC verification upon request completion + */ if (unlikely(areq_ctx->is_icv_fragmented)) { - /* Backup happens only when ICV is fragmented, ICV - * verification is made by CPU compare in order to simplify - * MAC verification upon request completion - */ - u32 size_to_skip = req->assoclen; - - if (areq_ctx->is_gcm4543) - size_to_skip += crypto_aead_ivsize(tfm); - - cc_copy_sg_portion(dev, areq_ctx->backup_mac, - req->src, - (size_to_skip + req->cryptlen - areq_ctx->req_authsize), - (size_to_skip + req->cryptlen), - SSI_SG_TO_BUF); + cc_copy_mac(dev, req, SSI_SG_TO_BUF); areq_ctx->icv_virt_addr = areq_ctx->backup_mac; + } else { /* Contig. ICV */ /*Should hanlde if the sg is not contig.*/ areq_ctx->icv_dma_addr = sg_dma_address( @@ -1249,22 +1243,13 @@ int cc_map_aead_request( mlli_params->curr_pool = NULL; sg_data.num_of_buffers = 0; + /* copy mac to a temporary location to deal with possible + * data memory overriding that caused by cache coherence problem. + */ if (drvdata->coherent && (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && - likely(req->src == req->dst)) { - u32 size_to_skip = req->assoclen; - - if (is_gcm4543) - size_to_skip += crypto_aead_ivsize(tfm); - - /* copy mac to a temporary location to deal with possible - * data memory overriding that caused by cache coherence problem. - */ - cc_copy_sg_portion(dev, areq_ctx->backup_mac, req->src, - (size_to_skip + req->cryptlen - areq_ctx->req_authsize), - (size_to_skip + req->cryptlen), - SSI_SG_TO_BUF); - } + likely(req->src == req->dst)) + cc_copy_mac(dev, req, SSI_SG_TO_BUF); /* cacluate the size for cipher remove ICV in decrypt*/ areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type == -- cgit v1.2.3 From da2e2d210c08ef81999ddd0ba8598bb79a0246da Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:14 +0000 Subject: staging: ccree: simplify pm manager using local var Make the code more readable by using a local variable. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_pm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_pm.c b/drivers/staging/ccree/ssi_pm.c index e1bc4c556248..d60143ca0509 100644 --- a/drivers/staging/ccree/ssi_pm.c +++ b/drivers/staging/ccree/ssi_pm.c @@ -90,20 +90,24 @@ int cc_pm_resume(struct device *dev) int cc_pm_get(struct device *dev) { int rc = 0; + struct ssi_drvdata *drvdata = + (struct ssi_drvdata *)dev_get_drvdata(dev); - if (cc_req_queue_suspended((struct ssi_drvdata *)dev_get_drvdata(dev))) { + if (cc_req_queue_suspended(drvdata)) rc = pm_runtime_get_sync(dev); - } else { + else pm_runtime_get_noresume(dev); - } + return rc; } int cc_pm_put_suspend(struct device *dev) { int rc = 0; + struct ssi_drvdata *drvdata = + (struct ssi_drvdata *)dev_get_drvdata(dev); - if (!cc_req_queue_suspended((struct ssi_drvdata *)dev_get_drvdata(dev))) { + if (!cc_req_queue_suspended(drvdata)) { pm_runtime_mark_last_busy(dev); rc = pm_runtime_put_autosuspend(dev); } else { -- cgit v1.2.3 From 6d7d9e787034a9dab21a27dc763aae2a84d90c75 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:15 +0000 Subject: staging: ccree: remove unneeded cast Remove unneeded cast of the return value of dev_get_drvdata() to struct ssi_drvdata * for better readability. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_pm.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_pm.c b/drivers/staging/ccree/ssi_pm.c index d60143ca0509..d3e938259f88 100644 --- a/drivers/staging/ccree/ssi_pm.c +++ b/drivers/staging/ccree/ssi_pm.c @@ -36,8 +36,7 @@ int cc_pm_suspend(struct device *dev) { - struct ssi_drvdata *drvdata = - (struct ssi_drvdata *)dev_get_drvdata(dev); + struct ssi_drvdata *drvdata = dev_get_drvdata(dev); int rc; dev_dbg(dev, "set HOST_POWER_DOWN_EN\n"); @@ -56,8 +55,7 @@ int cc_pm_suspend(struct device *dev) int cc_pm_resume(struct device *dev) { int rc; - struct ssi_drvdata *drvdata = - (struct ssi_drvdata *)dev_get_drvdata(dev); + struct ssi_drvdata *drvdata = dev_get_drvdata(dev); dev_dbg(dev, "unset HOST_POWER_DOWN_EN\n"); cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_DISABLE); @@ -90,8 +88,7 @@ int cc_pm_resume(struct device *dev) int cc_pm_get(struct device *dev) { int rc = 0; - struct ssi_drvdata *drvdata = - (struct ssi_drvdata *)dev_get_drvdata(dev); + struct ssi_drvdata *drvdata = dev_get_drvdata(dev); if (cc_req_queue_suspended(drvdata)) rc = pm_runtime_get_sync(dev); @@ -104,8 +101,7 @@ int cc_pm_get(struct device *dev) int cc_pm_put_suspend(struct device *dev) { int rc = 0; - struct ssi_drvdata *drvdata = - (struct ssi_drvdata *)dev_get_drvdata(dev); + struct ssi_drvdata *drvdata = dev_get_drvdata(dev); if (!cc_req_queue_suspended(drvdata)) { pm_runtime_mark_last_busy(dev); -- cgit v1.2.3 From 474f75a14c0d4b3782cc1640d6ab4e78501ad5f8 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:16 +0000 Subject: staging: ccree: remove compare to none zero The driver was full of code checking "if (x != 0)". Replace by "if (x)" for better readability. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 28 +++++------ drivers/staging/ccree/ssi_buffer_mgr.c | 74 ++++++++++++++--------------- drivers/staging/ccree/ssi_cipher.c | 14 +++--- drivers/staging/ccree/ssi_driver.c | 34 +++++++------- drivers/staging/ccree/ssi_hash.c | 82 ++++++++++++++++----------------- drivers/staging/ccree/ssi_ivgen.c | 2 +- drivers/staging/ccree/ssi_pm.c | 8 ++-- drivers/staging/ccree/ssi_request_mgr.c | 12 ++--- drivers/staging/ccree/ssi_sram_mgr.c | 2 +- 9 files changed, 128 insertions(+), 128 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index a8e1371772a3..e03616813e17 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -539,10 +539,10 @@ ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keyl } rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (unlikely(rc != 0)) + if (unlikely(rc)) dev_err(dev, "send_request() failed (rc=%d)\n", rc); - if (likely(key_dma_addr != 0)) + if (likely(key_dma_addr)) dma_unmap_single(dev, key_dma_addr, keylen, DMA_TO_DEVICE); return rc; @@ -598,7 +598,7 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) } rc = validate_keys_sizes(ctx); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto badkey; /* STAT_PHASE_1: Copy key to ctx */ @@ -611,7 +611,7 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen); } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */ rc = ssi_get_plain_hmac_key(tfm, key, ctx->auth_keylen); - if (rc != 0) + if (rc) goto badkey; } @@ -637,7 +637,7 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) if (seq_len > 0) { /* For CCM there is no sequence to setup the key */ rc = send_request(ctx->drvdata, &ssi_req, desc, seq_len, 0); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); goto setkey_error; } @@ -1520,7 +1520,7 @@ static inline int ssi_aead_ccm( } /* process the cipher */ - if (req_ctx->cryptlen != 0) + if (req_ctx->cryptlen) ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, &idx); /* Read temporal MAC */ @@ -1602,7 +1602,7 @@ static int config_ccm_adata(struct aead_request *req) *b0 |= 64; /* Enable bit 6 if Adata exists. */ rc = set_msg_len(b0 + 16 - l, cryptlen, l); /* Write L'. */ - if (rc != 0) { + if (rc) { dev_err(dev, "message len overflow detected"); return rc; } @@ -1739,7 +1739,7 @@ static inline void ssi_aead_gcm_setup_gctr_desc( set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; - if ((req_ctx->cryptlen != 0) && (!req_ctx->plaintext_authenticate_only)) { + if (req_ctx->cryptlen && !req_ctx->plaintext_authenticate_only) { /* load AES/CTR initial CTR value inc by 2*/ hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); @@ -1854,7 +1854,7 @@ static inline int ssi_aead_gcm( ssi_aead_create_assoc_desc(req, DIN_HASH, desc, seq_size); ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size); /* process(gctr+ghash) */ - if (req_ctx->cryptlen != 0) + if (req_ctx->cryptlen) ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size); ssi_aead_process_gcm_result_desc(req, desc, seq_size); @@ -1984,7 +1984,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction /* STAT_PHASE_0: Init and sanity checks */ /* Check data length according to mode */ - if (unlikely(validate_data_size(ctx, direct, req) != 0)) { + if (unlikely(validate_data_size(ctx, direct, req))) { dev_err(dev, "Unsupported crypt/assoc len %d/%d.\n", req->cryptlen, req->assoclen); crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_BLOCK_LEN); @@ -2031,7 +2031,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction #if SSI_CC_HAS_AES_CCM if (ctx->cipher_mode == DRV_CIPHER_CCM) { rc = config_ccm_adata(req); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_dbg(dev, "config_ccm_adata() returned with a failure %d!", rc); goto exit; @@ -2046,7 +2046,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction #if SSI_CC_HAS_AES_GCM if (ctx->cipher_mode == DRV_CIPHER_GCTR) { rc = config_gcm_context(req); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_dbg(dev, "config_gcm_context() returned with a failure %d!", rc); goto exit; @@ -2055,7 +2055,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction #endif /*SSI_CC_HAS_AES_GCM*/ rc = cc_map_aead_request(ctx->drvdata, req); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "map_request() failed\n"); goto exit; } @@ -2774,7 +2774,7 @@ int ssi_aead_alloc(struct ssi_drvdata *drvdata) } t_alg->drvdata = drvdata; rc = crypto_register_aead(&t_alg->aead_alg); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "%s alg registration failed\n", t_alg->aead_alg.base.cra_driver_name); goto fail2; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 48c0b02a7d52..29ef046b5dc6 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -98,8 +98,8 @@ static unsigned int cc_get_sgl_nents( { unsigned int nents = 0; - while (nbytes != 0) { - if (sg_list->length != 0) { + while (nbytes) { + if (sg_list->length) { nents++; /* get the number of bytes in the last entry */ *lbytes = nbytes; @@ -203,7 +203,7 @@ static inline int cc_render_sg_to_mlli( u32 *mlli_entry_p = *mlli_entry_pp; s32 rc = 0; - for ( ; (curr_sgl) && (sgl_data_len != 0); + for ( ; (curr_sgl && sgl_data_len); curr_sgl = sg_next(curr_sgl)) { u32 entry_data_len = (sgl_data_len > sg_dma_len(curr_sgl) - sgl_offset) ? @@ -213,7 +213,7 @@ static inline int cc_render_sg_to_mlli( rc = cc_render_buff_to_mlli(dev, sg_dma_address(curr_sgl) + sgl_offset, entry_data_len, curr_nents, &mlli_entry_p); - if (rc != 0) + if (rc) return rc; sgl_offset = 0; @@ -258,7 +258,7 @@ static int cc_generate_mlli( rc = cc_render_buff_to_mlli(dev, entry->buffer_dma, tot_len, &total_nents, &mlli_p); - if (rc != 0) + if (rc) return rc; /* set last bit in the current table */ @@ -480,7 +480,7 @@ void cc_unmap_blkcipher_request( { struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx; - if (likely(req_ctx->gen_ctx.iv_dma_addr != 0)) { + if (likely(req_ctx->gen_ctx.iv_dma_addr)) { dev_dbg(dev, "Unmapped iv: iv_dma_addr=%pad iv_size=%u\n", &req_ctx->gen_ctx.iv_dma_addr, ivsize); dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr, @@ -527,7 +527,7 @@ int cc_map_blkcipher_request( sg_data.num_of_buffers = 0; /* Map IV buffer */ - if (likely(ivsize != 0)) { + if (likely(ivsize)) { dump_byte_array("iv", (u8 *)info, ivsize); req_ctx->gen_ctx.iv_dma_addr = dma_map_single(dev, (void *)info, @@ -549,7 +549,7 @@ int cc_map_blkcipher_request( /* Map the src SGL */ rc = cc_map_sg(dev, src, nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents, LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { rc = -ENOMEM; goto ablkcipher_exit; } @@ -589,7 +589,7 @@ int cc_map_blkcipher_request( if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; rc = cc_generate_mlli(dev, &sg_data, mlli_params); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto ablkcipher_exit; } @@ -613,29 +613,29 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req) bool chained; u32 size_to_unmap = 0; - if (areq_ctx->mac_buf_dma_addr != 0) { + if (areq_ctx->mac_buf_dma_addr) { dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr, MAX_MAC_SIZE, DMA_BIDIRECTIONAL); } #if SSI_CC_HAS_AES_GCM if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) { - if (areq_ctx->hkey_dma_addr != 0) { + if (areq_ctx->hkey_dma_addr) { dma_unmap_single(dev, areq_ctx->hkey_dma_addr, AES_BLOCK_SIZE, DMA_BIDIRECTIONAL); } - if (areq_ctx->gcm_block_len_dma_addr != 0) { + if (areq_ctx->gcm_block_len_dma_addr) { dma_unmap_single(dev, areq_ctx->gcm_block_len_dma_addr, AES_BLOCK_SIZE, DMA_TO_DEVICE); } - if (areq_ctx->gcm_iv_inc1_dma_addr != 0) { + if (areq_ctx->gcm_iv_inc1_dma_addr) { dma_unmap_single(dev, areq_ctx->gcm_iv_inc1_dma_addr, AES_BLOCK_SIZE, DMA_TO_DEVICE); } - if (areq_ctx->gcm_iv_inc2_dma_addr != 0) { + if (areq_ctx->gcm_iv_inc2_dma_addr) { dma_unmap_single(dev, areq_ctx->gcm_iv_inc2_dma_addr, AES_BLOCK_SIZE, DMA_TO_DEVICE); } @@ -643,14 +643,14 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req) #endif if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { - if (areq_ctx->ccm_iv0_dma_addr != 0) { + if (areq_ctx->ccm_iv0_dma_addr) { dma_unmap_single(dev, areq_ctx->ccm_iv0_dma_addr, AES_BLOCK_SIZE, DMA_TO_DEVICE); } dma_unmap_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE); } - if (areq_ctx->gen_ctx.iv_dma_addr != 0) { + if (areq_ctx->gen_ctx.iv_dma_addr) { dma_unmap_single(dev, areq_ctx->gen_ctx.iv_dma_addr, hw_iv_size, DMA_BIDIRECTIONAL); } @@ -1125,7 +1125,7 @@ static inline int cc_aead_chain_data( &areq_ctx->dst.nents, LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes, &dst_mapped_nents); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { rc = -ENOMEM; goto chain_data_exit; } @@ -1284,7 +1284,7 @@ int cc_map_aead_request( } if (ssi_aead_handle_config_buf(dev, areq_ctx, areq_ctx->ccm_config, &sg_data, - req->assoclen) != 0) { + req->assoclen)) { rc = -ENOMEM; goto aead_map_failure; } @@ -1353,7 +1353,7 @@ int cc_map_aead_request( (LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + LLI_MAX_NUM_OF_DATA_ENTRIES), &dummy, &mapped_nents); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { rc = -ENOMEM; goto aead_map_failure; } @@ -1366,13 +1366,13 @@ int cc_map_aead_request( * Note: IV is contg. buffer (not an SGL) */ rc = cc_aead_chain_assoc(drvdata, req, &sg_data, true, false); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto aead_map_failure; rc = cc_aead_chain_iv(drvdata, req, &sg_data, true, false); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto aead_map_failure; rc = cc_aead_chain_data(drvdata, req, &sg_data, true, false); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto aead_map_failure; } else { /* DOUBLE-PASS flow */ /* @@ -1396,13 +1396,13 @@ int cc_map_aead_request( * (4) MLLI for dst */ rc = cc_aead_chain_assoc(drvdata, req, &sg_data, false, true); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto aead_map_failure; rc = cc_aead_chain_iv(drvdata, req, &sg_data, false, true); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto aead_map_failure; rc = cc_aead_chain_data(drvdata, req, &sg_data, true, true); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto aead_map_failure; } @@ -1412,7 +1412,7 @@ int cc_map_aead_request( (areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI))) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; rc = cc_generate_mlli(dev, &sg_data, mlli_params); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto aead_map_failure; cc_update_aead_mlli_nents(drvdata, req); @@ -1459,9 +1459,9 @@ int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, /*TODO: copy data in case that buffer is enough for operation */ /* map the previous buffer */ - if (*curr_buff_cnt != 0) { + if (*curr_buff_cnt) { if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff, - *curr_buff_cnt, &sg_data) != 0) { + *curr_buff_cnt, &sg_data)) { return -ENOMEM; } } @@ -1491,7 +1491,7 @@ int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, /* add the src data to the sg_data */ cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, nbytes, 0, true, &areq_ctx->mlli_nents); - if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params) != 0)) { + if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params))) { goto fail_unmap_din; } } @@ -1505,7 +1505,7 @@ fail_unmap_din: dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE); unmap_curr_buff: - if (*curr_buff_cnt != 0) + if (*curr_buff_cnt) dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE); return -ENOMEM; @@ -1563,7 +1563,7 @@ int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, *next_buff_cnt, update_data_len); /* Copy the new residue to next buffer */ - if (*next_buff_cnt != 0) { + if (*next_buff_cnt) { dev_dbg(dev, " handle residue: next buff %pK skip data %u residue %u\n", next_buff, (update_data_len - *curr_buff_cnt), *next_buff_cnt); @@ -1574,9 +1574,9 @@ int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, swap_index = 1; } - if (*curr_buff_cnt != 0) { + if (*curr_buff_cnt) { if (ssi_ahash_handle_curr_buf(dev, areq_ctx, curr_buff, - *curr_buff_cnt, &sg_data) != 0) { + *curr_buff_cnt, &sg_data)) { return -ENOMEM; } /* change the buffer index for next operation */ @@ -1610,7 +1610,7 @@ int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, (update_data_len - *curr_buff_cnt), 0, true, &areq_ctx->mlli_nents); - if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params) != 0)) { + if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params))) { goto fail_unmap_din; } } @@ -1622,7 +1622,7 @@ fail_unmap_din: dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE); unmap_curr_buff: - if (*curr_buff_cnt != 0) + if (*curr_buff_cnt) dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE); return -ENOMEM; @@ -1647,14 +1647,14 @@ void cc_unmap_hash_request(struct device *dev, void *ctx, areq_ctx->mlli_params.mlli_dma_addr); } - if ((src) && likely(areq_ctx->in_nents != 0)) { + if ((src) && likely(areq_ctx->in_nents)) { dev_dbg(dev, "Unmapped sg src: virt=%pK dma=%pad len=0x%X\n", sg_virt(src), &sg_dma_address(src), sg_dma_len(src)); dma_unmap_sg(dev, src, areq_ctx->in_nents, DMA_TO_DEVICE); } - if (*prev_len != 0) { + if (*prev_len) { dev_dbg(dev, "Unmapped buffer: areq_ctx->buff_sg=%pK dma=%pad len 0x%X\n", sg_virt(areq_ctx->buff_sg), &sg_dma_address(areq_ctx->buff_sg), diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index 721acf4fb5ef..4d05b4aba7c2 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -311,7 +311,7 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, keylen -= 1; #endif /*SSI_CC_HAS_MULTI2*/ - if (unlikely(validate_keys_sizes(ctx_p, keylen) != 0)) { + if (unlikely(validate_keys_sizes(ctx_p, keylen))) { dev_err(dev, "Unsupported key size %d.\n", keylen); crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; @@ -365,13 +365,13 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, } } if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) && - xts_check_key(tfm, key, keylen) != 0) { + xts_check_key(tfm, key, keylen)) { dev_dbg(dev, "weak XTS key"); return -EINVAL; } if ((ctx_p->flow_mode == S_DIN_to_DES) && (keylen == DES3_EDE_KEY_SIZE) && - ssi_verify_3des_keys(key, keylen) != 0) { + ssi_verify_3des_keys(key, keylen)) { dev_dbg(dev, "weak 3DES key"); return -EINVAL; } @@ -788,7 +788,7 @@ static int ssi_blkcipher_process( rc = cc_map_blkcipher_request(ctx_p->drvdata, req_ctx, ivsize, nbytes, req_ctx->iv, src, dst); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "map_request() failed\n"); goto exit_process; } @@ -827,7 +827,7 @@ static int ssi_blkcipher_process( } } else { - if (rc != 0) { + if (rc) { cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); } else { @@ -838,7 +838,7 @@ static int ssi_blkcipher_process( } exit_process: - if (cts_restore_flag != 0) + if (cts_restore_flag) ctx_p->cipher_mode = DRV_CIPHER_CBC_CTS; if (rc != -EINPROGRESS) { @@ -1338,7 +1338,7 @@ int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata) rc = crypto_register_alg(&t_alg->crypto_alg); dev_dbg(dev, "%s alg registration rc = %x\n", t_alg->crypto_alg.cra_driver_name, rc); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "%s alg registration failed\n", t_alg->crypto_alg.cra_driver_name); kfree(t_alg); diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index b9d13520b4d4..7b77f3f273d8 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -111,7 +111,7 @@ static irqreturn_t cc_isr(int irq, void *dev_id) drvdata->irq = irr; /* Completion interrupt - most probable */ - if (likely((irr & SSI_COMP_IRQ_MASK) != 0)) { + if (likely((irr & SSI_COMP_IRQ_MASK))) { /* Mask AXI completion interrupt - will be unmasked in Deferred service handler */ cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | SSI_COMP_IRQ_MASK); irr &= ~SSI_COMP_IRQ_MASK; @@ -119,7 +119,7 @@ static irqreturn_t cc_isr(int irq, void *dev_id) } #ifdef CC_SUPPORT_FIPS /* TEE FIPS interrupt */ - if (likely((irr & SSI_GPR0_IRQ_MASK) != 0)) { + if (likely((irr & SSI_GPR0_IRQ_MASK))) { /* Mask interrupt - will be unmasked in Deferred service handler */ cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | SSI_GPR0_IRQ_MASK); irr &= ~SSI_GPR0_IRQ_MASK; @@ -127,7 +127,7 @@ static irqreturn_t cc_isr(int irq, void *dev_id) } #endif /* AXI error interrupt */ - if (unlikely((irr & SSI_AXI_ERR_IRQ_MASK) != 0)) { + if (unlikely((irr & SSI_AXI_ERR_IRQ_MASK))) { u32 axi_err; /* Read the AXI error ID */ @@ -138,7 +138,7 @@ static irqreturn_t cc_isr(int irq, void *dev_id) irr &= ~SSI_AXI_ERR_IRQ_MASK; } - if (unlikely(irr != 0)) { + if (unlikely(irr)) { dev_dbg(dev, "IRR includes unknown cause bits (0x%08X)\n", irr); /* Just warning */ @@ -292,26 +292,26 @@ static int init_cc_resources(struct platform_device *plat_dev) DRV_MODULE_VERSION); rc = init_cc_regs(new_drvdata, true); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "init_cc_regs failed\n"); goto post_clk_err; } #ifdef ENABLE_CC_SYSFS rc = ssi_sysfs_init(&dev->kobj, new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "init_stat_db failed\n"); goto post_regs_err; } #endif rc = ssi_fips_init(new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "SSI_FIPS_INIT failed 0x%x\n", rc); goto post_sysfs_err; } rc = ssi_sram_mgr_init(new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "ssi_sram_mgr_init failed\n"); goto post_fips_init_err; } @@ -325,45 +325,45 @@ static int init_cc_resources(struct platform_device *plat_dev) } rc = request_mgr_init(new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "request_mgr_init failed\n"); goto post_sram_mgr_err; } rc = cc_buffer_mgr_init(new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "buffer_mgr_init failed\n"); goto post_req_mgr_err; } rc = cc_pm_init(new_drvdata); - if (unlikely(rc != 0)) { - dev_err(dev, "cc_pm_init failed\n"); + if (unlikely(rc)) { + dev_err(dev, "ssi_power_mgr_init failed\n"); goto post_buf_mgr_err; } rc = ssi_ivgen_init(new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "ssi_ivgen_init failed\n"); goto post_power_mgr_err; } /* Allocate crypto algs */ rc = ssi_ablkcipher_alloc(new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "ssi_ablkcipher_alloc failed\n"); goto post_ivgen_err; } /* hash must be allocated before aead since hash exports APIs */ rc = ssi_hash_alloc(new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "ssi_hash_alloc failed\n"); goto post_cipher_err; } rc = ssi_aead_alloc(new_drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "ssi_aead_alloc failed\n"); goto post_hash_err; } @@ -477,7 +477,7 @@ static int cc7x_probe(struct platform_device *plat_dev) /* Map registers space */ rc = init_cc_resources(plat_dev); - if (rc != 0) + if (rc) return rc; dev_info(dev, "ARM ccree device initialized\n"); diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index d18d2d9c4cf4..5b110b991375 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -234,7 +234,7 @@ static int ssi_hash_map_request(struct device *dev, set_flow_mode(&desc, BYPASS); rc = send_request(ctx->drvdata, &ssi_req, &desc, 1, 0); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); goto fail4; } @@ -276,12 +276,12 @@ static int ssi_hash_map_request(struct device *dev, return 0; fail5: - if (state->digest_bytes_len_dma_addr != 0) { + if (state->digest_bytes_len_dma_addr) { dma_unmap_single(dev, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, DMA_BIDIRECTIONAL); state->digest_bytes_len_dma_addr = 0; } fail4: - if (state->digest_buff_dma_addr != 0) { + if (state->digest_buff_dma_addr) { dma_unmap_single(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); state->digest_buff_dma_addr = 0; } @@ -308,21 +308,21 @@ static void ssi_hash_unmap_request(struct device *dev, struct ahash_req_ctx *state, struct ssi_hash_ctx *ctx) { - if (state->digest_buff_dma_addr != 0) { + if (state->digest_buff_dma_addr) { dma_unmap_single(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", &state->digest_buff_dma_addr); state->digest_buff_dma_addr = 0; } - if (state->digest_bytes_len_dma_addr != 0) { + if (state->digest_bytes_len_dma_addr) { dma_unmap_single(dev, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, DMA_BIDIRECTIONAL); dev_dbg(dev, "Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=%pad\n", &state->digest_bytes_len_dma_addr); state->digest_bytes_len_dma_addr = 0; } - if (state->opad_digest_dma_addr != 0) { + if (state->opad_digest_dma_addr) { dma_unmap_single(dev, state->opad_digest_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); dev_dbg(dev, "Unmapped opad-digest: opad_digest_dma_addr=%pad\n", @@ -342,7 +342,7 @@ static void ssi_hash_unmap_result(struct device *dev, struct ahash_req_ctx *state, unsigned int digestsize, u8 *result) { - if (state->digest_result_dma_addr != 0) { + if (state->digest_result_dma_addr) { dma_unmap_single(dev, state->digest_result_dma_addr, digestsize, @@ -419,18 +419,18 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, dev_dbg(dev, "===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash", nbytes); - if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) { + if (unlikely(ssi_hash_map_request(dev, state, ctx))) { dev_err(dev, "map_ahash_source() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (unlikely(ssi_hash_map_result(dev, state, digestsize))) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, - src, nbytes, 1) != 0)) { + src, nbytes, 1))) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -465,7 +465,7 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, NS_BIT); } else { set_din_const(&desc[idx], 0, HASH_LEN_SIZE); - if (likely(nbytes != 0)) + if (likely(nbytes)) set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); else set_cipher_do(&desc[idx], DO_PAD); @@ -555,7 +555,7 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); cc_unmap_hash_request(dev, state, src, true); } else { @@ -654,7 +654,7 @@ static int ssi_hash_update(struct ahash_req_ctx *state, } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); cc_unmap_hash_request(dev, state, src, true); } else { @@ -683,11 +683,11 @@ static int ssi_hash_finup(struct ahash_req_ctx *state, nbytes); if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, src, - nbytes, 1) != 0)) { + nbytes, 1))) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (unlikely(ssi_hash_map_result(dev, state, digestsize))) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } @@ -787,7 +787,7 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); @@ -819,12 +819,12 @@ static int ssi_hash_final(struct ahash_req_ctx *state, nbytes); if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, src, - nbytes, 0) != 0)) { + nbytes, 0))) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (unlikely(ssi_hash_map_result(dev, state, digestsize))) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } @@ -933,7 +933,7 @@ ctx->drvdata, ctx->hash_mode), HASH_LEN_SIZE); } } else { rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) { + if (rc) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); cc_unmap_hash_request(dev, state, src, true); ssi_hash_unmap_result(dev, state, digestsize, result); @@ -989,7 +989,7 @@ static int ssi_hash_setkey(void *hash, ctx->key_params.key_dma_addr = 0; ctx->is_hmac = true; - if (keylen != 0) { + if (keylen) { ctx->key_params.key_dma_addr = dma_map_single( dev, (void *)key, keylen, DMA_TO_DEVICE); @@ -1056,7 +1056,7 @@ static int ssi_hash_setkey(void *hash, keylen, NS_BIT, 0); idx++; - if ((blocksize - keylen) != 0) { + if ((blocksize - keylen)) { hw_desc_init(&desc[idx]); set_din_const(&desc[idx], 0, (blocksize - keylen)); @@ -1078,7 +1078,7 @@ static int ssi_hash_setkey(void *hash, } rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "send_request() failed (rc=%d)\n", rc); goto out; } @@ -1218,7 +1218,7 @@ static int ssi_xcbc_setkey(struct crypto_ahash *ahash, rc = send_request(ctx->drvdata, &ssi_req, desc, idx, 0); - if (rc != 0) + if (rc) crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); dma_unmap_single(dev, ctx->key_params.key_dma_addr, @@ -1273,14 +1273,14 @@ static void ssi_hash_free_ctx(struct ssi_hash_ctx *ctx) { struct device *dev = drvdata_to_dev(ctx->drvdata); - if (ctx->digest_buff_dma_addr != 0) { + if (ctx->digest_buff_dma_addr) { dma_unmap_single(dev, ctx->digest_buff_dma_addr, sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", &ctx->digest_buff_dma_addr); ctx->digest_buff_dma_addr = 0; } - if (ctx->opad_tmp_keys_dma_addr != 0) { + if (ctx->opad_tmp_keys_dma_addr) { dma_unmap_single(dev, ctx->opad_tmp_keys_dma_addr, sizeof(ctx->opad_tmp_keys_buff), DMA_BIDIRECTIONAL); @@ -1446,12 +1446,12 @@ static int ssi_mac_final(struct ahash_request *req) dev_dbg(dev, "===== final xcbc reminder (%d) ====\n", rem_cnt); if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, req->src, - req->nbytes, 0) != 0)) { + req->nbytes, 0))) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (unlikely(ssi_hash_map_result(dev, state, digestsize))) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } @@ -1550,11 +1550,11 @@ static int ssi_mac_finup(struct ahash_request *req) } if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, req->src, - req->nbytes, 1) != 0)) { + req->nbytes, 1))) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (unlikely(ssi_hash_map_result(dev, state, digestsize))) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } @@ -1617,17 +1617,17 @@ static int ssi_mac_digest(struct ahash_request *req) dev_dbg(dev, "===== -digest mac (%d) ====\n", req->nbytes); - if (unlikely(ssi_hash_map_request(dev, state, ctx) != 0)) { + if (unlikely(ssi_hash_map_request(dev, state, ctx))) { dev_err(dev, "map_ahash_source() failed\n"); return -ENOMEM; } - if (unlikely(ssi_hash_map_result(dev, state, digestsize) != 0)) { + if (unlikely(ssi_hash_map_result(dev, state, digestsize))) { dev_err(dev, "map_ahash_digest() failed\n"); return -ENOMEM; } if (unlikely(cc_map_hash_request_final(ctx->drvdata, state, req->src, - req->nbytes, 1) != 0)) { + req->nbytes, 1))) { dev_err(dev, "map_ahash_request_final() failed\n"); return -ENOMEM; } @@ -2114,7 +2114,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) ARRAY_SIZE(digest_len_init), larval_seq, &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto init_digest_const_err; sram_buff_ofs += sizeof(digest_len_init); @@ -2126,7 +2126,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) ARRAY_SIZE(digest_len_sha512_init), larval_seq, &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto init_digest_const_err; sram_buff_ofs += sizeof(digest_len_sha512_init); @@ -2141,7 +2141,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) ARRAY_SIZE(md5_init), larval_seq, &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto init_digest_const_err; sram_buff_ofs += sizeof(md5_init); larval_seq_len = 0; @@ -2150,7 +2150,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) ARRAY_SIZE(sha1_init), larval_seq, &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto init_digest_const_err; sram_buff_ofs += sizeof(sha1_init); larval_seq_len = 0; @@ -2159,7 +2159,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) ARRAY_SIZE(sha224_init), larval_seq, &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto init_digest_const_err; sram_buff_ofs += sizeof(sha224_init); larval_seq_len = 0; @@ -2168,7 +2168,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) ARRAY_SIZE(sha256_init), larval_seq, &larval_seq_len); rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) + if (unlikely(rc)) goto init_digest_const_err; sram_buff_ofs += sizeof(sha256_init); larval_seq_len = 0; @@ -2187,7 +2187,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) sram_buff_ofs += sizeof(u32); } rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "send_request() failed (rc = %d)\n", rc); goto init_digest_const_err; } @@ -2205,7 +2205,7 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) sram_buff_ofs += sizeof(u32); } rc = send_request_init(drvdata, larval_seq, larval_seq_len); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "send_request() failed (rc = %d)\n", rc); goto init_digest_const_err; } @@ -2254,7 +2254,7 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata) /*must be set before the alg registration as it is being used there*/ rc = ssi_hash_init_sram_digest_consts(drvdata); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "Init digest CONST failed (rc=%d)\n", rc); goto fail; } diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c index 0d85bce36e3a..a33fd7631ffe 100644 --- a/drivers/staging/ccree/ssi_ivgen.c +++ b/drivers/staging/ccree/ssi_ivgen.c @@ -143,7 +143,7 @@ int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata) /* Generate initial pool */ rc = ssi_ivgen_generate_pool(ivgen_ctx, iv_seq, &iv_seq_len); - if (unlikely(rc != 0)) + if (unlikely(rc)) return rc; /* Fire-and-forget */ diff --git a/drivers/staging/ccree/ssi_pm.c b/drivers/staging/ccree/ssi_pm.c index d3e938259f88..86d403d6a950 100644 --- a/drivers/staging/ccree/ssi_pm.c +++ b/drivers/staging/ccree/ssi_pm.c @@ -42,7 +42,7 @@ int cc_pm_suspend(struct device *dev) dev_dbg(dev, "set HOST_POWER_DOWN_EN\n"); cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE); rc = cc_suspend_req_queue(drvdata); - if (rc != 0) { + if (rc) { dev_err(dev, "cc_suspend_req_queue (%x)\n", rc); return rc; @@ -67,13 +67,13 @@ int cc_pm_resume(struct device *dev) } rc = init_cc_regs(drvdata, false); - if (rc != 0) { + if (rc) { dev_err(dev, "init_cc_regs (%x)\n", rc); return rc; } rc = cc_resume_req_queue(drvdata); - if (rc != 0) { + if (rc) { dev_err(dev, "cc_resume_req_queue (%x)\n", rc); return rc; } @@ -127,7 +127,7 @@ int cc_pm_init(struct ssi_drvdata *drvdata) pm_runtime_use_autosuspend(dev); /* activate the PM module */ rc = pm_runtime_set_active(dev); - if (rc != 0) + if (rc) return rc; /* enable the PM module*/ pm_runtime_enable(dev); diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index f5d51c185cbd..8fa3fc1aa1d5 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -73,7 +73,7 @@ void request_mgr_fini(struct ssi_drvdata *drvdata) if (!req_mgr_h) return; /* Not allocated */ - if (req_mgr_h->dummy_comp_buff_dma != 0) { + if (req_mgr_h->dummy_comp_buff_dma) { dma_free_coherent(dev, sizeof(u32), req_mgr_h->dummy_comp_buff, req_mgr_h->dummy_comp_buff_dma); } @@ -275,8 +275,8 @@ int send_request( #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) rc = cc_pm_get(dev); - if (rc != 0) { - dev_err(dev, "cc_pm_get returned %x\n", rc); + if (rc) { + dev_err(dev, "ssi_power_mgr_runtime_get returned %x\n", rc); return rc; } #endif @@ -333,7 +333,7 @@ int send_request( ssi_req->ivgen_dma_addr_len, ssi_req->ivgen_size, iv_seq, &iv_seq_len); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { dev_err(dev, "Failed to generate IV (rc=%d)\n", rc); spin_unlock_bh(&req_mgr_h->hw_lock); #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) @@ -412,7 +412,7 @@ int send_request_init( /* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT. */ rc = request_mgr_queues_status_check(drvdata, req_mgr_h, total_seq_len); - if (unlikely(rc != 0)) + if (unlikely(rc)) return rc; set_queue_last_ind(&desc[(len - 1)]); @@ -500,7 +500,7 @@ static void proc_completions(struct ssi_drvdata *drvdata) request_mgr_handle->axi_completed); #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) rc = cc_pm_put_suspend(dev); - if (rc != 0) + if (rc) dev_err(dev, "Failed to set runtime suspension %d\n", rc); #endif diff --git a/drivers/staging/ccree/ssi_sram_mgr.c b/drivers/staging/ccree/ssi_sram_mgr.c index 5151324823f7..2263433e0f2b 100644 --- a/drivers/staging/ccree/ssi_sram_mgr.c +++ b/drivers/staging/ccree/ssi_sram_mgr.c @@ -75,7 +75,7 @@ ssi_sram_addr_t cc_sram_alloc(struct ssi_drvdata *drvdata, u32 size) struct device *dev = drvdata_to_dev(drvdata); ssi_sram_addr_t p; - if (unlikely((size & 0x3) != 0)) { + if (unlikely((size & 0x3))) { dev_err(dev, "Requested buffer size (%u) is not multiple of 4", size); return NULL_SRAM_ADDR; -- cgit v1.2.3 From 155ff091da429df5bb636f093b6b55e307a42f08 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:17 +0000 Subject: staging: ccree: remove braces for single statement Remove necessary braces for single statement blocks to improve code readabilty. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 29ef046b5dc6..bfabb5b28064 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -1491,9 +1491,8 @@ int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, /* add the src data to the sg_data */ cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, nbytes, 0, true, &areq_ctx->mlli_nents); - if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params))) { + if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params))) goto fail_unmap_din; - } } /* change the buffer index for the unmap function */ areq_ctx->buff_index = (areq_ctx->buff_index ^ 1); @@ -1610,9 +1609,8 @@ int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, cc_add_sg_entry(dev, &sg_data, areq_ctx->in_nents, src, (update_data_len - *curr_buff_cnt), 0, true, &areq_ctx->mlli_nents); - if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params))) { + if (unlikely(cc_generate_mlli(dev, &sg_data, mlli_params))) goto fail_unmap_din; - } } areq_ctx->buff_index = (areq_ctx->buff_index ^ swap_index); -- cgit v1.2.3 From f9f284693a43e7f6e894440a513c2c971f5f3d48 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Thu, 9 Nov 2017 09:16:18 +0000 Subject: staging: ccree: remove unused cc_base parameter Remove a common parameter named cc_base with the pointer to the mapped command registers which was used by the old register access macros that are not longer in use. Signed-off-by: Gilad Ben-Yossef Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 2 +- drivers/staging/ccree/ssi_cipher.c | 12 +++++------- drivers/staging/ccree/ssi_driver.c | 3 --- drivers/staging/ccree/ssi_driver.h | 2 +- drivers/staging/ccree/ssi_hash.c | 6 +++--- drivers/staging/ccree/ssi_request_mgr.c | 5 ++--- 6 files changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index e03616813e17..9e2478341f97 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -225,7 +225,7 @@ init_failed: return -ENOMEM; } -static void ssi_aead_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_aead_complete(struct device *dev, void *ssi_req) { struct aead_request *areq = (struct aead_request *)ssi_req; struct aead_req_ctx *areq_ctx = aead_request_ctx(areq); diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index 4d05b4aba7c2..b5bb97c0c8cf 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -67,7 +67,7 @@ struct ssi_ablkcipher_ctx { struct crypto_shash *shash_tfm; }; -static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __iomem *cc_base); +static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req); static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) { @@ -688,8 +688,7 @@ static int ssi_blkcipher_complete(struct device *dev, struct scatterlist *dst, struct scatterlist *src, unsigned int ivsize, - void *areq, - void __iomem *cc_base) + void *areq) { int completion_error = 0; struct ablkcipher_request *req = (struct ablkcipher_request *)areq; @@ -832,8 +831,7 @@ static int ssi_blkcipher_process( dst); } else { rc = ssi_blkcipher_complete(dev, ctx_p, req_ctx, dst, - src, ivsize, NULL, - ctx_p->drvdata->cc_base); + src, ivsize, NULL); } } @@ -849,7 +847,7 @@ exit_process: return rc; } -static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req) { struct ablkcipher_request *areq = (struct ablkcipher_request *)ssi_req; struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(areq); @@ -858,7 +856,7 @@ static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __io unsigned int ivsize = crypto_ablkcipher_ivsize(tfm); ssi_blkcipher_complete(dev, ctx_p, req_ctx, areq->dst, areq->src, - ivsize, areq, cc_base); + ivsize, areq); } /* Async wrap functions */ diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index 7b77f3f273d8..0d5c1a9af9a5 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -199,7 +199,6 @@ int init_cc_regs(struct ssi_drvdata *drvdata, bool is_probe) static int init_cc_resources(struct platform_device *plat_dev) { struct resource *req_mem_cc_regs = NULL; - void __iomem *cc_base = NULL; struct ssi_drvdata *new_drvdata; struct device *dev = &plat_dev->dev; struct device_node *np = dev->of_node; @@ -232,8 +231,6 @@ static int init_cc_resources(struct platform_device *plat_dev) dev_dbg(dev, "CC registers mapped from %pa to 0x%p\n", &req_mem_cc_regs->start, new_drvdata->cc_base); - cc_base = new_drvdata->cc_base; - /* Then IRQ */ new_drvdata->irq = platform_get_irq(plat_dev, 0); if (new_drvdata->irq < 0) { diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h index 94c755cafb47..f4967caf070d 100644 --- a/drivers/staging/ccree/ssi_driver.h +++ b/drivers/staging/ccree/ssi_driver.h @@ -100,7 +100,7 @@ #define SSI_MAX_IVGEN_DMA_ADDRESSES 3 struct ssi_crypto_req { - void (*user_cb)(struct device *dev, void *req, void __iomem *cc_base); + void (*user_cb)(struct device *dev, void *req); void *user_arg; dma_addr_t ivgen_dma_addr[SSI_MAX_IVGEN_DMA_ADDRESSES]; /* For the first 'ivgen_dma_addr_len' addresses of this array, diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 5b110b991375..e9ed04c61b27 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -357,7 +357,7 @@ static void ssi_hash_unmap_result(struct device *dev, state->digest_result_dma_addr = 0; } -static void ssi_hash_update_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_hash_update_complete(struct device *dev, void *ssi_req) { struct ahash_request *req = (struct ahash_request *)ssi_req; struct ahash_req_ctx *state = ahash_request_ctx(req); @@ -368,7 +368,7 @@ static void ssi_hash_update_complete(struct device *dev, void *ssi_req, void __i req->base.complete(&req->base, 0); } -static void ssi_hash_digest_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_hash_digest_complete(struct device *dev, void *ssi_req) { struct ahash_request *req = (struct ahash_request *)ssi_req; struct ahash_req_ctx *state = ahash_request_ctx(req); @@ -384,7 +384,7 @@ static void ssi_hash_digest_complete(struct device *dev, void *ssi_req, void __i req->base.complete(&req->base, 0); } -static void ssi_hash_complete(struct device *dev, void *ssi_req, void __iomem *cc_base) +static void ssi_hash_complete(struct device *dev, void *ssi_req) { struct ahash_request *req = (struct ahash_request *)ssi_req; struct ahash_req_ctx *state = ahash_request_ctx(req); diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 8fa3fc1aa1d5..e9a09b39ac18 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -189,7 +189,7 @@ static inline void enqueue_seq( * \param dev * \param dx_compl_h The completion event to signal */ -static void request_mgr_complete(struct device *dev, void *dx_compl_h, void __iomem *cc_base) +static void request_mgr_complete(struct device *dev, void *dx_compl_h) { struct completion *this_compl = dx_compl_h; @@ -491,8 +491,7 @@ static void proc_completions(struct ssi_drvdata *drvdata) #endif /* COMPLETION_DELAY */ if (likely(ssi_req->user_cb)) - ssi_req->user_cb(dev, ssi_req->user_arg, - drvdata->cc_base); + ssi_req->user_cb(dev, ssi_req->user_arg); request_mgr_handle->req_queue_tail = (request_mgr_handle->req_queue_tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1); dev_dbg(dev, "Dequeue request tail=%u\n", request_mgr_handle->req_queue_tail); -- cgit v1.2.3 From ead5f963c05fef2d81485f5752760379d429dac4 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:29 +0000 Subject: staging: ccree: fix typos Fix a bunch of comment typos. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_hash.c | 2 +- drivers/staging/ccree/ssi_hash.h | 2 +- drivers/staging/ccree/ssi_ivgen.c | 2 +- drivers/staging/ccree/ssi_request_mgr.c | 2 +- drivers/staging/ccree/ssi_request_mgr.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index e9ed04c61b27..8dcc50fb8e2b 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -2481,7 +2481,7 @@ static void ssi_hash_create_data_desc(struct ahash_req_ctx *areq_ctx, * \param drvdata * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256 * - * \return u32 The address of the inital digest in SRAM + * \return u32 The address of the initial digest in SRAM */ ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode) { diff --git a/drivers/staging/ccree/ssi_hash.h b/drivers/staging/ccree/ssi_hash.h index 2400e389d65a..c884727aa906 100644 --- a/drivers/staging/ccree/ssi_hash.h +++ b/drivers/staging/ccree/ssi_hash.h @@ -95,7 +95,7 @@ ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, u32 mode); * \param drvdata * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512 * - * \return u32 The address of the inital digest in SRAM + * \return u32 The address of the initial digest in SRAM */ ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode); diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c index a33fd7631ffe..2f9201eec482 100644 --- a/drivers/staging/ccree/ssi_ivgen.c +++ b/drivers/staging/ccree/ssi_ivgen.c @@ -198,7 +198,7 @@ int ssi_ivgen_init(struct ssi_drvdata *drvdata) ivgen_ctx = drvdata->ivgen_handle; - /* Allocate pool's header for intial enc. key/IV */ + /* Allocate pool's header for initial enc. key/IV */ ivgen_ctx->pool_meta = dma_alloc_coherent(device, SSI_IVPOOL_META_SIZE, &ivgen_ctx->pool_meta_dma, GFP_KERNEL); diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index e9a09b39ac18..597a71f917c6 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -205,7 +205,7 @@ static inline int request_mgr_queues_status_check( struct device *dev = drvdata_to_dev(drvdata); /* SW queue is checked only once as it will not - * be chaned during the poll becasue the spinlock_bh + * be chaned during the poll because the spinlock_bh * is held by the thread */ if (unlikely(((req_mgr_h->req_queue_head + 1) & diff --git a/drivers/staging/ccree/ssi_request_mgr.h b/drivers/staging/ccree/ssi_request_mgr.h index ba44ab4ebe7b..23883e204f6e 100644 --- a/drivers/staging/ccree/ssi_request_mgr.h +++ b/drivers/staging/ccree/ssi_request_mgr.h @@ -36,7 +36,7 @@ int request_mgr_init(struct ssi_drvdata *drvdata); * If "false": this function adds a dummy descriptor completion * and waits upon completion signal. * - * \return int Returns -EINPROGRESS if "is_dout=ture"; "0" if "is_dout=false" + * \return int Returns -EINPROGRESS if "is_dout=true"; "0" if "is_dout=false" */ int send_request( struct ssi_drvdata *drvdata, struct ssi_crypto_req *ssi_req, -- cgit v1.2.3 From 309700da4838a40484ecd7ed1598332607f3a5cc Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:30 +0000 Subject: staging: ccree: alloc by instance not type Allocation by instance is preferred to allocation by type. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_sram_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_sram_mgr.c b/drivers/staging/ccree/ssi_sram_mgr.c index 2263433e0f2b..b71460c2200b 100644 --- a/drivers/staging/ccree/ssi_sram_mgr.c +++ b/drivers/staging/ccree/ssi_sram_mgr.c @@ -51,7 +51,7 @@ void ssi_sram_mgr_fini(struct ssi_drvdata *drvdata) int ssi_sram_mgr_init(struct ssi_drvdata *drvdata) { /* Allocate "this" context */ - drvdata->sram_mgr_handle = kzalloc(sizeof(struct ssi_sram_mgr_ctx), + drvdata->sram_mgr_handle = kzalloc(sizeof(*drvdata->sram_mgr_handle), GFP_KERNEL); if (!drvdata->sram_mgr_handle) -- cgit v1.2.3 From e4607e7b3b2b308fe56b96f1fee868b31a5c9789 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:31 +0000 Subject: staging: ccree: remove unnecessary parentheses Remove unnecessary parentheses in if statements across the driver. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 36 +++++++++++++++++----------------- drivers/staging/ccree/ssi_buffer_mgr.c | 28 +++++++++++++------------- drivers/staging/ccree/ssi_cipher.c | 34 ++++++++++++++++---------------- drivers/staging/ccree/ssi_hash.c | 16 +++++++-------- drivers/staging/ccree/ssi_ivgen.c | 4 ++-- 5 files changed, 59 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 9e2478341f97..7abc35241b63 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -391,9 +391,9 @@ static int validate_keys_sizes(struct ssi_aead_ctx *ctx) case DRV_HASH_SHA256: break; case DRV_HASH_XCBC_MAC: - if ((ctx->auth_keylen != AES_KEYSIZE_128) && - (ctx->auth_keylen != AES_KEYSIZE_192) && - (ctx->auth_keylen != AES_KEYSIZE_256)) + if (ctx->auth_keylen != AES_KEYSIZE_128 && + ctx->auth_keylen != AES_KEYSIZE_192 && + ctx->auth_keylen != AES_KEYSIZE_256) return -ENOTSUPP; break; case DRV_HASH_NULL: /* Not authenc (e.g., CCM) - no auth_key) */ @@ -412,9 +412,9 @@ static int validate_keys_sizes(struct ssi_aead_ctx *ctx) return -EINVAL; } } else { /* Default assumed to be AES ciphers */ - if ((ctx->enc_keylen != AES_KEYSIZE_128) && - (ctx->enc_keylen != AES_KEYSIZE_192) && - (ctx->enc_keylen != AES_KEYSIZE_256)) { + if (ctx->enc_keylen != AES_KEYSIZE_128 && + ctx->enc_keylen != AES_KEYSIZE_192 && + ctx->enc_keylen != AES_KEYSIZE_256) { dev_err(dev, "Invalid cipher(AES) key size: %u\n", ctx->enc_keylen); return -EINVAL; @@ -676,8 +676,8 @@ static int ssi_aead_setauthsize( struct device *dev = drvdata_to_dev(ctx->drvdata); /* Unsupported auth. sizes */ - if ((authsize == 0) || - (authsize > crypto_aead_maxauthsize(authenc))) { + if (authsize == 0 || + authsize > crypto_aead_maxauthsize(authenc)) { return -ENOTSUPP; } @@ -744,8 +744,8 @@ ssi_aead_create_assoc_desc( set_din_type(&desc[idx], DMA_DLLI, sg_dma_address(areq->src), areq->assoclen, NS_BIT); set_flow_mode(&desc[idx], flow_mode); - if ((ctx->auth_mode == DRV_HASH_XCBC_MAC) && - (areq_ctx->cryptlen > 0)) + if (ctx->auth_mode == DRV_HASH_XCBC_MAC && + areq_ctx->cryptlen > 0) set_din_not_last_indication(&desc[idx]); break; case SSI_DMA_BUF_MLLI: @@ -754,8 +754,8 @@ ssi_aead_create_assoc_desc( set_din_type(&desc[idx], DMA_MLLI, areq_ctx->assoc.sram_addr, areq_ctx->assoc.mlli_nents, NS_BIT); set_flow_mode(&desc[idx], flow_mode); - if ((ctx->auth_mode == DRV_HASH_XCBC_MAC) && - (areq_ctx->cryptlen > 0)) + if (ctx->auth_mode == DRV_HASH_XCBC_MAC && + areq_ctx->cryptlen > 0) set_din_not_last_indication(&desc[idx]); break; case SSI_DMA_BUF_NULL: @@ -1192,8 +1192,8 @@ static inline void ssi_aead_load_mlli_to_sram( struct device *dev = drvdata_to_dev(ctx->drvdata); if (unlikely( - (req_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) || - (req_ctx->data_buff_type == SSI_DMA_BUF_MLLI) || + req_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI || + req_ctx->data_buff_type == SSI_DMA_BUF_MLLI || !req_ctx->is_single_pass)) { dev_dbg(dev, "Copy-to-sram: mlli_dma=%08x, mlli_size=%u\n", (unsigned int)ctx->drvdata->mlli_sram_addr, @@ -1350,15 +1350,15 @@ static int validate_data_size(struct ssi_aead_ctx *ctx, unsigned int cipherlen = (direct == DRV_CRYPTO_DIRECTION_DECRYPT) ? (req->cryptlen - ctx->authsize) : req->cryptlen; - if (unlikely((direct == DRV_CRYPTO_DIRECTION_DECRYPT) && - (req->cryptlen < ctx->authsize))) + if (unlikely(direct == DRV_CRYPTO_DIRECTION_DECRYPT && + req->cryptlen < ctx->authsize)) goto data_size_err; areq_ctx->is_single_pass = true; /*defaulted to fast flow*/ switch (ctx->flow_mode) { case S_DIN_to_AES: - if (unlikely((ctx->cipher_mode == DRV_CIPHER_CBC) && + if (unlikely(ctx->cipher_mode == DRV_CIPHER_CBC && !IS_ALIGNED(cipherlen, AES_BLOCK_SIZE))) goto data_size_err; if (ctx->cipher_mode == DRV_CIPHER_CCM) @@ -1372,7 +1372,7 @@ static int validate_data_size(struct ssi_aead_ctx *ctx, if (!IS_ALIGNED(assoclen, sizeof(u32))) areq_ctx->is_single_pass = false; - if ((ctx->cipher_mode == DRV_CIPHER_CTR) && + if (ctx->cipher_mode == DRV_CIPHER_CTR && !IS_ALIGNED(cipherlen, sizeof(u32))) areq_ctx->is_single_pass = false; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index bfabb5b28064..923a0dfb1c69 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -576,7 +576,7 @@ int cc_map_blkcipher_request( if (mapped_nents > 1) req_ctx->dma_buf_type = SSI_DMA_BUF_MLLI; - if (unlikely((req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI))) { + if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) { cc_add_sg_entry(dev, &sg_data, req_ctx->in_nents, src, nbytes, 0, true, &req_ctx->in_mlli_nents); @@ -689,7 +689,7 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req) DMA_BIDIRECTIONAL); } if (drvdata->coherent && - (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && + areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT && likely(req->src == req->dst)) { /* copy back mac from temporary location to deal with possible @@ -864,13 +864,13 @@ static inline int cc_aead_chain_assoc( } if (likely(mapped_nents == 1) && - (areq_ctx->ccm_hdr_size == ccm_header_size_null)) + areq_ctx->ccm_hdr_size == ccm_header_size_null) areq_ctx->assoc_buff_type = SSI_DMA_BUF_DLLI; else areq_ctx->assoc_buff_type = SSI_DMA_BUF_MLLI; if (unlikely((do_chain) || - (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI))) { + areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI)) { dev_dbg(dev, "Chain assoc: buff_type=%s nents=%u\n", GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), areq_ctx->assoc.nents); @@ -1155,8 +1155,8 @@ static inline int cc_aead_chain_data( } areq_ctx->dst.nents = dst_mapped_nents; areq_ctx->dst_offset = offset; - if ((src_mapped_nents > 1) || - (dst_mapped_nents > 1) || + if (src_mapped_nents > 1 || + dst_mapped_nents > 1 || do_chain) { areq_ctx->data_buff_type = SSI_DMA_BUF_MLLI; rc = cc_prepare_aead_data_mlli(drvdata, req, sg_data, @@ -1247,7 +1247,7 @@ int cc_map_aead_request( * data memory overriding that caused by cache coherence problem. */ if (drvdata->coherent && - (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) && + areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT && likely(req->src == req->dst)) cc_copy_mac(dev, req, SSI_SG_TO_BUF); @@ -1408,8 +1408,8 @@ int cc_map_aead_request( /* Mlli support -start building the MLLI according to the above results */ if (unlikely( - (areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI) || - (areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI))) { + areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI || + areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI)) { mlli_params->curr_pool = buff_mgr->mlli_buffs_pool; rc = cc_generate_mlli(dev, &sg_data, mlli_params); if (unlikely(rc)) @@ -1466,15 +1466,15 @@ int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, } } - if (src && (nbytes > 0) && do_update) { + if (src && nbytes > 0 && do_update) { if (unlikely(cc_map_sg(dev, src, nbytes, DMA_TO_DEVICE, &areq_ctx->in_nents, LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents))) { goto unmap_curr_buff; } - if (src && (mapped_nents == 1) - && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL)) { + if (src && mapped_nents == 1 + && areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) { memcpy(areq_ctx->buff_sg, src, sizeof(struct scatterlist)); areq_ctx->buff_sg->length = nbytes; @@ -1590,8 +1590,8 @@ int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, &mapped_nents))) { goto unmap_curr_buff; } - if ((mapped_nents == 1) - && (areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL)) { + if (mapped_nents == 1 + && areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) { /* only one entry in the SG and no previous data */ memcpy(areq_ctx->buff_sg, src, sizeof(struct scatterlist)); diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index b5bb97c0c8cf..957138a51116 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -76,18 +76,18 @@ static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) switch (size) { case CC_AES_128_BIT_KEY_SIZE: case CC_AES_192_BIT_KEY_SIZE: - if (likely((ctx_p->cipher_mode != DRV_CIPHER_XTS) && - (ctx_p->cipher_mode != DRV_CIPHER_ESSIV) && - (ctx_p->cipher_mode != DRV_CIPHER_BITLOCKER))) + if (likely(ctx_p->cipher_mode != DRV_CIPHER_XTS && + ctx_p->cipher_mode != DRV_CIPHER_ESSIV && + ctx_p->cipher_mode != DRV_CIPHER_BITLOCKER)) return 0; break; case CC_AES_256_BIT_KEY_SIZE: return 0; case (CC_AES_192_BIT_KEY_SIZE * 2): case (CC_AES_256_BIT_KEY_SIZE * 2): - if (likely((ctx_p->cipher_mode == DRV_CIPHER_XTS) || - (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) || - (ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER))) + if (likely(ctx_p->cipher_mode == DRV_CIPHER_XTS || + ctx_p->cipher_mode == DRV_CIPHER_ESSIV || + ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER)) return 0; break; default: @@ -115,8 +115,8 @@ static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int siz case S_DIN_to_AES: switch (ctx_p->cipher_mode) { case DRV_CIPHER_XTS: - if ((size >= SSI_MIN_AES_XTS_SIZE) && - (size <= SSI_MAX_AES_XTS_SIZE) && + if (size >= SSI_MIN_AES_XTS_SIZE && + size <= SSI_MAX_AES_XTS_SIZE && IS_ALIGNED(size, AES_BLOCK_SIZE)) return 0; break; @@ -333,9 +333,9 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, return -EINVAL; } - if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) || - (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) || - (ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER)) { + if (ctx_p->cipher_mode == DRV_CIPHER_XTS || + ctx_p->cipher_mode == DRV_CIPHER_ESSIV || + ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER) { if (unlikely(hki->hw_key1 == hki->hw_key2)) { dev_err(dev, "Illegal hw key numbers (%d,%d)\n", hki->hw_key1, hki->hw_key2); @@ -364,13 +364,13 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, return -EINVAL; } } - if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) && + if (ctx_p->cipher_mode == DRV_CIPHER_XTS && xts_check_key(tfm, key, keylen)) { dev_dbg(dev, "weak XTS key"); return -EINVAL; } - if ((ctx_p->flow_mode == S_DIN_to_DES) && - (keylen == DES3_EDE_KEY_SIZE) && + if (ctx_p->flow_mode == S_DIN_to_DES && + keylen == DES3_EDE_KEY_SIZE && ssi_verify_3des_keys(key, keylen)) { dev_dbg(dev, "weak 3DES key"); return -EINVAL; @@ -456,8 +456,8 @@ ssi_blkcipher_create_setup_desc( set_cipher_config0(&desc[*seq_size], direction); set_flow_mode(&desc[*seq_size], flow_mode); set_cipher_mode(&desc[*seq_size], cipher_mode); - if ((cipher_mode == DRV_CIPHER_CTR) || - (cipher_mode == DRV_CIPHER_OFB)) { + if (cipher_mode == DRV_CIPHER_CTR || + cipher_mode == DRV_CIPHER_OFB) { set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1); } else { set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE0); @@ -765,7 +765,7 @@ static int ssi_blkcipher_process( memcpy(req_ctx->iv, info, ivsize); /*For CTS in case of data size aligned to 16 use CBC mode*/ - if (((nbytes % AES_BLOCK_SIZE) == 0) && (ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS)) { + if (((nbytes % AES_BLOCK_SIZE) == 0) && ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS) { ctx_p->cipher_mode = DRV_CIPHER_CBC; cts_restore_flag = 1; } diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 8dcc50fb8e2b..0e5f94da707b 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -116,9 +116,9 @@ static void ssi_hash_create_data_desc( static inline void ssi_set_hash_endianity(u32 mode, struct cc_hw_desc *desc) { - if (unlikely((mode == DRV_HASH_MD5) || - (mode == DRV_HASH_SHA384) || - (mode == DRV_HASH_SHA512))) { + if (unlikely(mode == DRV_HASH_MD5 || + mode == DRV_HASH_SHA384 || + mode == DRV_HASH_SHA512)) { set_bytes_swap(desc, 1); } else { set_cipher_config0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN); @@ -204,12 +204,12 @@ static int ssi_hash_map_request(struct device *dev, if (is_hmac) { dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); - if ((ctx->hw_mode == DRV_CIPHER_XCBC_MAC) || (ctx->hw_mode == DRV_CIPHER_CMAC)) { + if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC || ctx->hw_mode == DRV_CIPHER_CMAC) { memset(state->digest_buff, 0, ctx->inter_digestsize); } else { /*sha*/ memcpy(state->digest_buff, ctx->digest_buff, ctx->inter_digestsize); #if (DX_DEV_SHA_MAX > 256) - if (unlikely((ctx->hash_mode == DRV_HASH_SHA512) || (ctx->hash_mode == DRV_HASH_SHA384))) + if (unlikely(ctx->hash_mode == DRV_HASH_SHA512 || ctx->hash_mode == DRV_HASH_SHA384)) memcpy(state->digest_bytes_len, digest_len_sha512_init, HASH_LEN_SIZE); else memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE); @@ -1460,7 +1460,7 @@ static int ssi_mac_final(struct ahash_request *req) ssi_req.user_cb = (void *)ssi_hash_complete; ssi_req.user_arg = (void *)req; - if (state->xcbc_count && (rem_cnt == 0)) { + if (state->xcbc_count && rem_cnt == 0) { /* Load key for ECB decryption */ hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], DRV_CIPHER_ECB); @@ -2285,8 +2285,8 @@ int ssi_hash_alloc(struct ssi_drvdata *drvdata) &hash_handle->hash_list); } - if ((hw_mode == DRV_CIPHER_XCBC_MAC) || - (hw_mode == DRV_CIPHER_CMAC)) + if (hw_mode == DRV_CIPHER_XCBC_MAC || + hw_mode == DRV_CIPHER_CMAC) continue; /* register hash version */ diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c index 2f9201eec482..7171796888b4 100644 --- a/drivers/staging/ccree/ssi_ivgen.c +++ b/drivers/staging/ccree/ssi_ivgen.c @@ -248,8 +248,8 @@ int ssi_ivgen_getiv( struct device *dev = drvdata_to_dev(drvdata); unsigned int t; - if ((iv_out_size != CC_AES_IV_SIZE) && - (iv_out_size != CTR_RFC3686_IV_SIZE)) { + if (iv_out_size != CC_AES_IV_SIZE && + iv_out_size != CTR_RFC3686_IV_SIZE) { return -EINVAL; } if ((iv_out_dma_len + 1) > SSI_IVPOOL_SEQ_LEN) { -- cgit v1.2.3 From df33d7928c95c6ee990e8d5364048ad6fa5b0685 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:32 +0000 Subject: staging: ccree: remove MIN/MAX macros The driver was using open coded MIN/MAX macros to compute fixed defines. Remove them and use bigger value always instead. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.h | 2 +- drivers/staging/ccree/ssi_driver.h | 3 --- drivers/staging/ccree/ssi_hash.c | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.h b/drivers/staging/ccree/ssi_aead.h index e85bcd917e7b..580fdb8ab50d 100644 --- a/drivers/staging/ccree/ssi_aead.h +++ b/drivers/staging/ccree/ssi_aead.h @@ -28,7 +28,7 @@ /* mac_cmp - HW writes 8 B but all bytes hold the same value */ #define ICV_CMP_SIZE 8 #define CCM_CONFIG_BUF_SIZE (AES_BLOCK_SIZE * 3) -#define MAX_MAC_SIZE MAX(SHA256_DIGEST_SIZE, AES_BLOCK_SIZE) +#define MAX_MAC_SIZE SHA256_DIGEST_SIZE /* defines for AES GCM configuration buffer */ #define GCM_BLOCK_LEN_SIZE 8 diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h index f4967caf070d..758268e96dcc 100644 --- a/drivers/staging/ccree/ssi_driver.h +++ b/drivers/staging/ccree/ssi_driver.h @@ -95,9 +95,6 @@ * field in the HW descriptor. The DMA engine +8 that value. */ -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - #define SSI_MAX_IVGEN_DMA_ADDRESSES 3 struct ssi_crypto_req { void (*user_cb)(struct device *dev, void *req); diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 0e5f94da707b..f56c75d15118 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -32,7 +32,7 @@ #include "ssi_sram_mgr.h" #define SSI_MAX_AHASH_SEQ_LEN 12 -#define SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE MAX(SSI_MAX_HASH_BLCK_SIZE, 3 * AES_BLOCK_SIZE) +#define SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE SSI_MAX_HASH_BLCK_SIZE struct ssi_hash_handle { ssi_sram_addr_t digest_len_sram_addr; /* const value in SRAM*/ -- cgit v1.2.3 From b426144f4a467fdbf44dba1529c17047bc2371bf Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:33 +0000 Subject: staging: ccree: move logical cont. to 1st line Move logical continuations to first line for readability. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 923a0dfb1c69..cda5a30c423c 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -1473,8 +1473,8 @@ int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, &dummy, &mapped_nents))) { goto unmap_curr_buff; } - if (src && mapped_nents == 1 - && areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) { + if (src && mapped_nents == 1 && + areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) { memcpy(areq_ctx->buff_sg, src, sizeof(struct scatterlist)); areq_ctx->buff_sg->length = nbytes; @@ -1590,8 +1590,8 @@ int cc_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, &mapped_nents))) { goto unmap_curr_buff; } - if (mapped_nents == 1 - && areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) { + if (mapped_nents == 1 && + areq_ctx->data_dma_buf_type == SSI_DMA_BUF_NULL) { /* only one entry in the SG and no previous data */ memcpy(areq_ctx->buff_sg, src, sizeof(struct scatterlist)); -- cgit v1.2.3 From 9549afee3c6268c78692a237cd77e266d9d69370 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:34 +0000 Subject: staging: ccree: remove unneeded empty lines Remove uneeded empty lines that crept in to code. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 1 - drivers/staging/ccree/ssi_hash.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index cda5a30c423c..684c934d7a43 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -691,7 +691,6 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req) if (drvdata->coherent && areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT && likely(req->src == req->dst)) { - /* copy back mac from temporary location to deal with possible * data memory overriding that caused by cache coherence problem. */ diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index f56c75d15118..716bbbdeb8bd 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -2061,7 +2061,6 @@ ssi_hash_create_alg(struct ssi_hash_template *template, struct device *dev, if (!t_crypto_alg) return ERR_PTR(-ENOMEM); - t_crypto_alg->ahash_alg = template->template_ahash; halg = &t_crypto_alg->ahash_alg; alg = &halg->halg.base; -- cgit v1.2.3 From 04fad5d4d7256753369b54bd5ae2a5480dec7fc3 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:35 +0000 Subject: staging: ccree: remove unneeded cast Remove uneeded cast from writel_relaxed parameter. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_request_mgr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 597a71f917c6..e23c6561a6b1 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -167,13 +167,13 @@ static inline void enqueue_seq( int i; for (i = 0; i < seq_len; i++) { - writel_relaxed(seq[i].word[0], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[1], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[2], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[3], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[4], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); + writel_relaxed(seq[i].word[0], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); + writel_relaxed(seq[i].word[1], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); + writel_relaxed(seq[i].word[2], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); + writel_relaxed(seq[i].word[3], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); + writel_relaxed(seq[i].word[4], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); wmb(); - writel_relaxed(seq[i].word[5], (volatile void __iomem *)(cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); + writel_relaxed(seq[i].word[5], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); #ifdef DX_DUMP_DESCS dev_dbg(dev, "desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n", i, seq[i].word[0], seq[i].word[1], seq[i].word[2], -- cgit v1.2.3 From 2712dc7b01ec4f76a9aef60699bc4d896e75c427 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:36 +0000 Subject: staging: ccree: make mem barrier per request The driver was issuing a write memory barrier per each HW descriptor written but these descriptors are written in groups and we really only need one per group. White at it, document memory barrier reason. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_request_mgr.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index e23c6561a6b1..f5041f71af5a 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -172,7 +172,6 @@ static inline void enqueue_seq( writel_relaxed(seq[i].word[2], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); writel_relaxed(seq[i].word[3], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); writel_relaxed(seq[i].word[4], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - wmb(); writel_relaxed(seq[i].word[5], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); #ifdef DX_DUMP_DESCS dev_dbg(dev, "desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n", @@ -359,6 +358,12 @@ int send_request( #ifdef FLUSH_CACHE_ALL flush_cache_all(); #endif + /* + * We are about to push command to the HW via the command registers + * that may refernece hsot memory. We need to issue a memory barrier + * to make sure there are no outstnading memory writes + */ + wmb(); /* STAT_PHASE_4: Push sequence */ enqueue_seq(cc_base, iv_seq, iv_seq_len); @@ -417,6 +422,12 @@ int send_request_init( set_queue_last_ind(&desc[(len - 1)]); + /* + * We are about to push command to the HW via the command registers + * that may refernece hsot memory. We need to issue a memory barrier + * to make sure there are no outstnading memory writes + */ + wmb(); enqueue_seq(cc_base, desc, len); /* Update the free slots in HW queue */ -- cgit v1.2.3 From add496c0ba9c5b894f9a5e797a654488ba9822dd Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:37 +0000 Subject: staging: ccree: replace open coded loop with for Replace open coded register writing loop with a for. Further simplify code by using a local var to precompute the register address for readability. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_request_mgr.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index f5041f71af5a..65c4d9f3f262 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -164,15 +164,17 @@ static inline void enqueue_seq( void __iomem *cc_base, struct cc_hw_desc seq[], unsigned int seq_len) { - int i; + int i, w; + void * __iomem reg = cc_base + CC_REG(DSCRPTR_QUEUE_WORD0); + + /* + * We do indeed write all 6 command words to the same + * register. The HW supports this. + */ for (i = 0; i < seq_len; i++) { - writel_relaxed(seq[i].word[0], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[1], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[2], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[3], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[4], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); - writel_relaxed(seq[i].word[5], (cc_base + CC_REG(DSCRPTR_QUEUE_WORD0))); + for (w = 0; w <= 5; w++) + writel_relaxed(seq[i].word[w], reg); #ifdef DX_DUMP_DESCS dev_dbg(dev, "desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n", i, seq[i].word[0], seq[i].word[1], seq[i].word[2], -- cgit v1.2.3 From da4e52ac3e0af04ab75ed979f44db35557028f50 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:38 +0000 Subject: staging: ccree: document spinlock usage Document spinlock usage to protect against concurrent access to HW register which must occur a single request at a time. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_request_mgr.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 65c4d9f3f262..1d9c0381059b 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -43,6 +43,9 @@ struct ssi_request_mgr_handle { u32 req_queue_tail; u32 axi_completed; u32 q_free_slots; + /* This lock protects access to HW register + * that must be single request at a time + */ spinlock_t hw_lock; struct cc_hw_desc compl_desc; u8 *dummy_comp_buff; -- cgit v1.2.3 From 7d2e4fc239fd1f86b97fb7a1e4e8ac7cd29fc311 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:39 +0000 Subject: staging: ccree: constify help string Make help string static const Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index 5d39f15cdb59..8d503826e422 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -47,7 +47,7 @@ static ssize_t ssi_sys_regdump_show(struct kobject *kobj, static ssize_t ssi_sys_help_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - char *help_str[] = { + static const char * const help_str[] = { "cat reg_dump ", "Print several of CC register values", }; int i = 0, offset = 0; -- cgit v1.2.3 From 1eccfc44944b69366057730eeeaef7e3ae19d12a Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:40 +0000 Subject: staging: ccree: fix code indent Fix code ident not following the coding style. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_cipher.c | 2 +- drivers/staging/ccree/ssi_sysfs.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index 957138a51116..4c1080ae08c5 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -140,7 +140,7 @@ static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int siz break; case S_DIN_to_DES: if (likely(IS_ALIGNED(size, DES_BLOCK_SIZE))) - return 0; + return 0; break; #if SSI_CC_HAS_MULTI2 case S_DIN_to_MULTI2: diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index 8d503826e422..ed97decbe5e1 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -53,8 +53,10 @@ static ssize_t ssi_sys_help_show(struct kobject *kobj, int i = 0, offset = 0; offset += scnprintf(buf + offset, PAGE_SIZE - offset, "Usage:\n"); - for (i = 0; i < ARRAY_SIZE(help_str); i += 2) - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s\t\t%s\n", help_str[i], help_str[i + 1]); + for (i = 0; i < ARRAY_SIZE(help_str); i += 2) { + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s\t\t%s\n", help_str[i], help_str[i + 1]); + } return offset; } -- cgit v1.2.3 From f2f459ca644518e58d65f1749a5de85573d64719 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:41 +0000 Subject: staging: ccree: Replace CONFIG_PM_RUNTIME with CONFIG_PM After commit b2b49ccbdd54 ("PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is selected") PM_RUNTIME is always set if PM is set, so #ifdef blocks depending on CONFIG_PM_RUNTIME may now be changed to depend on CONFIG_PM. Replace CONFIG_PM_RUNTIME with CONFIG_PM. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_driver.c | 4 ++-- drivers/staging/ccree/ssi_pm.c | 6 +++--- drivers/staging/ccree/ssi_pm.h | 2 +- drivers/staging/ccree/ssi_request_mgr.c | 14 +++++++------- drivers/staging/ccree/ssi_request_mgr.h | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index 0d5c1a9af9a5..8d1682365fbc 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -495,13 +495,13 @@ static int cc7x_remove(struct platform_device *plat_dev) return 0; } -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) static const struct dev_pm_ops arm_cc7x_driver_pm = { SET_RUNTIME_PM_OPS(cc_pm_suspend, cc_pm_resume, NULL) }; #endif -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) #define DX_DRIVER_RUNTIME_PM (&arm_cc7x_driver_pm) #else #define DX_DRIVER_RUNTIME_PM NULL diff --git a/drivers/staging/ccree/ssi_pm.c b/drivers/staging/ccree/ssi_pm.c index 86d403d6a950..5e2ef5e1226c 100644 --- a/drivers/staging/ccree/ssi_pm.c +++ b/drivers/staging/ccree/ssi_pm.c @@ -29,7 +29,7 @@ #include "ssi_hash.h" #include "ssi_pm.h" -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) #define POWER_DOWN_ENABLE 0x01 #define POWER_DOWN_DISABLE 0x00 @@ -119,7 +119,7 @@ int cc_pm_put_suspend(struct device *dev) int cc_pm_init(struct ssi_drvdata *drvdata) { int rc = 0; -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) struct device *dev = drvdata_to_dev(drvdata); /* must be before the enabling to avoid resdundent suspending */ @@ -137,7 +137,7 @@ int cc_pm_init(struct ssi_drvdata *drvdata) void cc_pm_fini(struct ssi_drvdata *drvdata) { -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) pm_runtime_disable(drvdata_to_dev(drvdata)); #endif } diff --git a/drivers/staging/ccree/ssi_pm.h b/drivers/staging/ccree/ssi_pm.h index 557ec98b2d23..50bcf037dead 100644 --- a/drivers/staging/ccree/ssi_pm.h +++ b/drivers/staging/ccree/ssi_pm.h @@ -29,7 +29,7 @@ int cc_pm_init(struct ssi_drvdata *drvdata); void cc_pm_fini(struct ssi_drvdata *drvdata); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) int cc_pm_suspend(struct device *dev); int cc_pm_resume(struct device *dev); diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 1d9c0381059b..ab1885110559 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -58,7 +58,7 @@ struct ssi_request_mgr_handle { #else struct tasklet_struct comptask; #endif -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) bool is_runtime_suspended; #endif }; @@ -277,7 +277,7 @@ int send_request( SSI_IVPOOL_SEQ_LEN) + (!is_dout ? 1 : 0)); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) rc = cc_pm_get(dev); if (rc) { dev_err(dev, "ssi_power_mgr_runtime_get returned %x\n", rc); @@ -304,7 +304,7 @@ int send_request( /* Any error other than HW queue full * (SW queue is full) */ -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) cc_pm_put_suspend(dev); #endif return rc; @@ -340,7 +340,7 @@ int send_request( if (unlikely(rc)) { dev_err(dev, "Failed to generate IV (rc=%d)\n", rc); spin_unlock_bh(&req_mgr_h->hw_lock); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) cc_pm_put_suspend(dev); #endif return rc; @@ -469,7 +469,7 @@ static void proc_completions(struct ssi_drvdata *drvdata) struct device *dev = drvdata_to_dev(drvdata); struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) int rc = 0; #endif @@ -513,7 +513,7 @@ static void proc_completions(struct ssi_drvdata *drvdata) request_mgr_handle->req_queue_tail); dev_dbg(dev, "Request completed. axi_completed=%d\n", request_mgr_handle->axi_completed); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) rc = cc_pm_put_suspend(dev); if (rc) dev_err(dev, "Failed to set runtime suspension %d\n", @@ -579,7 +579,7 @@ static void comp_handler(unsigned long devarg) * resume the queue configuration - no need to take the lock as this happens inside * the spin lock protection */ -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) int cc_resume_req_queue(struct ssi_drvdata *drvdata) { struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; diff --git a/drivers/staging/ccree/ssi_request_mgr.h b/drivers/staging/ccree/ssi_request_mgr.h index 23883e204f6e..53eed5f10ae9 100644 --- a/drivers/staging/ccree/ssi_request_mgr.h +++ b/drivers/staging/ccree/ssi_request_mgr.h @@ -49,7 +49,7 @@ void complete_request(struct ssi_drvdata *drvdata); void request_mgr_fini(struct ssi_drvdata *drvdata); -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) +#if defined(CONFIG_PM) int cc_resume_req_queue(struct ssi_drvdata *drvdata); int cc_suspend_req_queue(struct ssi_drvdata *drvdata); -- cgit v1.2.3 From 07ece8b5b1da49bacca7d56e27509183f755aa68 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:42 +0000 Subject: staging: ccree: replace macro with inline func Replace GET_DMA_BUFFER_TYPE with an inline function variant with type checking. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 684c934d7a43..5e014772bd2f 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -33,11 +33,6 @@ #include "ssi_hash.h" #include "ssi_aead.h" -#define GET_DMA_BUFFER_TYPE(buff_type) ( \ - ((buff_type) == SSI_DMA_BUF_NULL) ? "BUF_NULL" : \ - ((buff_type) == SSI_DMA_BUF_DLLI) ? "BUF_DLLI" : \ - ((buff_type) == SSI_DMA_BUF_MLLI) ? "BUF_MLLI" : "BUF_INVALID") - enum dma_buffer_type { DMA_NULL_TYPE = -1, DMA_SGL_TYPE = 1, @@ -64,6 +59,20 @@ struct buffer_array { u32 *mlli_nents[MAX_NUM_OF_BUFFERS_IN_MLLI]; }; +static inline char *cc_dma_buf_type(enum ssi_req_dma_buf_type type) +{ + switch (type) { + case SSI_DMA_BUF_NULL: + return "BUF_NULL"; + case SSI_DMA_BUF_DLLI: + return "BUF_DLLI"; + case SSI_DMA_BUF_MLLI: + return "BUF_MLLI"; + default: + return "BUF_INVALID"; + } +} + /** * cc_copy_mac() - Copy MAC to temporary location * @@ -594,7 +603,7 @@ int cc_map_blkcipher_request( } dev_dbg(dev, "areq_ctx->dma_buf_type = %s\n", - GET_DMA_BUFFER_TYPE(req_ctx->dma_buf_type)); + cc_dma_buf_type(req_ctx->dma_buf_type)); return 0; @@ -819,7 +828,7 @@ static inline int cc_aead_chain_assoc( areq_ctx->assoc.nents = 0; areq_ctx->assoc.mlli_nents = 0; dev_dbg(dev, "Chain assoc of length 0: buff_type=%s nents=%u\n", - GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), + cc_dma_buf_type(areq_ctx->assoc_buff_type), areq_ctx->assoc.nents); goto chain_assoc_exit; } @@ -871,7 +880,7 @@ static inline int cc_aead_chain_assoc( if (unlikely((do_chain) || areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI)) { dev_dbg(dev, "Chain assoc: buff_type=%s nents=%u\n", - GET_DMA_BUFFER_TYPE(areq_ctx->assoc_buff_type), + cc_dma_buf_type(areq_ctx->assoc_buff_type), areq_ctx->assoc.nents); cc_add_sg_entry(dev, sg_data, areq_ctx->assoc.nents, req->src, req->assoclen, 0, is_last, @@ -1496,7 +1505,7 @@ int cc_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, /* change the buffer index for the unmap function */ areq_ctx->buff_index = (areq_ctx->buff_index ^ 1); dev_dbg(dev, "areq_ctx->data_dma_buf_type = %s\n", - GET_DMA_BUFFER_TYPE(areq_ctx->data_dma_buf_type)); + cc_dma_buf_type(areq_ctx->data_dma_buf_type)); return 0; fail_unmap_din: -- cgit v1.2.3 From a213e41c33f7763e4aadf8942d5885a29094bc64 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:43 +0000 Subject: staging: ccree: trim long lines for readability The ccree driver did not adhere to the kernel max 80 chars per line limit making the code hard to follow. Fix this by breaking long lines and in some cases, moving comments to a separate line from code. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 152 ++++++++++++++++++++++---------- drivers/staging/ccree/ssi_aead.h | 15 ++-- drivers/staging/ccree/ssi_buffer_mgr.c | 100 +++++++++++++-------- drivers/staging/ccree/ssi_cipher.c | 66 ++++++++++---- drivers/staging/ccree/ssi_cipher.h | 5 +- drivers/staging/ccree/ssi_config.h | 6 +- drivers/staging/ccree/ssi_driver.c | 8 +- drivers/staging/ccree/ssi_driver.h | 15 ++-- drivers/staging/ccree/ssi_fips.h | 3 +- drivers/staging/ccree/ssi_hash.c | 131 +++++++++++++++++++-------- drivers/staging/ccree/ssi_hash.h | 10 ++- drivers/staging/ccree/ssi_ivgen.c | 7 +- drivers/staging/ccree/ssi_ivgen.h | 3 +- drivers/staging/ccree/ssi_request_mgr.c | 45 ++++++---- drivers/staging/ccree/ssi_sysfs.c | 33 +++++-- 15 files changed, 406 insertions(+), 193 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index 7abc35241b63..e2cdf527c3af 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -100,7 +100,8 @@ static void ssi_aead_exit(struct crypto_aead *tfm) /* Unmap enckey buffer */ if (ctx->enckey) { - dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, ctx->enckey_dma_addr); + dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, + ctx->enckey_dma_addr); dev_dbg(dev, "Freed enckey DMA buffer enckey_dma_addr=%pad\n", &ctx->enckey_dma_addr); ctx->enckey_dma_addr = 0; @@ -259,12 +260,17 @@ static void ssi_aead_complete(struct device *dev, void *ssi_req) SSI_SG_FROM_BUF); } - /* If an IV was generated, copy it back to the user provided buffer. */ + /* If an IV was generated, copy it back to the user provided + * buffer. + */ if (areq_ctx->backup_giv) { if (ctx->cipher_mode == DRV_CIPHER_CTR) - memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_IV_SIZE); + memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + + CTR_RFC3686_NONCE_SIZE, + CTR_RFC3686_IV_SIZE); else if (ctx->cipher_mode == DRV_CIPHER_CCM) - memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, CCM_BLOCK_IV_SIZE); + memcpy(areq_ctx->backup_giv, areq_ctx->ctr_iv + + CCM_BLOCK_IV_OFFSET, CCM_BLOCK_IV_SIZE); } } @@ -275,8 +281,9 @@ static int xcbc_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) { /* Load the AES key */ hw_desc_init(&desc[0]); - /* We are using for the source/user key the same buffer as for the output keys, - * because after this key loading it is not needed anymore + /* We are using for the source/user key the same buffer + * as for the output keys, * because after this key loading it + * is not needed anymore */ set_din_type(&desc[0], DMA_DLLI, ctx->auth_state.xcbc.xcbc_keys_dma_addr, ctx->auth_keylen, @@ -428,7 +435,8 @@ static int validate_keys_sizes(struct ssi_aead_ctx *ctx) * (copy to intenral buffer or hash in case of key longer than block */ static int -ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) { dma_addr_t key_dma_addr = 0; struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); @@ -459,7 +467,8 @@ ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, unsigned int keyl } if (likely(keylen != 0)) { - key_dma_addr = dma_map_single(dev, (void *)key, keylen, DMA_TO_DEVICE); + key_dma_addr = dma_map_single(dev, (void *)key, keylen, + DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, key_dma_addr))) { dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", key, keylen); @@ -587,8 +596,9 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) /* Copy nonce from last 4 bytes in CTR key to * first 4 bytes in CTR IV */ - memcpy(ctx->ctr_nonce, key + ctx->auth_keylen + ctx->enc_keylen - - CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE); + memcpy(ctx->ctr_nonce, key + ctx->auth_keylen + + ctx->enc_keylen - CTR_RFC3686_NONCE_SIZE, + CTR_RFC3686_NONCE_SIZE); /* Set CTR key size */ ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE; } @@ -654,7 +664,8 @@ setkey_error: } #if SSI_CC_HAS_AES_CCM -static int ssi_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +static int ssi_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) { struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); @@ -856,7 +867,8 @@ ssi_aead_process_cipher_data_desc( hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, (sg_dma_address(areq_ctx->src_sgl) + - areq_ctx->src_offset), areq_ctx->cryptlen, NS_BIT); + areq_ctx->src_offset), areq_ctx->cryptlen, + NS_BIT); set_dout_dlli(&desc[idx], (sg_dma_address(areq_ctx->dst_sgl) + areq_ctx->dst_offset), @@ -1256,7 +1268,8 @@ static inline void ssi_aead_hmac_authenc( ssi_aead_hmac_setup_digest_desc(req, desc, seq_size); ssi_aead_setup_cipher_desc(req, desc, seq_size); ssi_aead_process_digest_header_desc(req, desc, seq_size); - ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, seq_size); + ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, + seq_size); ssi_aead_process_digest_scheme_desc(req, desc, seq_size); ssi_aead_process_digest_result_desc(req, desc, seq_size); return; @@ -1272,14 +1285,16 @@ static inline void ssi_aead_hmac_authenc( ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode); /* authenc after..*/ ssi_aead_hmac_setup_digest_desc(req, desc, seq_size); - ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct); + ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, + seq_size, direct); ssi_aead_process_digest_scheme_desc(req, desc, seq_size); ssi_aead_process_digest_result_desc(req, desc, seq_size); } else { /*DECRYPT*/ /* authenc first..*/ ssi_aead_hmac_setup_digest_desc(req, desc, seq_size); - ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct); + ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, + seq_size, direct); ssi_aead_process_digest_scheme_desc(req, desc, seq_size); /* decrypt after.. */ ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode); @@ -1310,7 +1325,8 @@ ssi_aead_xcbc_authenc( ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size); ssi_aead_setup_cipher_desc(req, desc, seq_size); ssi_aead_process_digest_header_desc(req, desc, seq_size); - ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, seq_size); + ssi_aead_process_cipher_data_desc(req, data_flow_mode, desc, + seq_size); ssi_aead_process_digest_result_desc(req, desc, seq_size); return; } @@ -1325,12 +1341,14 @@ ssi_aead_xcbc_authenc( ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode); /* authenc after.. */ ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size); - ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct); + ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, + seq_size, direct); ssi_aead_process_digest_result_desc(req, desc, seq_size); } else { /*DECRYPT*/ /* authenc first.. */ ssi_aead_xcbc_setup_digest_desc(req, desc, seq_size); - ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, seq_size, direct); + ssi_aead_process_authenc_data_desc(req, DIN_HASH, desc, + seq_size, direct); /* decrypt after..*/ ssi_aead_process_cipher(req, desc, seq_size, data_flow_mode); /* read the digest result with setting the completion bit @@ -1521,7 +1539,8 @@ static inline int ssi_aead_ccm( /* process the cipher */ if (req_ctx->cryptlen) - ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, &idx); + ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, + &idx); /* Read temporal MAC */ hw_desc_init(&desc[idx]); @@ -1571,7 +1590,9 @@ static int config_ccm_adata(struct aead_request *req) struct aead_req_ctx *req_ctx = aead_request_ctx(req); //unsigned int size_of_a = 0, rem_a_size = 0; unsigned int lp = req->iv[0]; - /* Note: The code assume that req->iv[0] already contains the value of L' of RFC3610 */ + /* Note: The code assume that req->iv[0] already contains the value + * of L' of RFC3610 + */ unsigned int l = lp + 1; /* This is L' of RFC 3610. */ unsigned int m = ctx->authsize; /* This is M' of RFC 3610. */ u8 *b0 = req_ctx->ccm_config + CCM_B0_OFFSET; @@ -1628,11 +1649,18 @@ static void ssi_rfc4309_ccm_process(struct aead_request *req) /* L' */ memset(areq_ctx->ctr_iv, 0, AES_BLOCK_SIZE); - areq_ctx->ctr_iv[0] = 3; /* For RFC 4309, always use 4 bytes for message length (at most 2^32-1 bytes). */ + /* For RFC 4309, always use 4 bytes for message length + * (at most 2^32-1 bytes). + */ + areq_ctx->ctr_iv[0] = 3; - /* In RFC 4309 there is an 11-bytes nonce+IV part, that we build here. */ - memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce, CCM_BLOCK_NONCE_SIZE); - memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, req->iv, CCM_BLOCK_IV_SIZE); + /* In RFC 4309 there is an 11-bytes nonce+IV part, + * that we build here. + */ + memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce, + CCM_BLOCK_NONCE_SIZE); + memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, req->iv, + CCM_BLOCK_IV_SIZE); req->iv = areq_ctx->ctr_iv; req->assoclen -= CCM_BLOCK_IV_SIZE; } @@ -1704,7 +1732,9 @@ static inline void ssi_aead_gcm_setup_ghash_desc( set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); idx++; - /* Load GHASH initial STATE (which is 0). (for any hash there is an initial state) */ + /* Load GHASH initial STATE (which is 0). (for any hash there is an + * initial state) + */ hw_desc_init(&desc[idx]); set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE); set_dout_no_dma(&desc[idx], 0, 0, 1); @@ -1855,7 +1885,8 @@ static inline int ssi_aead_gcm( ssi_aead_gcm_setup_gctr_desc(req, desc, seq_size); /* process(gctr+ghash) */ if (req_ctx->cryptlen) - ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, seq_size); + ssi_aead_process_cipher_data_desc(req, cipher_flow_mode, desc, + seq_size); ssi_aead_process_gcm_result_desc(req, desc, seq_size); return 0; @@ -1895,13 +1926,16 @@ static inline void ssi_aead_dump_gcm( dump_byte_array("mac_buf", req_ctx->mac_buf, AES_BLOCK_SIZE); - dump_byte_array("gcm_len_block", req_ctx->gcm_len_block.len_a, AES_BLOCK_SIZE); + dump_byte_array("gcm_len_block", req_ctx->gcm_len_block.len_a, + AES_BLOCK_SIZE); if (req->src && req->cryptlen) - dump_byte_array("req->src", sg_virt(req->src), req->cryptlen + req->assoclen); + dump_byte_array("req->src", sg_virt(req->src), + req->cryptlen + req->assoclen); if (req->dst) - dump_byte_array("req->dst", sg_virt(req->dst), req->cryptlen + ctx->authsize + req->assoclen); + dump_byte_array("req->dst", sg_virt(req->dst), + req->cryptlen + ctx->authsize + req->assoclen); } #endif @@ -1939,10 +1973,14 @@ static int config_gcm_context(struct aead_request *req) memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64)); temp64 = cpu_to_be64(cryptlen * 8); memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8); - } else { //rfc4543=> all data(AAD,IV,Plain) are considered additional data that is nothing is encrypted. + } else { + /* rfc4543=> all data(AAD,IV,Plain) are considered additional + * data that is nothing is encrypted. + */ __be64 temp64; - temp64 = cpu_to_be64((req->assoclen + GCM_BLOCK_RFC4_IV_SIZE + cryptlen) * 8); + temp64 = cpu_to_be64((req->assoclen + GCM_BLOCK_RFC4_IV_SIZE + + cryptlen) * 8); memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64)); temp64 = 0; memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8); @@ -1957,15 +1995,18 @@ static void ssi_rfc4_gcm_process(struct aead_request *req) struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); struct aead_req_ctx *areq_ctx = aead_request_ctx(req); - memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET, ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE); - memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET, req->iv, GCM_BLOCK_RFC4_IV_SIZE); + memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET, + ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE); + memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET, req->iv, + GCM_BLOCK_RFC4_IV_SIZE); req->iv = areq_ctx->ctr_iv; req->assoclen -= GCM_BLOCK_RFC4_IV_SIZE; } #endif /*SSI_CC_HAS_AES_GCM*/ -static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction direct) +static int ssi_aead_process(struct aead_request *req, + enum drv_crypto_direction direct) { int rc = 0; int seq_len = 0; @@ -2006,7 +2047,8 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction /* Build CTR IV - Copy nonce from last 4 bytes in * CTR key to first 4 bytes in CTR IV */ - memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce, CTR_RFC3686_NONCE_SIZE); + memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce, + CTR_RFC3686_NONCE_SIZE); if (!areq_ctx->backup_giv) /*User none-generated IV*/ memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, req->iv, CTR_RFC3686_IV_SIZE); @@ -2021,7 +2063,8 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction (ctx->cipher_mode == DRV_CIPHER_GCTR)) { areq_ctx->hw_iv_size = AES_BLOCK_SIZE; if (areq_ctx->ctr_iv != req->iv) { - memcpy(areq_ctx->ctr_iv, req->iv, crypto_aead_ivsize(tfm)); + memcpy(areq_ctx->ctr_iv, req->iv, + crypto_aead_ivsize(tfm)); req->iv = areq_ctx->ctr_iv; } } else { @@ -2064,20 +2107,29 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction if (areq_ctx->backup_giv) { /* set the DMA mapped IV address*/ if (ctx->cipher_mode == DRV_CIPHER_CTR) { - ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr + CTR_RFC3686_NONCE_SIZE; + ssi_req.ivgen_dma_addr[0] = + areq_ctx->gen_ctx.iv_dma_addr + + CTR_RFC3686_NONCE_SIZE; ssi_req.ivgen_dma_addr_len = 1; } else if (ctx->cipher_mode == DRV_CIPHER_CCM) { - /* In ccm, the IV needs to exist both inside B0 and inside the counter. - * It is also copied to iv_dma_addr for other reasons (like returning - * it to the user). + /* In ccm, the IV needs to exist both inside B0 and + * inside the counter.It is also copied to iv_dma_addr + * for other reasons (like returning it to the user). * So, using 3 (identical) IV outputs. */ - ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr + CCM_BLOCK_IV_OFFSET; - ssi_req.ivgen_dma_addr[1] = sg_dma_address(&areq_ctx->ccm_adata_sg) + CCM_B0_OFFSET + CCM_BLOCK_IV_OFFSET; - ssi_req.ivgen_dma_addr[2] = sg_dma_address(&areq_ctx->ccm_adata_sg) + CCM_CTR_COUNT_0_OFFSET + CCM_BLOCK_IV_OFFSET; + ssi_req.ivgen_dma_addr[0] = + areq_ctx->gen_ctx.iv_dma_addr + + CCM_BLOCK_IV_OFFSET; + ssi_req.ivgen_dma_addr[1] = + sg_dma_address(&areq_ctx->ccm_adata_sg) + + CCM_B0_OFFSET + CCM_BLOCK_IV_OFFSET; + ssi_req.ivgen_dma_addr[2] = + sg_dma_address(&areq_ctx->ccm_adata_sg) + + CCM_CTR_COUNT_0_OFFSET + CCM_BLOCK_IV_OFFSET; ssi_req.ivgen_dma_addr_len = 3; } else { - ssi_req.ivgen_dma_addr[0] = areq_ctx->gen_ctx.iv_dma_addr; + ssi_req.ivgen_dma_addr[0] = + areq_ctx->gen_ctx.iv_dma_addr; ssi_req.ivgen_dma_addr_len = 1; } @@ -2232,7 +2284,8 @@ out: #if SSI_CC_HAS_AES_GCM -static int ssi_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +static int ssi_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) { struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); @@ -2248,7 +2301,8 @@ static int ssi_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsign return ssi_aead_setkey(tfm, key, keylen); } -static int ssi_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) +static int ssi_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) { struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); @@ -2696,7 +2750,8 @@ static struct ssi_crypto_alg *ssi_aead_create_alg( alg = &template->template_aead; - snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", template->name); + snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", + template->name); snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", template->driver_name); alg->base.cra_module = THIS_MODULE; @@ -2725,7 +2780,8 @@ int ssi_aead_free(struct ssi_drvdata *drvdata) if (aead_handle) { /* Remove registered algs */ - list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list, entry) { + list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list, + entry) { crypto_unregister_aead(&t_alg->aead_alg); list_del(&t_alg->entry); kfree(t_alg); diff --git a/drivers/staging/ccree/ssi_aead.h b/drivers/staging/ccree/ssi_aead.h index 580fdb8ab50d..4e29063a3509 100644 --- a/drivers/staging/ccree/ssi_aead.h +++ b/drivers/staging/ccree/ssi_aead.h @@ -74,17 +74,22 @@ struct aead_req_ctx { } gcm_len_block; u8 ccm_config[CCM_CONFIG_BUF_SIZE] ____cacheline_aligned; - unsigned int hw_iv_size ____cacheline_aligned; /*HW actual size input*/ - u8 backup_mac[MAX_MAC_SIZE]; /*used to prevent cache coherence problem*/ + /* HW actual size input */ + unsigned int hw_iv_size ____cacheline_aligned; + /* used to prevent cache coherence problem */ + u8 backup_mac[MAX_MAC_SIZE]; u8 *backup_iv; /*store iv for generated IV flow*/ u8 *backup_giv; /*store iv for rfc3686(ctr) flow*/ dma_addr_t mac_buf_dma_addr; /* internal ICV DMA buffer */ - dma_addr_t ccm_iv0_dma_addr; /* buffer for internal ccm configurations */ + /* buffer for internal ccm configurations */ + dma_addr_t ccm_iv0_dma_addr; dma_addr_t icv_dma_addr; /* Phys. address of ICV */ //used in gcm - dma_addr_t gcm_iv_inc1_dma_addr; /* buffer for internal gcm configurations */ - dma_addr_t gcm_iv_inc2_dma_addr; /* buffer for internal gcm configurations */ + /* buffer for internal gcm configurations */ + dma_addr_t gcm_iv_inc1_dma_addr; + /* buffer for internal gcm configurations */ + dma_addr_t gcm_iv_inc2_dma_addr; dma_addr_t hkey_dma_addr; /* Phys. address of hkey */ dma_addr_t gcm_block_len_dma_addr; /* Phys. address of gcm block len */ bool is_gcm4543; diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 5e014772bd2f..966033d03b2f 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -112,7 +112,8 @@ static unsigned int cc_get_sgl_nents( nents++; /* get the number of bytes in the last entry */ *lbytes = nbytes; - nbytes -= (sg_list->length > nbytes) ? nbytes : sg_list->length; + nbytes -= (sg_list->length > nbytes) ? + nbytes : sg_list->length; sg_list = sg_next(sg_list); } else { sg_list = (struct scatterlist *)sg_page(sg_list); @@ -433,7 +434,8 @@ ssi_aead_handle_config_buf(struct device *dev, { dev_dbg(dev, " handle additional data config set to DLLI\n"); /* create sg for the current buffer */ - sg_init_one(&areq_ctx->ccm_adata_sg, config_data, AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size); + sg_init_one(&areq_ctx->ccm_adata_sg, config_data, + AES_BLOCK_SIZE + areq_ctx->ccm_hdr_size); if (unlikely(dma_map_sg(dev, &areq_ctx->ccm_adata_sg, 1, DMA_TO_DEVICE) != 1)) { dev_err(dev, "dma_map_sg() config buffer failed\n"); @@ -701,7 +703,8 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req) areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT && likely(req->src == req->dst)) { /* copy back mac from temporary location to deal with possible - * data memory overriding that caused by cache coherence problem. + * data memory overriding that caused by cache coherence + * problem. */ cc_copy_mac(dev, req, SSI_SG_FROM_BUF); } @@ -716,7 +719,9 @@ static inline int cc_get_aead_icv_nents( bool *is_icv_fragmented) { unsigned int icv_max_size = 0; - unsigned int icv_required_size = authsize > last_entry_data_size ? (authsize - last_entry_data_size) : authsize; + unsigned int icv_required_size = authsize > last_entry_data_size ? + (authsize - last_entry_data_size) : + authsize; unsigned int nents; unsigned int i; @@ -735,10 +740,12 @@ static inline int cc_get_aead_icv_nents( icv_max_size = sgl->length; if (last_entry_data_size > authsize) { - nents = 0; /* ICV attached to data in last entry (not fragmented!) */ + /* ICV attached to data in last entry (not fragmented!) */ + nents = 0; *is_icv_fragmented = false; } else if (last_entry_data_size == authsize) { - nents = 1; /* ICV placed in whole last entry (not fragmented!) */ + /* ICV placed in whole last entry (not fragmented!) */ + nents = 1; *is_icv_fragmented = false; } else if (icv_max_size > icv_required_size) { nents = 1; @@ -773,7 +780,8 @@ static inline int cc_aead_chain_iv( goto chain_iv_exit; } - areq_ctx->gen_ctx.iv_dma_addr = dma_map_single(dev, req->iv, hw_iv_size, + areq_ctx->gen_ctx.iv_dma_addr = dma_map_single(dev, req->iv, + hw_iv_size, DMA_BIDIRECTIONAL); if (unlikely(dma_mapping_error(dev, areq_ctx->gen_ctx.iv_dma_addr))) { dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n", @@ -784,7 +792,8 @@ static inline int cc_aead_chain_iv( dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n", hw_iv_size, req->iv, &areq_ctx->gen_ctx.iv_dma_addr); - if (do_chain && areq_ctx->plaintext_authenticate_only) { // TODO: what about CTR?? ask Ron + // TODO: what about CTR?? ask Ron + if (do_chain && areq_ctx->plaintext_authenticate_only) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); unsigned int iv_size_to_authenc = crypto_aead_ivsize(tfm); unsigned int iv_ofs = GCM_BLOCK_RFC4_IV_OFFSET; @@ -836,12 +845,15 @@ static inline int cc_aead_chain_assoc( //iterate over the sgl to see how many entries are for associated data //it is assumed that if we reach here , the sgl is already mapped sg_index = current_sg->length; - if (sg_index > size_of_assoc) { //the first entry in the scatter list contains all the associated data + //the first entry in the scatter list contains all the associated data + if (sg_index > size_of_assoc) { mapped_nents++; } else { while (sg_index <= size_of_assoc) { current_sg = sg_next(current_sg); - //if have reached the end of the sgl, then this is unexpected + /* if have reached the end of the sgl, then this is + * unexpected + */ if (!current_sg) { dev_err(dev, "reached end of sg list. unexpected\n"); return -EINVAL; @@ -959,8 +971,8 @@ static inline int cc_prepare_aead_data_mlli( if (unlikely(areq_ctx->is_icv_fragmented)) { /* Backup happens only when ICV is fragmented, ICV - * verification is made by CPU compare in order to simplify - * MAC verification upon request completion + * verification is made by CPU compare in order to + * simplify MAC verification upon request completion */ if (direct == DRV_CRYPTO_DIRECTION_DECRYPT) { /* In coherent platforms (e.g. ACP) @@ -974,7 +986,8 @@ static inline int cc_prepare_aead_data_mlli( areq_ctx->icv_virt_addr = areq_ctx->backup_mac; } else { areq_ctx->icv_virt_addr = areq_ctx->mac_buf; - areq_ctx->icv_dma_addr = areq_ctx->mac_buf_dma_addr; + areq_ctx->icv_dma_addr = + areq_ctx->mac_buf_dma_addr; } } else { /* Contig. ICV */ /*Should hanlde if the sg is not contig.*/ @@ -1076,7 +1089,8 @@ static inline int cc_aead_chain_data( int rc = 0; u32 src_mapped_nents = 0, dst_mapped_nents = 0; u32 offset = 0; - unsigned int size_for_map = req->assoclen + req->cryptlen; /*non-inplace mode*/ + /* non-inplace mode */ + unsigned int size_for_map = req->assoclen + req->cryptlen; struct crypto_aead *tfm = crypto_aead_reqtfm(req); u32 sg_index = 0; bool chained = false; @@ -1097,7 +1111,8 @@ static inline int cc_aead_chain_data( if (is_gcm4543) size_for_map += crypto_aead_ivsize(tfm); - size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0; + size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? + authsize : 0; src_mapped_nents = cc_get_sgl_nents(dev, req->src, size_for_map, &src_last_bytes, &chained); sg_index = areq_ctx->src_sgl->length; @@ -1125,7 +1140,8 @@ static inline int cc_aead_chain_data( if (req->src != req->dst) { size_for_map = req->assoclen + req->cryptlen; - size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? authsize : 0; + size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? + authsize : 0; if (is_gcm4543) size_for_map += crypto_aead_ivsize(tfm); @@ -1276,12 +1292,13 @@ int cc_map_aead_request( } if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { - areq_ctx->ccm_iv0_dma_addr = dma_map_single(dev, - (areq_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET), - AES_BLOCK_SIZE, - DMA_TO_DEVICE); + areq_ctx->ccm_iv0_dma_addr = + dma_map_single(dev, (areq_ctx->ccm_config + + CCM_CTR_COUNT_0_OFFSET), + AES_BLOCK_SIZE, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, areq_ctx->ccm_iv0_dma_addr))) { + if (unlikely(dma_mapping_error(dev, + areq_ctx->ccm_iv0_dma_addr))) { dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, (areq_ctx->ccm_config + @@ -1304,30 +1321,31 @@ int cc_map_aead_request( areq_ctx->hkey, AES_BLOCK_SIZE, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, areq_ctx->hkey_dma_addr))) { + if (unlikely(dma_mapping_error(dev, + areq_ctx->hkey_dma_addr))) { dev_err(dev, "Mapping hkey %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, areq_ctx->hkey); rc = -ENOMEM; goto aead_map_failure; } - areq_ctx->gcm_block_len_dma_addr = dma_map_single(dev, - &areq_ctx->gcm_len_block, - AES_BLOCK_SIZE, - DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_block_len_dma_addr))) { + areq_ctx->gcm_block_len_dma_addr = + dma_map_single(dev, &areq_ctx->gcm_len_block, + AES_BLOCK_SIZE, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev, + areq_ctx->gcm_block_len_dma_addr))) { dev_err(dev, "Mapping gcm_len_block %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, &areq_ctx->gcm_len_block); rc = -ENOMEM; goto aead_map_failure; } - areq_ctx->gcm_iv_inc1_dma_addr = dma_map_single(dev, - areq_ctx->gcm_iv_inc1, - AES_BLOCK_SIZE, - DMA_TO_DEVICE); + areq_ctx->gcm_iv_inc1_dma_addr = + dma_map_single(dev, areq_ctx->gcm_iv_inc1, + AES_BLOCK_SIZE, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_iv_inc1_dma_addr))) { + if (unlikely(dma_mapping_error(dev, + areq_ctx->gcm_iv_inc1_dma_addr))) { dev_err(dev, "Mapping gcm_iv_inc1 %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc1)); areq_ctx->gcm_iv_inc1_dma_addr = 0; @@ -1335,12 +1353,12 @@ int cc_map_aead_request( goto aead_map_failure; } - areq_ctx->gcm_iv_inc2_dma_addr = dma_map_single(dev, - areq_ctx->gcm_iv_inc2, - AES_BLOCK_SIZE, - DMA_TO_DEVICE); + areq_ctx->gcm_iv_inc2_dma_addr = + dma_map_single(dev, areq_ctx->gcm_iv_inc2, + AES_BLOCK_SIZE, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, areq_ctx->gcm_iv_inc2_dma_addr))) { + if (unlikely(dma_mapping_error(dev, + areq_ctx->gcm_iv_inc2_dma_addr))) { dev_err(dev, "Mapping gcm_iv_inc2 %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc2)); areq_ctx->gcm_iv_inc2_dma_addr = 0; @@ -1414,7 +1432,9 @@ int cc_map_aead_request( goto aead_map_failure; } - /* Mlli support -start building the MLLI according to the above results */ + /* Mlli support -start building the MLLI according to the above + * results + */ if (unlikely( areq_ctx->assoc_buff_type == SSI_DMA_BUF_MLLI || areq_ctx->data_buff_type == SSI_DMA_BUF_MLLI)) { @@ -1667,7 +1687,9 @@ void cc_unmap_hash_request(struct device *dev, void *ctx, sg_dma_len(areq_ctx->buff_sg)); dma_unmap_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE); if (!do_revert) { - /* clean the previous data length for update operation */ + /* clean the previous data length for update + * operation + */ *prev_len = 0; } else { areq_ctx->buff_index ^= 1; diff --git a/drivers/staging/ccree/ssi_cipher.c b/drivers/staging/ccree/ssi_cipher.c index 4c1080ae08c5..f6e680c67df5 100644 --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -109,7 +109,8 @@ static int validate_keys_sizes(struct ssi_ablkcipher_ctx *ctx_p, u32 size) return -EINVAL; } -static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int size) +static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, + unsigned int size) { switch (ctx_p->flow_mode) { case S_DIN_to_AES: @@ -164,12 +165,16 @@ static int validate_data_size(struct ssi_ablkcipher_ctx *ctx_p, unsigned int siz static unsigned int get_max_keysize(struct crypto_tfm *tfm) { - struct ssi_crypto_alg *ssi_alg = container_of(tfm->__crt_alg, struct ssi_crypto_alg, crypto_alg); + struct ssi_crypto_alg *ssi_alg = + container_of(tfm->__crt_alg, struct ssi_crypto_alg, + crypto_alg); - if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_ABLKCIPHER) + if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_ABLKCIPHER) return ssi_alg->crypto_alg.cra_ablkcipher.max_keysize; - if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER) + if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_BLKCIPHER) return ssi_alg->crypto_alg.cra_blkcipher.max_keysize; return 0; @@ -267,8 +272,10 @@ static int ssi_verify_3des_keys(const u8 *key, unsigned int keylen) struct tdes_keys *tdes_key = (struct tdes_keys *)key; /* verify key1 != key2 and key3 != key2*/ - if (unlikely((memcmp((u8 *)tdes_key->key1, (u8 *)tdes_key->key2, sizeof(tdes_key->key1)) == 0) || - (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, sizeof(tdes_key->key3)) == 0))) { + if (unlikely((memcmp((u8 *)tdes_key->key1, (u8 *)tdes_key->key2, + sizeof(tdes_key->key1)) == 0) || + (memcmp((u8 *)tdes_key->key3, (u8 *)tdes_key->key2, + sizeof(tdes_key->key3)) == 0))) { return -ENOEXEC; } @@ -306,7 +313,9 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, /* STAT_PHASE_0: Init and sanity checks */ #if SSI_CC_HAS_MULTI2 - /*last byte of key buffer is round number and should not be a part of key size*/ + /* last byte of key buffer is round number and should not be a part + * of key size + */ if (ctx_p->flow_mode == S_DIN_to_MULTI2) keylen -= 1; #endif /*SSI_CC_HAS_MULTI2*/ @@ -341,7 +350,8 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, hki->hw_key1, hki->hw_key2); return -EINVAL; } - ctx_p->hw.key2_slot = hw_key_to_cc_hw_key(hki->hw_key2); + ctx_p->hw.key2_slot = + hw_key_to_cc_hw_key(hki->hw_key2); if (unlikely(ctx_p->hw.key2_slot == END_OF_KEYS)) { dev_err(dev, "Unsupported hw key2 number (%d)\n", hki->hw_key2); @@ -383,7 +393,8 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, if (ctx_p->flow_mode == S_DIN_to_MULTI2) { #if SSI_CC_HAS_MULTI2 memcpy(ctx_p->user.key, key, CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE); - ctx_p->key_round_number = key[CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE]; + ctx_p->key_round_number = + key[CC_MULTI2_SYSTEM_N_DATA_KEY_SIZE]; if (ctx_p->key_round_number < CC_MULTI2_MIN_NUM_ROUNDS || ctx_p->key_round_number > CC_MULTI2_MAX_NUM_ROUNDS) { crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); @@ -393,7 +404,8 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, } else { memcpy(ctx_p->user.key, key, keylen); if (keylen == 24) - memset(ctx_p->user.key + 24, 0, CC_AES_KEY_SIZE_MAX - 24); + memset(ctx_p->user.key + 24, 0, + CC_AES_KEY_SIZE_MAX - 24); if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { /* sha256 for key2 - use sw implementation */ @@ -403,7 +415,9 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm, desc->tfm = ctx_p->shash_tfm; - err = crypto_shash_digest(desc, ctx_p->user.key, key_len, ctx_p->user.key + key_len); + err = crypto_shash_digest(desc, ctx_p->user.key, + key_len, + ctx_p->user.key + key_len); if (err) { dev_err(dev, "Failed to hash ESSIV key.\n"); return err; @@ -437,11 +451,15 @@ ssi_blkcipher_create_setup_desc( dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr; unsigned int du_size = nbytes; - struct ssi_crypto_alg *ssi_alg = container_of(tfm->__crt_alg, struct ssi_crypto_alg, crypto_alg); + struct ssi_crypto_alg *ssi_alg = + container_of(tfm->__crt_alg, struct ssi_crypto_alg, + crypto_alg); - if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == CRYPTO_ALG_BULK_DU_512) + if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == + CRYPTO_ALG_BULK_DU_512) du_size = 512; - if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == CRYPTO_ALG_BULK_DU_4096) + if ((ssi_alg->crypto_alg.cra_flags & CRYPTO_ALG_BULK_MASK) == + CRYPTO_ALG_BULK_DU_4096) du_size = 4096; switch (cipher_mode) { @@ -765,7 +783,8 @@ static int ssi_blkcipher_process( memcpy(req_ctx->iv, info, ivsize); /*For CTS in case of data size aligned to 16 use CBC mode*/ - if (((nbytes % AES_BLOCK_SIZE) == 0) && ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS) { + if (((nbytes % AES_BLOCK_SIZE) == 0) && + ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS) { ctx_p->cipher_mode = DRV_CIPHER_CBC; cts_restore_flag = 1; } @@ -817,10 +836,13 @@ static int ssi_blkcipher_process( /* STAT_PHASE_3: Lock HW and push sequence */ - rc = send_request(ctx_p->drvdata, &ssi_req, desc, seq_len, (!areq) ? 0 : 1); + rc = send_request(ctx_p->drvdata, &ssi_req, desc, seq_len, + (!areq) ? 0 : 1); if (areq) { if (unlikely(rc != -EINPROGRESS)) { - /* Failed to send the request or request completed synchronously */ + /* Failed to send the request or request completed + * synchronously + */ cc_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); } @@ -886,7 +908,10 @@ static int ssi_ablkcipher_encrypt(struct ablkcipher_request *req) req_ctx->is_giv = false; - return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_ENCRYPT); + return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, + req->nbytes, req->info, ivsize, + (void *)req, + DRV_CRYPTO_DIRECTION_ENCRYPT); } static int ssi_ablkcipher_decrypt(struct ablkcipher_request *req) @@ -908,7 +933,10 @@ static int ssi_ablkcipher_decrypt(struct ablkcipher_request *req) (req->nbytes - ivsize), ivsize, 0); req_ctx->is_giv = false; - return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_DECRYPT); + return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, + req->nbytes, req->info, ivsize, + (void *)req, + DRV_CRYPTO_DIRECTION_DECRYPT); } /* DX Block cipher alg */ diff --git a/drivers/staging/ccree/ssi_cipher.h b/drivers/staging/ccree/ssi_cipher.h index 25e6335c0d94..14c0ad99c0c5 100644 --- a/drivers/staging/ccree/ssi_cipher.h +++ b/drivers/staging/ccree/ssi_cipher.h @@ -33,7 +33,10 @@ #define CC_CRYPTO_CIPHER_KEY_KFDE3 BIT(3) #define CC_CRYPTO_CIPHER_DU_SIZE_512B BIT(4) -#define CC_CRYPTO_CIPHER_KEY_KFDE_MASK (CC_CRYPTO_CIPHER_KEY_KFDE0 | CC_CRYPTO_CIPHER_KEY_KFDE1 | CC_CRYPTO_CIPHER_KEY_KFDE2 | CC_CRYPTO_CIPHER_KEY_KFDE3) +#define CC_CRYPTO_CIPHER_KEY_KFDE_MASK (CC_CRYPTO_CIPHER_KEY_KFDE0 | \ + CC_CRYPTO_CIPHER_KEY_KFDE1 | \ + CC_CRYPTO_CIPHER_KEY_KFDE2 | \ + CC_CRYPTO_CIPHER_KEY_KFDE3) struct blkcipher_req_ctx { struct async_gen_req_ctx gen_ctx; diff --git a/drivers/staging/ccree/ssi_config.h b/drivers/staging/ccree/ssi_config.h index ff7597c2d77e..ea7484514645 100644 --- a/drivers/staging/ccree/ssi_config.h +++ b/drivers/staging/ccree/ssi_config.h @@ -28,9 +28,11 @@ //#define DX_DUMP_DESCS // #define DX_DUMP_BYTES // #define CC_DEBUG -#define ENABLE_CC_SYSFS /* Enable sysfs interface for debugging REE driver */ +/* Enable sysfs interface for debugging REE driver */ +#define ENABLE_CC_SYSFS //#define DX_IRQ_DELAY 100000 -#define DMA_BIT_MASK_LEN 48 /* was 32 bit, but for juno's sake it was enlarged to 48 bit */ +/* was 32 bit, but for juno's sake it was enlarged to 48 bit */ +#define DMA_BIT_MASK_LEN 48 #endif /*__DX_CONFIG_H__*/ diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index 8d1682365fbc..b17b81137db0 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -112,7 +112,9 @@ static irqreturn_t cc_isr(int irq, void *dev_id) drvdata->irq = irr; /* Completion interrupt - most probable */ if (likely((irr & SSI_COMP_IRQ_MASK))) { - /* Mask AXI completion interrupt - will be unmasked in Deferred service handler */ + /* Mask AXI completion interrupt - will be unmasked in + * Deferred service handler + */ cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | SSI_COMP_IRQ_MASK); irr &= ~SSI_COMP_IRQ_MASK; complete_request(drvdata); @@ -120,7 +122,9 @@ static irqreturn_t cc_isr(int irq, void *dev_id) #ifdef CC_SUPPORT_FIPS /* TEE FIPS interrupt */ if (likely((irr & SSI_GPR0_IRQ_MASK))) { - /* Mask interrupt - will be unmasked in Deferred service handler */ + /* Mask interrupt - will be unmasked in Deferred service + * handler + */ cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | SSI_GPR0_IRQ_MASK); irr &= ~SSI_GPR0_IRQ_MASK; fips_handler(drvdata); diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h index 758268e96dcc..7c266ff16462 100644 --- a/drivers/staging/ccree/ssi_driver.h +++ b/drivers/staging/ccree/ssi_driver.h @@ -63,8 +63,10 @@ #define SSI_CC_HAS_MULTI2 0 #define SSI_CC_HAS_CMAC 1 -#define SSI_AXI_IRQ_MASK ((1 << DX_AXIM_CFG_BRESPMASK_BIT_SHIFT) | (1 << DX_AXIM_CFG_RRESPMASK_BIT_SHIFT) | \ - (1 << DX_AXIM_CFG_INFLTMASK_BIT_SHIFT) | (1 << DX_AXIM_CFG_COMPMASK_BIT_SHIFT)) +#define SSI_AXI_IRQ_MASK ((1 << DX_AXIM_CFG_BRESPMASK_BIT_SHIFT) | \ + (1 << DX_AXIM_CFG_RRESPMASK_BIT_SHIFT) | \ + (1 << DX_AXIM_CFG_INFLTMASK_BIT_SHIFT) | \ + (1 << DX_AXIM_CFG_COMPMASK_BIT_SHIFT)) #define SSI_AXI_ERR_IRQ_MASK BIT(DX_HOST_IRR_AXI_ERR_INT_BIT_SHIFT) @@ -104,8 +106,10 @@ struct ssi_crypto_req { * generated IV would be placed in it by send_request(). * Same generated IV for all addresses! */ - unsigned int ivgen_dma_addr_len; /* Amount of 'ivgen_dma_addr' elements to be filled. */ - unsigned int ivgen_size; /* The generated IV size required, 8/16 B allowed. */ + /* Amount of 'ivgen_dma_addr' elements to be filled. */ + unsigned int ivgen_dma_addr_len; + /* The generated IV size required, 8/16 B allowed. */ + unsigned int ivgen_size; struct completion seq_compl; /* request completion */ }; @@ -178,7 +182,8 @@ static inline struct device *drvdata_to_dev(struct ssi_drvdata *drvdata) } #ifdef DX_DUMP_BYTES -void dump_byte_array(const char *name, const u8 *the_array, unsigned long size); +void dump_byte_array(const char *name, const u8 *the_array, + unsigned long size); #else static inline void dump_byte_array(const char *name, const u8 *the_array, unsigned long size) {}; diff --git a/drivers/staging/ccree/ssi_fips.h b/drivers/staging/ccree/ssi_fips.h index 63bcca7f3af9..8cb1893536a5 100644 --- a/drivers/staging/ccree/ssi_fips.h +++ b/drivers/staging/ccree/ssi_fips.h @@ -40,7 +40,8 @@ static inline int ssi_fips_init(struct ssi_drvdata *p_drvdata) } static inline void ssi_fips_fini(struct ssi_drvdata *drvdata) {} -static inline void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, bool ok) {} +static inline void cc_set_ree_fips_status(struct ssi_drvdata *drvdata, + bool ok) {} static inline void fips_handler(struct ssi_drvdata *drvdata) {} #endif /* CONFIG_CRYPTO_FIPS */ diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 716bbbdeb8bd..bf896a564039 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -164,18 +164,21 @@ static int ssi_hash_map_request(struct device *dev, if (!state->buff1) goto fail_buff0; - state->digest_result_buff = kzalloc(SSI_MAX_HASH_DIGEST_SIZE, GFP_KERNEL | GFP_DMA); + state->digest_result_buff = kzalloc(SSI_MAX_HASH_DIGEST_SIZE, + GFP_KERNEL | GFP_DMA); if (!state->digest_result_buff) goto fail_buff1; - state->digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL | GFP_DMA); + state->digest_buff = kzalloc(ctx->inter_digestsize, + GFP_KERNEL | GFP_DMA); if (!state->digest_buff) goto fail_digest_result_buff; dev_dbg(dev, "Allocated digest-buffer in context ctx->digest_buff=@%p\n", state->digest_buff); if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) { - state->digest_bytes_len = kzalloc(HASH_LEN_SIZE, GFP_KERNEL | GFP_DMA); + state->digest_bytes_len = kzalloc(HASH_LEN_SIZE, + GFP_KERNEL | GFP_DMA); if (!state->digest_bytes_len) goto fail1; @@ -185,14 +188,17 @@ static int ssi_hash_map_request(struct device *dev, state->digest_bytes_len = NULL; } - state->opad_digest_buff = kzalloc(ctx->inter_digestsize, GFP_KERNEL | GFP_DMA); + state->opad_digest_buff = kzalloc(ctx->inter_digestsize, + GFP_KERNEL | GFP_DMA); if (!state->opad_digest_buff) goto fail2; dev_dbg(dev, "Allocated opad-digest-buffer in context state->digest_bytes_len=@%p\n", state->opad_digest_buff); - state->digest_buff_dma_addr = dma_map_single(dev, (void *)state->digest_buff, ctx->inter_digestsize, DMA_BIDIRECTIONAL); + state->digest_buff_dma_addr = + dma_map_single(dev, (void *)state->digest_buff, + ctx->inter_digestsize, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, state->digest_buff_dma_addr)) { dev_err(dev, "Mapping digest len %d B at va=%pK for DMA failed\n", ctx->inter_digestsize, state->digest_buff); @@ -203,25 +209,39 @@ static int ssi_hash_map_request(struct device *dev, &state->digest_buff_dma_addr); if (is_hmac) { - dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); - if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC || ctx->hw_mode == DRV_CIPHER_CMAC) { + dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, + ctx->inter_digestsize, + DMA_BIDIRECTIONAL); + if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC || + ctx->hw_mode == DRV_CIPHER_CMAC) { memset(state->digest_buff, 0, ctx->inter_digestsize); } else { /*sha*/ - memcpy(state->digest_buff, ctx->digest_buff, ctx->inter_digestsize); + memcpy(state->digest_buff, ctx->digest_buff, + ctx->inter_digestsize); #if (DX_DEV_SHA_MAX > 256) - if (unlikely(ctx->hash_mode == DRV_HASH_SHA512 || ctx->hash_mode == DRV_HASH_SHA384)) - memcpy(state->digest_bytes_len, digest_len_sha512_init, HASH_LEN_SIZE); + if (unlikely(ctx->hash_mode == DRV_HASH_SHA512 || + ctx->hash_mode == DRV_HASH_SHA384)) + memcpy(state->digest_bytes_len, + digest_len_sha512_init, HASH_LEN_SIZE); else - memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE); + memcpy(state->digest_bytes_len, + digest_len_init, HASH_LEN_SIZE); #else - memcpy(state->digest_bytes_len, digest_len_init, HASH_LEN_SIZE); + memcpy(state->digest_bytes_len, digest_len_init, + HASH_LEN_SIZE); #endif } - dma_sync_single_for_device(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); + dma_sync_single_for_device(dev, state->digest_buff_dma_addr, + ctx->inter_digestsize, + DMA_BIDIRECTIONAL); if (ctx->hash_mode != DRV_HASH_NULL) { - dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); - memcpy(state->opad_digest_buff, ctx->opad_tmp_keys_buff, ctx->inter_digestsize); + dma_sync_single_for_cpu(dev, + ctx->opad_tmp_keys_dma_addr, + ctx->inter_digestsize, + DMA_BIDIRECTIONAL); + memcpy(state->opad_digest_buff, + ctx->opad_tmp_keys_buff, ctx->inter_digestsize); } } else { /*hash*/ /* Copy the initial digests if hash flow. The SRAM contains the @@ -241,7 +261,9 @@ static int ssi_hash_map_request(struct device *dev, } if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) { - state->digest_bytes_len_dma_addr = dma_map_single(dev, (void *)state->digest_bytes_len, HASH_LEN_SIZE, DMA_BIDIRECTIONAL); + state->digest_bytes_len_dma_addr = + dma_map_single(dev, (void *)state->digest_bytes_len, + HASH_LEN_SIZE, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, state->digest_bytes_len_dma_addr)) { dev_err(dev, "Mapping digest len %u B at va=%pK for DMA failed\n", HASH_LEN_SIZE, state->digest_bytes_len); @@ -255,7 +277,10 @@ static int ssi_hash_map_request(struct device *dev, } if (is_hmac && ctx->hash_mode != DRV_HASH_NULL) { - state->opad_digest_dma_addr = dma_map_single(dev, (void *)state->opad_digest_buff, ctx->inter_digestsize, DMA_BIDIRECTIONAL); + state->opad_digest_dma_addr = + dma_map_single(dev, (void *)state->opad_digest_buff, + ctx->inter_digestsize, + DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, state->opad_digest_dma_addr)) { dev_err(dev, "Mapping opad digest %d B at va=%pK for DMA failed\n", ctx->inter_digestsize, @@ -277,12 +302,14 @@ static int ssi_hash_map_request(struct device *dev, fail5: if (state->digest_bytes_len_dma_addr) { - dma_unmap_single(dev, state->digest_bytes_len_dma_addr, HASH_LEN_SIZE, DMA_BIDIRECTIONAL); + dma_unmap_single(dev, state->digest_bytes_len_dma_addr, + HASH_LEN_SIZE, DMA_BIDIRECTIONAL); state->digest_bytes_len_dma_addr = 0; } fail4: if (state->digest_buff_dma_addr) { - dma_unmap_single(dev, state->digest_buff_dma_addr, ctx->inter_digestsize, DMA_BIDIRECTIONAL); + dma_unmap_single(dev, state->digest_buff_dma_addr, + ctx->inter_digestsize, DMA_BIDIRECTIONAL); state->digest_buff_dma_addr = 0; } fail3: @@ -441,7 +468,9 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, ssi_req.user_arg = (void *)async_req; } - /* If HMAC then load hash IPAD xor key, if HASH then load initial digest */ + /* If HMAC then load hash IPAD xor key, if HASH then load initial + * digest + */ hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], ctx->hw_mode); if (is_hmac) { @@ -1042,8 +1071,9 @@ static int ssi_hash_setkey(void *hash, hw_desc_init(&desc[idx]); set_din_const(&desc[idx], 0, (blocksize - digestsize)); set_flow_mode(&desc[idx], BYPASS); - set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr + - digestsize), + set_dout_dlli(&desc[idx], + (ctx->opad_tmp_keys_dma_addr + + digestsize), (blocksize - digestsize), NS_BIT, 0); idx++; } else { @@ -1118,7 +1148,9 @@ static int ssi_hash_setkey(void *hash, set_flow_mode(&desc[idx], DIN_HASH); idx++; - /* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest of the first HASH "update" state) */ + /* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest + * of the first HASH "update" state) + */ hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], ctx->hw_mode); if (i > 0) /* Not first iteration */ @@ -1136,7 +1168,8 @@ static int ssi_hash_setkey(void *hash, out: if (rc) - crypto_ahash_set_flags((struct crypto_ahash *)hash, CRYPTO_TFM_RES_BAD_KEY_LEN); + crypto_ahash_set_flags((struct crypto_ahash *)hash, + CRYPTO_TFM_RES_BAD_KEY_LEN); if (ctx->key_params.key_dma_addr) { dma_unmap_single(dev, ctx->key_params.key_dma_addr, @@ -1257,8 +1290,10 @@ static int ssi_cmac_setkey(struct crypto_ahash *ahash, keylen, DMA_TO_DEVICE); memcpy(ctx->opad_tmp_keys_buff, key, keylen); - if (keylen == 24) - memset(ctx->opad_tmp_keys_buff + 24, 0, CC_AES_KEY_SIZE_MAX - 24); + if (keylen == 24) { + memset(ctx->opad_tmp_keys_buff + 24, 0, + CC_AES_KEY_SIZE_MAX - 24); + } dma_sync_single_for_device(dev, ctx->opad_tmp_keys_dma_addr, keylen, DMA_TO_DEVICE); @@ -1298,7 +1333,9 @@ static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx) ctx->key_params.keylen = 0; - ctx->digest_buff_dma_addr = dma_map_single(dev, (void *)ctx->digest_buff, sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); + ctx->digest_buff_dma_addr = + dma_map_single(dev, (void *)ctx->digest_buff, + sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, ctx->digest_buff_dma_addr)) { dev_err(dev, "Mapping digest len %zu B at va=%pK for DMA failed\n", sizeof(ctx->digest_buff), ctx->digest_buff); @@ -1308,7 +1345,10 @@ static int ssi_hash_alloc_ctx(struct ssi_hash_ctx *ctx) sizeof(ctx->digest_buff), ctx->digest_buff, &ctx->digest_buff_dma_addr); - ctx->opad_tmp_keys_dma_addr = dma_map_single(dev, (void *)ctx->opad_tmp_keys_buff, sizeof(ctx->opad_tmp_keys_buff), DMA_BIDIRECTIONAL); + ctx->opad_tmp_keys_dma_addr = + dma_map_single(dev, (void *)ctx->opad_tmp_keys_buff, + sizeof(ctx->opad_tmp_keys_buff), + DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, ctx->opad_tmp_keys_dma_addr)) { dev_err(dev, "Mapping opad digest %zu B at va=%pK for DMA failed\n", sizeof(ctx->opad_tmp_keys_buff), @@ -1335,7 +1375,8 @@ static int ssi_ahash_cra_init(struct crypto_tfm *tfm) struct ahash_alg *ahash_alg = container_of(hash_alg_common, struct ahash_alg, halg); struct ssi_hash_alg *ssi_alg = - container_of(ahash_alg, struct ssi_hash_alg, ahash_alg); + container_of(ahash_alg, struct ssi_hash_alg, + ahash_alg); crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), sizeof(struct ahash_req_ctx)); @@ -1473,7 +1514,9 @@ static int ssi_mac_final(struct ahash_request *req) set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); idx++; - /* Initiate decryption of block state to previous block_state-XOR-M[n] */ + /* Initiate decryption of block state to previous + * block_state-XOR-M[n] + */ hw_desc_init(&desc[idx]); set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, CC_AES_BLOCK_SIZE, NS_BIT); @@ -1502,7 +1545,8 @@ static int ssi_mac_final(struct ahash_request *req) set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; } else if (rem_cnt > 0) { - ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); + ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, + false, &idx); } else { hw_desc_init(&desc[idx]); set_din_const(&desc[idx], 0x00, CC_AES_BLOCK_SIZE); @@ -1579,7 +1623,8 @@ static int ssi_mac_finup(struct ahash_request *req) set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; } else { - ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); + ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, + false, &idx); } /* Get final MAC result */ @@ -1652,7 +1697,8 @@ static int ssi_mac_digest(struct ahash_request *req) set_flow_mode(&desc[idx], S_DIN_to_AES); idx++; } else { - ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); + ssi_hash_create_data_desc(state, ctx, DIN_AES_DOUT, desc, + false, &idx); } /* Get final MAC result */ @@ -1684,7 +1730,8 @@ static int ssi_ahash_digest(struct ahash_request *req) struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm); u32 digestsize = crypto_ahash_digestsize(tfm); - return ssi_hash_digest(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req); + return ssi_hash_digest(state, ctx, digestsize, req->src, req->nbytes, + req->result, (void *)req); } static int ssi_ahash_update(struct ahash_request *req) @@ -1694,7 +1741,8 @@ static int ssi_ahash_update(struct ahash_request *req) struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm); unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base); - return ssi_hash_update(state, ctx, block_size, req->src, req->nbytes, (void *)req); + return ssi_hash_update(state, ctx, block_size, req->src, req->nbytes, + (void *)req); } static int ssi_ahash_finup(struct ahash_request *req) @@ -1704,7 +1752,8 @@ static int ssi_ahash_finup(struct ahash_request *req) struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm); u32 digestsize = crypto_ahash_digestsize(tfm); - return ssi_hash_finup(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req); + return ssi_hash_finup(state, ctx, digestsize, req->src, req->nbytes, + req->result, (void *)req); } static int ssi_ahash_final(struct ahash_request *req) @@ -1714,7 +1763,8 @@ static int ssi_ahash_final(struct ahash_request *req) struct ssi_hash_ctx *ctx = crypto_ahash_ctx(tfm); u32 digestsize = crypto_ahash_digestsize(tfm); - return ssi_hash_final(state, ctx, digestsize, req->src, req->nbytes, req->result, (void *)req); + return ssi_hash_final(state, ctx, digestsize, req->src, req->nbytes, + req->result, (void *)req); } static int ssi_ahash_init(struct ahash_request *req) @@ -2173,7 +2223,9 @@ int ssi_hash_init_sram_digest_consts(struct ssi_drvdata *drvdata) larval_seq_len = 0; #if (DX_DEV_SHA_MAX > 256) - /* We are forced to swap each double-word larval before copying to sram */ + /* We are forced to swap each double-word larval before copying to + * sram + */ for (i = 0; i < ARRAY_SIZE(sha384_init); i++) { const u32 const0 = ((u32 *)((u64 *)&sha384_init[i]))[1]; const u32 const1 = ((u32 *)((u64 *)&sha384_init[i]))[0]; @@ -2323,7 +2375,8 @@ int ssi_hash_free(struct ssi_drvdata *drvdata) struct ssi_hash_handle *hash_handle = drvdata->hash_handle; if (hash_handle) { - list_for_each_entry_safe(t_hash_alg, hash_n, &hash_handle->hash_list, entry) { + list_for_each_entry_safe(t_hash_alg, hash_n, + &hash_handle->hash_list, entry) { crypto_unregister_ahash(&t_hash_alg->ahash_alg); list_del(&t_hash_alg->entry); kfree(t_hash_alg); diff --git a/drivers/staging/ccree/ssi_hash.h b/drivers/staging/ccree/ssi_hash.h index c884727aa906..8e6eee5b79f9 100644 --- a/drivers/staging/ccree/ssi_hash.h +++ b/drivers/staging/ccree/ssi_hash.h @@ -41,7 +41,9 @@ #define CC_EXPORT_MAGIC 0xC2EE1070U -// this struct was taken from drivers/crypto/nx/nx-aes-xcbc.c and it is used for xcbc/cmac statesize +/* this struct was taken from drivers/crypto/nx/nx-aes-xcbc.c and it is used + * for xcbc/cmac statesize + */ struct aeshash_state { u8 state[AES_BLOCK_SIZE]; unsigned int count; @@ -81,7 +83,8 @@ int ssi_hash_free(struct ssi_drvdata *drvdata); * Gets the initial digest length * * \param drvdata - * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512 + * \param mode The Hash mode. Supported modes: + * MD5/SHA1/SHA224/SHA256/SHA384/SHA512 * * \return u32 returns the address of the initial digest length in SRAM */ @@ -93,7 +96,8 @@ ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, u32 mode); * according to the given hash mode * * \param drvdata - * \param mode The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256/SHA384/SHA512 + * \param mode The Hash mode. Supported modes: + * MD5/SHA1/SHA224/SHA256/SHA384/SHA512 * * \return u32 The address of the initial digest in SRAM */ diff --git a/drivers/staging/ccree/ssi_ivgen.c b/drivers/staging/ccree/ssi_ivgen.c index 7171796888b4..4ca6ca7caf62 100644 --- a/drivers/staging/ccree/ssi_ivgen.c +++ b/drivers/staging/ccree/ssi_ivgen.c @@ -228,7 +228,8 @@ out: * * \param drvdata Driver private context * \param iv_out_dma Array of physical IV out addresses - * \param iv_out_dma_len Length of iv_out_dma array (additional elements of iv_out_dma array are ignore) + * \param iv_out_dma_len Length of iv_out_dma array (additional elements + * of iv_out_dma array are ignore) * \param iv_out_size May be 8 or 16 bytes long * \param iv_seq IN/OUT array to the descriptors sequence * \param iv_seq_len IN/OUT pointer to the sequence length @@ -257,7 +258,9 @@ int ssi_ivgen_getiv( return -EINVAL; } - //check that number of generated IV is limited to max dma address iv buffer size + /* check that number of generated IV is limited to max dma address + * iv buffer size + */ if (iv_out_dma_len > SSI_MAX_IVGEN_DMA_ADDRESSES) { /* The sequence will be longer than allowed */ return -EINVAL; diff --git a/drivers/staging/ccree/ssi_ivgen.h b/drivers/staging/ccree/ssi_ivgen.h index 961aea411cb3..fd28309adac6 100644 --- a/drivers/staging/ccree/ssi_ivgen.h +++ b/drivers/staging/ccree/ssi_ivgen.h @@ -53,7 +53,8 @@ int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata); * * \param drvdata Driver private context * \param iv_out_dma Array of physical IV out addresses - * \param iv_out_dma_len Length of iv_out_dma array (additional elements of iv_out_dma array are ignore) + * \param iv_out_dma_len Length of iv_out_dma array (additional elements of + * iv_out_dma array are ignore) * \param iv_out_size May be 8 or 16 bytes long * \param iv_seq IN/OUT array to the descriptors sequence * \param iv_seq_len IN/OUT pointer to the sequence length diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index ab1885110559..001bbe979396 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -123,7 +123,8 @@ int request_mgr_init(struct ssi_drvdata *drvdata) INIT_DELAYED_WORK(&req_mgr_h->compwork, comp_work_handler); #else dev_dbg(dev, "Initializing completion tasklet\n"); - tasklet_init(&req_mgr_h->comptask, comp_handler, (unsigned long)drvdata); + tasklet_init(&req_mgr_h->comptask, comp_handler, + (unsigned long)drvdata); #endif req_mgr_h->hw_queue_size = cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_SRAM_SIZE)); @@ -138,9 +139,10 @@ int request_mgr_init(struct ssi_drvdata *drvdata) req_mgr_h->max_used_sw_slots = 0; /* Allocate DMA word for "dummy" completion descriptor use */ - req_mgr_h->dummy_comp_buff = dma_alloc_coherent(dev, sizeof(u32), - &req_mgr_h->dummy_comp_buff_dma, - GFP_KERNEL); + req_mgr_h->dummy_comp_buff = + dma_alloc_coherent(dev, sizeof(u32), + &req_mgr_h->dummy_comp_buff_dma, + GFP_KERNEL); if (!req_mgr_h->dummy_comp_buff) { dev_err(dev, "Not enough memory to allocate DMA (%zu) dropped buffer\n", sizeof(u32)); @@ -272,10 +274,10 @@ int send_request( struct cc_hw_desc iv_seq[SSI_IVPOOL_SEQ_LEN]; struct device *dev = drvdata_to_dev(drvdata); int rc; - unsigned int max_required_seq_len = (total_seq_len + - ((ssi_req->ivgen_dma_addr_len == 0) ? 0 : - SSI_IVPOOL_SEQ_LEN) + - (!is_dout ? 1 : 0)); + unsigned int max_required_seq_len = + (total_seq_len + + ((ssi_req->ivgen_dma_addr_len == 0) ? 0 : + SSI_IVPOOL_SEQ_LEN) + (!is_dout ? 1 : 0)); #if defined(CONFIG_PM) rc = cc_pm_get(dev); @@ -349,13 +351,16 @@ int send_request( total_seq_len += iv_seq_len; } - used_sw_slots = ((req_mgr_h->req_queue_head - req_mgr_h->req_queue_tail) & (MAX_REQUEST_QUEUE_SIZE - 1)); + used_sw_slots = ((req_mgr_h->req_queue_head - + req_mgr_h->req_queue_tail) & + (MAX_REQUEST_QUEUE_SIZE - 1)); if (unlikely(used_sw_slots > req_mgr_h->max_used_sw_slots)) req_mgr_h->max_used_sw_slots = used_sw_slots; /* Enqueue request - must be locked with HW lock*/ req_mgr_h->req_queue[req_mgr_h->req_queue_head] = *ssi_req; - req_mgr_h->req_queue_head = (req_mgr_h->req_queue_head + 1) & (MAX_REQUEST_QUEUE_SIZE - 1); + req_mgr_h->req_queue_head = (req_mgr_h->req_queue_head + 1) & + (MAX_REQUEST_QUEUE_SIZE - 1); /* TODO: Use circ_buf.h ? */ dev_dbg(dev, "Enqueue request head=%u\n", req_mgr_h->req_queue_head); @@ -419,7 +424,8 @@ int send_request_init( unsigned int total_seq_len = len; /*initial sequence length*/ int rc = 0; - /* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT. */ + /* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT. + */ rc = request_mgr_queues_status_check(drvdata, req_mgr_h, total_seq_len); if (unlikely(rc)) @@ -447,7 +453,8 @@ void complete_request(struct ssi_drvdata *drvdata) struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; #ifdef COMP_IN_WQ - queue_delayed_work(request_mgr_handle->workq, &request_mgr_handle->compwork, 0); + queue_delayed_work(request_mgr_handle->workq, + &request_mgr_handle->compwork, 0); #else tasklet_schedule(&request_mgr_handle->comptask); #endif @@ -477,7 +484,8 @@ static void proc_completions(struct ssi_drvdata *drvdata) request_mgr_handle->axi_completed--; /* Dequeue request */ - if (unlikely(request_mgr_handle->req_queue_head == request_mgr_handle->req_queue_tail)) { + if (unlikely(request_mgr_handle->req_queue_head == + request_mgr_handle->req_queue_tail)) { /* We are supposed to handle a completion but our * queue is empty. This is not normal. Return and * hope for the best. @@ -508,7 +516,9 @@ static void proc_completions(struct ssi_drvdata *drvdata) if (likely(ssi_req->user_cb)) ssi_req->user_cb(dev, ssi_req->user_arg); - request_mgr_handle->req_queue_tail = (request_mgr_handle->req_queue_tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1); + request_mgr_handle->req_queue_tail = + (request_mgr_handle->req_queue_tail + 1) & + (MAX_REQUEST_QUEUE_SIZE - 1); dev_dbg(dev, "Dequeue request tail=%u\n", request_mgr_handle->req_queue_tail); dev_dbg(dev, "Request completed. axi_completed=%d\n", @@ -576,13 +586,14 @@ static void comp_handler(unsigned long devarg) } /* - * resume the queue configuration - no need to take the lock as this happens inside - * the spin lock protection + * resume the queue configuration - no need to take the lock as this happens + * inside the spin lock protection */ #if defined(CONFIG_PM) int cc_resume_req_queue(struct ssi_drvdata *drvdata) { - struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; + struct ssi_request_mgr_handle *request_mgr_handle = + drvdata->request_mgr_handle; spin_lock_bh(&request_mgr_handle->hw_lock); request_mgr_handle->is_runtime_suspended = false; diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index ed97decbe5e1..656215b34231 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -32,15 +32,26 @@ static ssize_t ssi_sys_regdump_show(struct kobject *kobj, int offset = 0; register_value = cc_ioread(drvdata, CC_REG(HOST_SIGNATURE)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_SIGNATURE ", DX_HOST_SIGNATURE_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "HOST_SIGNATURE ", + DX_HOST_SIGNATURE_REG_OFFSET, register_value); register_value = cc_ioread(drvdata, CC_REG(HOST_IRR)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_IRR ", DX_HOST_IRR_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "HOST_IRR ", + DX_HOST_IRR_REG_OFFSET, register_value); register_value = cc_ioread(drvdata, CC_REG(HOST_POWER_DOWN_EN)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_POWER_DOWN_EN ", DX_HOST_POWER_DOWN_EN_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "HOST_POWER_DOWN_EN ", + DX_HOST_POWER_DOWN_EN_REG_OFFSET, register_value); register_value = cc_ioread(drvdata, CC_REG(AXIM_MON_ERR)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "AXIM_MON_ERR ", DX_AXIM_MON_ERR_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "AXIM_MON_ERR ", + DX_AXIM_MON_ERR_REG_OFFSET, register_value); register_value = cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT)); - offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "DSCRPTR_QUEUE_CONTENT", DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET, register_value); + offset += scnprintf(buf + offset, PAGE_SIZE - offset, + "%s \t(0x%lX)\t 0x%08X\n", "DSCRPTR_QUEUE_CONTENT", + DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET, + register_value); return offset; } @@ -48,14 +59,16 @@ static ssize_t ssi_sys_help_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { static const char * const help_str[] = { - "cat reg_dump ", "Print several of CC register values", + "cat reg_dump ", + "Print several of CC register values", }; int i = 0, offset = 0; offset += scnprintf(buf + offset, PAGE_SIZE - offset, "Usage:\n"); for (i = 0; i < ARRAY_SIZE(help_str); i += 2) { offset += scnprintf(buf + offset, PAGE_SIZE - offset, - "%s\t\t%s\n", help_str[i], help_str[i + 1]); + "%s\t\t%s\n", help_str[i], + help_str[i + 1]); } return offset; @@ -84,8 +97,10 @@ static struct kobj_attribute ssi_sys_top_level_attrs[] = { __ATTR(dump_regs, 0444, ssi_sys_regdump_show, NULL), __ATTR(help, 0444, ssi_sys_help_show, NULL), #if defined CC_CYCLE_COUNT - __ATTR(stats_host, 0664, ssi_sys_stat_host_db_show, ssi_sys_stats_host_db_clear), - __ATTR(stats_cc, 0664, ssi_sys_stat_cc_db_show, ssi_sys_stats_cc_db_clear), + __ATTR(stats_host, 0664, ssi_sys_stat_host_db_show, + ssi_sys_stats_host_db_clear), + __ATTR(stats_cc, 0664, ssi_sys_stat_cc_db_show, + ssi_sys_stats_cc_db_clear), #endif }; -- cgit v1.2.3 From 5e1de0e7378ae9852c7f230a9ec55f39bf90b5bd Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:44 +0000 Subject: staging: ccree: remove dead defs and decls Remove no longer definitions of enums and forward declaration of functions dealing with sysfs interface of the long removed ccree cycle counter. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_sysfs.h | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_sysfs.h b/drivers/staging/ccree/ssi_sysfs.h index 44ae3d4c40b3..512452841694 100644 --- a/drivers/staging/ccree/ssi_sysfs.h +++ b/drivers/staging/ccree/ssi_sysfs.h @@ -26,30 +26,7 @@ /* forward declaration */ struct ssi_drvdata; -enum stat_phase { - STAT_PHASE_0 = 0, - STAT_PHASE_1, - STAT_PHASE_2, - STAT_PHASE_3, - STAT_PHASE_4, - STAT_PHASE_5, - STAT_PHASE_6, - MAX_STAT_PHASES, -}; - -enum stat_op { - STAT_OP_TYPE_NULL = 0, - STAT_OP_TYPE_ENCODE, - STAT_OP_TYPE_DECODE, - STAT_OP_TYPE_SETKEY, - STAT_OP_TYPE_GENERIC, - MAX_STAT_OP_TYPES, -}; - int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata); void ssi_sysfs_fini(void); -void update_host_stat(unsigned int op_type, unsigned int phase, cycles_t result); -void update_cc_stat(unsigned int op_type, unsigned int phase, unsigned int elapsed_cycles); -void display_all_stat_db(void); #endif /*__SSI_SYSFS_H__*/ -- cgit v1.2.3 From 896d236f74ffd7c5fc70db5d0f0970286f460e9f Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:45 +0000 Subject: staging: ccree: refactor code with local vars Refactor the queue handling loop using local variables for better code readability. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_request_mgr.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 001bbe979396..a2a82ef9e143 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -476,6 +476,8 @@ static void proc_completions(struct ssi_drvdata *drvdata) struct device *dev = drvdata_to_dev(drvdata); struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; + unsigned int *tail = &request_mgr_handle->req_queue_tail; + unsigned int *head = &request_mgr_handle->req_queue_head; #if defined(CONFIG_PM) int rc = 0; #endif @@ -484,18 +486,17 @@ static void proc_completions(struct ssi_drvdata *drvdata) request_mgr_handle->axi_completed--; /* Dequeue request */ - if (unlikely(request_mgr_handle->req_queue_head == - request_mgr_handle->req_queue_tail)) { + if (unlikely(*head == *tail)) { /* We are supposed to handle a completion but our * queue is empty. This is not normal. Return and * hope for the best. */ dev_err(dev, "Request queue is empty head == tail %u\n", - request_mgr_handle->req_queue_head); + *head); break; } - ssi_req = &request_mgr_handle->req_queue[request_mgr_handle->req_queue_tail]; + ssi_req = &request_mgr_handle->req_queue[*tail]; #ifdef FLUSH_CACHE_ALL flush_cache_all(); @@ -516,11 +517,8 @@ static void proc_completions(struct ssi_drvdata *drvdata) if (likely(ssi_req->user_cb)) ssi_req->user_cb(dev, ssi_req->user_arg); - request_mgr_handle->req_queue_tail = - (request_mgr_handle->req_queue_tail + 1) & - (MAX_REQUEST_QUEUE_SIZE - 1); - dev_dbg(dev, "Dequeue request tail=%u\n", - request_mgr_handle->req_queue_tail); + *tail = (*tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1); + dev_dbg(dev, "Dequeue request tail=%u\n", *tail); dev_dbg(dev, "Request completed. axi_completed=%d\n", request_mgr_handle->axi_completed); #if defined(CONFIG_PM) -- cgit v1.2.3 From d86601600a63cc5db6767c96bf5bf52ce41b2af4 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:46 +0000 Subject: staging: ccree: rename func for readability Rename the insanely long ssi_ahash_get_larval_digest_sram_addr() func to cc_larval_digest_addr() for better code readability Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 7 +++---- drivers/staging/ccree/ssi_hash.c | 13 ++++++------- drivers/staging/ccree/ssi_hash.h | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index e2cdf527c3af..fcff625f8d2d 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -336,8 +336,8 @@ static int hmac_setkey(struct cc_hw_desc *desc, struct ssi_aead_ctx *ctx) hw_desc_init(&desc[idx]); set_cipher_mode(&desc[idx], hash_mode); set_din_sram(&desc[idx], - ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->auth_mode), + cc_larval_digest_addr(ctx->drvdata, + ctx->auth_mode), digest_size); set_flow_mode(&desc[idx], S_DIN_to_HASH); set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); @@ -441,8 +441,7 @@ ssi_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *key, dma_addr_t key_dma_addr = 0; struct ssi_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev = drvdata_to_dev(ctx->drvdata); - u32 larval_addr = ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->auth_mode); + u32 larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->auth_mode); struct ssi_crypto_req ssi_req = {}; unsigned int blocksize; unsigned int digestsize; diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index bf896a564039..10e902c9d7fe 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -150,8 +150,8 @@ static int ssi_hash_map_request(struct device *dev, struct ssi_hash_ctx *ctx) { bool is_hmac = ctx->is_hmac; - ssi_sram_addr_t larval_digest_addr = ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->hash_mode); + ssi_sram_addr_t larval_digest_addr = + cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); struct ssi_crypto_req ssi_req = {}; struct cc_hw_desc desc; int rc = -ENOMEM; @@ -438,8 +438,8 @@ static int ssi_hash_digest(struct ahash_req_ctx *state, bool is_hmac = ctx->is_hmac; struct ssi_crypto_req ssi_req = {}; struct cc_hw_desc desc[SSI_MAX_AHASH_SEQ_LEN]; - ssi_sram_addr_t larval_digest_addr = ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->hash_mode); + ssi_sram_addr_t larval_digest_addr = + cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); int idx = 0; int rc = 0; @@ -1008,8 +1008,7 @@ static int ssi_hash_setkey(void *hash, blocksize = crypto_tfm_alg_blocksize(&((struct crypto_ahash *)hash)->base); digestsize = crypto_ahash_digestsize(((struct crypto_ahash *)hash)); - larval_addr = ssi_ahash_get_larval_digest_sram_addr( - ctx->drvdata, ctx->hash_mode); + larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); /* The keylen value distinguishes HASH in case keylen is ZERO bytes, * any NON-ZERO value utilizes HMAC flow @@ -2535,7 +2534,7 @@ static void ssi_hash_create_data_desc(struct ahash_req_ctx *areq_ctx, * * \return u32 The address of the initial digest in SRAM */ -ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode) +ssi_sram_addr_t cc_larval_digest_addr(void *drvdata, u32 mode) { struct ssi_drvdata *_drvdata = (struct ssi_drvdata *)drvdata; struct ssi_hash_handle *hash_handle = _drvdata->hash_handle; diff --git a/drivers/staging/ccree/ssi_hash.h b/drivers/staging/ccree/ssi_hash.h index 8e6eee5b79f9..32eb47388f93 100644 --- a/drivers/staging/ccree/ssi_hash.h +++ b/drivers/staging/ccree/ssi_hash.h @@ -101,7 +101,7 @@ ssi_ahash_get_initial_digest_len_sram_addr(void *drvdata, u32 mode); * * \return u32 The address of the initial digest in SRAM */ -ssi_sram_addr_t ssi_ahash_get_larval_digest_sram_addr(void *drvdata, u32 mode); +ssi_sram_addr_t cc_larval_digest_addr(void *drvdata, u32 mode); #endif /*__SSI_HASH_H__*/ -- cgit v1.2.3 From 37f98f838427b5620ed97b54fb62876c5a307587 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:47 +0000 Subject: staging: ccree: rename long define for readability Rename the too long SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE to SSI_MAX_OPAD_KEYS_SIZE for better code readability. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 10e902c9d7fe..34badb2c72cc 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -32,7 +32,7 @@ #include "ssi_sram_mgr.h" #define SSI_MAX_AHASH_SEQ_LEN 12 -#define SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE SSI_MAX_HASH_BLCK_SIZE +#define SSI_MAX_OPAD_KEYS_SIZE SSI_MAX_HASH_BLCK_SIZE struct ssi_hash_handle { ssi_sram_addr_t digest_len_sram_addr; /* const value in SRAM*/ @@ -94,7 +94,7 @@ struct ssi_hash_ctx { * the initial digest if HASH. */ u8 digest_buff[SSI_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned; - u8 opad_tmp_keys_buff[SSI_MAX_HASH_OPAD_TMP_KEYS_SIZE] ____cacheline_aligned; + u8 opad_tmp_keys_buff[SSI_MAX_OPAD_KEYS_SIZE] ____cacheline_aligned; dma_addr_t opad_tmp_keys_dma_addr ____cacheline_aligned; dma_addr_t digest_buff_dma_addr; -- cgit v1.2.3 From 00fb304d6319eacfa048ed9735a455b8b869fd42 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:48 +0000 Subject: staging: ccree: remove unneeded wrapper function Remove unneeded wrapper function to simplify code. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_hash.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_hash.c b/drivers/staging/ccree/ssi_hash.c index 34badb2c72cc..4d79725357a7 100644 --- a/drivers/staging/ccree/ssi_hash.c +++ b/drivers/staging/ccree/ssi_hash.c @@ -986,10 +986,8 @@ static int ssi_hash_init(struct ahash_req_ctx *state, struct ssi_hash_ctx *ctx) return 0; } -static int ssi_hash_setkey(void *hash, - const u8 *key, - unsigned int keylen, - bool synchronize) +static int ssi_ahash_setkey(struct crypto_ahash *ahash, const u8 *key, + unsigned int keylen) { unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; struct ssi_crypto_req ssi_req = {}; @@ -1001,12 +999,12 @@ static int ssi_hash_setkey(void *hash, ssi_sram_addr_t larval_addr; struct device *dev; - ctx = crypto_ahash_ctx(((struct crypto_ahash *)hash)); + ctx = crypto_ahash_ctx(ahash); dev = drvdata_to_dev(ctx->drvdata); dev_dbg(dev, "start keylen: %d", keylen); - blocksize = crypto_tfm_alg_blocksize(&((struct crypto_ahash *)hash)->base); - digestsize = crypto_ahash_digestsize(((struct crypto_ahash *)hash)); + blocksize = crypto_tfm_alg_blocksize(&ahash->base); + digestsize = crypto_ahash_digestsize(ahash); larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); @@ -1167,8 +1165,7 @@ static int ssi_hash_setkey(void *hash, out: if (rc) - crypto_ahash_set_flags((struct crypto_ahash *)hash, - CRYPTO_TFM_RES_BAD_KEY_LEN); + crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); if (ctx->key_params.key_dma_addr) { dma_unmap_single(dev, ctx->key_params.key_dma_addr, @@ -1876,12 +1873,6 @@ out: return rc; } -static int ssi_ahash_setkey(struct crypto_ahash *ahash, - const u8 *key, unsigned int keylen) -{ - return ssi_hash_setkey((void *)ahash, key, keylen, false); -} - struct ssi_hash_template { char name[CRYPTO_MAX_ALG_NAME]; char driver_name[CRYPTO_MAX_ALG_NAME]; -- cgit v1.2.3 From 5a83a3937bb06c46a67a05dbc4ddbd433ed11a7c Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:49 +0000 Subject: staging: ccree: remove unused field Field monitor_null_cycles of struct drvdata was not being used. Remove it. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_driver.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h index 7c266ff16462..ff9f5aaa6732 100644 --- a/drivers/staging/ccree/ssi_driver.h +++ b/drivers/staging/ccree/ssi_driver.h @@ -125,10 +125,6 @@ struct ssi_drvdata { int irq; u32 irq_mask; u32 fw_ver; - /* Calibration time of start/stop - * monitor descriptors - */ - u32 monitor_null_cycles; struct platform_device *plat_dev; ssi_sram_addr_t mlli_sram_addr; void *buff_mgr_handle; -- cgit v1.2.3 From d59c6d9cee8c8c66a0fe67e025a32266cc963e16 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:50 +0000 Subject: staging: ccree: replace msleep with a completion When the driver would try to queue commands to the HW FIFO but ran out of slots it would use msleep as a delay until the FIFO would clear. This is messy and not accurate. Replace the msleep with a proper completion on the event of command completion which should indicate at least one slot is free. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_driver.c | 2 ++ drivers/staging/ccree/ssi_driver.h | 1 + drivers/staging/ccree/ssi_request_mgr.c | 7 +++++-- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_driver.c b/drivers/staging/ccree/ssi_driver.c index b17b81137db0..3cb22967afb7 100644 --- a/drivers/staging/ccree/ssi_driver.c +++ b/drivers/staging/ccree/ssi_driver.c @@ -251,6 +251,8 @@ static int init_cc_resources(struct platform_device *plat_dev) } dev_dbg(dev, "Registered to IRQ: %d\n", new_drvdata->irq); + init_completion(&new_drvdata->hw_queue_avail); + if (!plat_dev->dev.dma_mask) plat_dev->dev.dma_mask = &plat_dev->dev.coherent_dma_mask; diff --git a/drivers/staging/ccree/ssi_driver.h b/drivers/staging/ccree/ssi_driver.h index ff9f5aaa6732..f92867b76073 100644 --- a/drivers/staging/ccree/ssi_driver.h +++ b/drivers/staging/ccree/ssi_driver.h @@ -125,6 +125,7 @@ struct ssi_drvdata { int irq; u32 irq_mask; u32 fw_ver; + struct completion hw_queue_avail; /* wait for HW queue availability */ struct platform_device *plat_dev; ssi_sram_addr_t mlli_sram_addr; void *buff_mgr_handle; diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index a2a82ef9e143..0882efd208ab 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -312,8 +312,9 @@ int send_request( return rc; } - /* HW queue is full - short sleep */ - msleep(1); + /* HW queue is full - wait for it to clear up */ + wait_for_completion_interruptible(&drvdata->hw_queue_avail); + reinit_completion(&drvdata->hw_queue_avail); } while (1); /* Additional completion descriptor is needed incase caller did not @@ -452,6 +453,8 @@ void complete_request(struct ssi_drvdata *drvdata) { struct ssi_request_mgr_handle *request_mgr_handle = drvdata->request_mgr_handle; + + complete(&drvdata->hw_queue_avail); #ifdef COMP_IN_WQ queue_delayed_work(request_mgr_handle->workq, &request_mgr_handle->compwork, 0); -- cgit v1.2.3 From c804f359924b54a35747d65755fdfaacce94dbd5 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:51 +0000 Subject: staging: ccree: use local vars for readability Refactor cc_map_aead_request() to use local vars for addresses for better readability of code. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_buffer_mgr.c | 64 +++++++++++++++------------------- 1 file changed, 29 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_buffer_mgr.c b/drivers/staging/ccree/ssi_buffer_mgr.c index 966033d03b2f..c5422250dfe5 100644 --- a/drivers/staging/ccree/ssi_buffer_mgr.c +++ b/drivers/staging/ccree/ssi_buffer_mgr.c @@ -1259,7 +1259,7 @@ int cc_map_aead_request( int rc = 0; struct crypto_aead *tfm = crypto_aead_reqtfm(req); bool is_gcm4543 = areq_ctx->is_gcm4543; - + dma_addr_t dma_addr; u32 mapped_nents = 0; u32 dummy = 0; /*used for the assoc data fragments */ u32 size_to_map = 0; @@ -1281,32 +1281,31 @@ int cc_map_aead_request( req->cryptlen : (req->cryptlen - authsize); - areq_ctx->mac_buf_dma_addr = dma_map_single(dev, areq_ctx->mac_buf, - MAX_MAC_SIZE, - DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, areq_ctx->mac_buf_dma_addr))) { + dma_addr = dma_map_single(dev, areq_ctx->mac_buf, MAX_MAC_SIZE, + DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(dev, dma_addr))) { dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n", MAX_MAC_SIZE, areq_ctx->mac_buf); rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->mac_buf_dma_addr = dma_addr; if (areq_ctx->ccm_hdr_size != ccm_header_size_null) { - areq_ctx->ccm_iv0_dma_addr = - dma_map_single(dev, (areq_ctx->ccm_config + - CCM_CTR_COUNT_0_OFFSET), - AES_BLOCK_SIZE, DMA_TO_DEVICE); + void *addr = areq_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET; - if (unlikely(dma_mapping_error(dev, - areq_ctx->ccm_iv0_dma_addr))) { + dma_addr = dma_map_single(dev, addr, AES_BLOCK_SIZE, + DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(dev, dma_addr))) { dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n", - AES_BLOCK_SIZE, - (areq_ctx->ccm_config + - CCM_CTR_COUNT_0_OFFSET)); + AES_BLOCK_SIZE, addr); areq_ctx->ccm_iv0_dma_addr = 0; rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->ccm_iv0_dma_addr = dma_addr; + if (ssi_aead_handle_config_buf(dev, areq_ctx, areq_ctx->ccm_config, &sg_data, req->assoclen)) { @@ -1317,54 +1316,49 @@ int cc_map_aead_request( #if SSI_CC_HAS_AES_GCM if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) { - areq_ctx->hkey_dma_addr = dma_map_single(dev, - areq_ctx->hkey, - AES_BLOCK_SIZE, - DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, - areq_ctx->hkey_dma_addr))) { + dma_addr = dma_map_single(dev, areq_ctx->hkey, AES_BLOCK_SIZE, + DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(dev, dma_addr))) { dev_err(dev, "Mapping hkey %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, areq_ctx->hkey); rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->hkey_dma_addr = dma_addr; - areq_ctx->gcm_block_len_dma_addr = - dma_map_single(dev, &areq_ctx->gcm_len_block, - AES_BLOCK_SIZE, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, - areq_ctx->gcm_block_len_dma_addr))) { + dma_addr = dma_map_single(dev, &areq_ctx->gcm_len_block, + AES_BLOCK_SIZE, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev, dma_addr))) { dev_err(dev, "Mapping gcm_len_block %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, &areq_ctx->gcm_len_block); rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->gcm_block_len_dma_addr = dma_addr; - areq_ctx->gcm_iv_inc1_dma_addr = - dma_map_single(dev, areq_ctx->gcm_iv_inc1, - AES_BLOCK_SIZE, DMA_TO_DEVICE); + dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc1, + AES_BLOCK_SIZE, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, - areq_ctx->gcm_iv_inc1_dma_addr))) { + if (unlikely(dma_mapping_error(dev, dma_addr))) { dev_err(dev, "Mapping gcm_iv_inc1 %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc1)); areq_ctx->gcm_iv_inc1_dma_addr = 0; rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->gcm_iv_inc1_dma_addr = dma_addr; - areq_ctx->gcm_iv_inc2_dma_addr = - dma_map_single(dev, areq_ctx->gcm_iv_inc2, - AES_BLOCK_SIZE, DMA_TO_DEVICE); + dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc2, + AES_BLOCK_SIZE, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, - areq_ctx->gcm_iv_inc2_dma_addr))) { + if (unlikely(dma_mapping_error(dev, dma_addr))) { dev_err(dev, "Mapping gcm_iv_inc2 %u B at va=%pK for DMA failed\n", AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc2)); areq_ctx->gcm_iv_inc2_dma_addr = 0; rc = -ENOMEM; goto aead_map_failure; } + areq_ctx->gcm_iv_inc2_dma_addr = dma_addr; } #endif /*SSI_CC_HAS_AES_GCM*/ -- cgit v1.2.3 From d5a2a8186854982d6eeee6cf1c66ba5e5fe64125 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 13 Nov 2017 14:45:52 +0000 Subject: staging: ccree: drop unused macro The CC_REG_NAME macro is unused. Drop it. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/cc_hw_queue_defs.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/cc_hw_queue_defs.h b/drivers/staging/ccree/cc_hw_queue_defs.h index 2ae0f655e7a0..c5aaa79dcfc0 100644 --- a/drivers/staging/ccree/cc_hw_queue_defs.h +++ b/drivers/staging/ccree/cc_hw_queue_defs.h @@ -30,8 +30,6 @@ /* Define max. available slots in HW queue */ #define HW_QUEUE_SLOTS_MAX 15 -#define CC_REG_NAME(word, name) DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name - #define CC_REG_LOW(word, name) \ (DX_DSCRPTR_QUEUE_WORD ## word ## _ ## name ## _BIT_SHIFT) -- cgit v1.2.3 From 217f93366ec7f6f6d85dba901b6e3cc312ef6ec6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 17 Nov 2017 18:19:08 +0000 Subject: staging: ccree: fix incorrect indentation of break statement The break statement is indented one level too many, fix this. Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_aead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_aead.c b/drivers/staging/ccree/ssi_aead.c index fcff625f8d2d..2cd2b0f7cb15 100644 --- a/drivers/staging/ccree/ssi_aead.c +++ b/drivers/staging/ccree/ssi_aead.c @@ -2160,7 +2160,7 @@ static int ssi_aead_process(struct aead_request *req, if (ctx->cipher_mode == DRV_CIPHER_GCTR) ssi_aead_gcm(req, desc, &seq_len); #endif /*SSI_CC_HAS_AES_GCM*/ - break; + break; #endif default: dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode); -- cgit v1.2.3 From 15bfaf777712f62e5d0c99b78e27978dab9a56c1 Mon Sep 17 00:00:00 2001 From: Joshua Abraham Date: Tue, 7 Nov 2017 13:24:25 -0500 Subject: staging: dgnc: Fix usleep_range is preferred over udelay This patch fixes the issue: CHECK: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt Signed-off-by: Joshua Abraham Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/dgnc_cls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 9639035fddd1..e264fe11cba4 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -397,7 +397,7 @@ static void cls_assert_modem_signals(struct channel_t *ch) writeb(out, &ch->ch_cls_uart->mcr); /* Give time for the UART to actually drop the signals */ - udelay(10); + usleep_range(10, 20); } static void cls_copy_data_from_queue_to_uart(struct channel_t *ch) -- cgit v1.2.3 From 6b549e20b63421e8655f7fe3612de414ec16ee2a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 8 Nov 2017 13:30:31 +0000 Subject: staging: rtlwifi: remove redundant assignments to ul_enc_algo Variable ul_enc_algo is being initialized with a value that is never read, it is being set again in the following switch statements in all of the case and default paths. Hence the unitialization is redundant and can be removed. Cleans up two clang warnings: Value stored to 'ul_enc_algo' during its initialization is never read Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtlwifi/cam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtlwifi/cam.c b/drivers/staging/rtlwifi/cam.c index 9c8c907cb48e..ca1c9e36d976 100644 --- a/drivers/staging/rtlwifi/cam.c +++ b/drivers/staging/rtlwifi/cam.c @@ -181,7 +181,7 @@ void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index) u32 ul_command; u32 ul_content; - u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; + u32 ul_enc_algo; switch (rtlpriv->sec.pairwise_enc_algorithm) { case WEP40_ENCRYPTION: @@ -221,7 +221,7 @@ void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) u32 ul_command; u32 ul_content; - u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; + u32 ul_encalgo; u8 entry_i; switch (rtlpriv->sec.pairwise_enc_algorithm) { -- cgit v1.2.3 From f6829ad6179906da6c2f7fd4ce526f4bb2e03579 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 7 Nov 2017 11:43:34 +0100 Subject: staging: rtlwifi: rtlwifi: use ktime_get_real_seconds() for suspend time do_gettimeofday() is deprecated and slower than necessary for the purpose of reading the seconds. This changes rtl_op_suspend/resume to use ktime_get_real_seconds() instead, which is simpler and avoids confusion about whether it is y2038-safe or not. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtlwifi/core.c | 8 ++------ drivers/staging/rtlwifi/wifi.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtlwifi/core.c b/drivers/staging/rtlwifi/core.c index b00e51df984f..a43d37452e8b 100644 --- a/drivers/staging/rtlwifi/core.c +++ b/drivers/staging/rtlwifi/core.c @@ -509,15 +509,13 @@ static int rtl_op_suspend(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct timeval ts; RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n"); if (WARN_ON(!wow)) return -EINVAL; /* to resolve s4 can not wake up*/ - do_gettimeofday(&ts); - rtlhal->last_suspend_sec = ts.tv_sec; + rtlhal->last_suspend_sec = ktime_get_real_seconds(); if ((ppsc->wo_wlan_mode & WAKE_ON_PATTERN_MATCH) && wow->n_patterns) _rtl_add_wowlan_patterns(hw, wow); @@ -536,7 +534,6 @@ static int rtl_op_resume(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct timeval ts; RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n"); rtlhal->driver_is_goingto_unload = false; @@ -544,8 +541,7 @@ static int rtl_op_resume(struct ieee80211_hw *hw) rtlhal->wake_from_pnp_sleep = true; /* to resovle s4 can not wake up*/ - do_gettimeofday(&ts); - if (ts.tv_sec - rtlhal->last_suspend_sec < 5) + if (ktime_get_real_seconds() - rtlhal->last_suspend_sec < 5) return -1; rtl_op_start(hw); diff --git a/drivers/staging/rtlwifi/wifi.h b/drivers/staging/rtlwifi/wifi.h index eb91c130b245..ca0243fa2e66 100644 --- a/drivers/staging/rtlwifi/wifi.h +++ b/drivers/staging/rtlwifi/wifi.h @@ -1670,7 +1670,7 @@ struct rtl_hal { bool enter_pnp_sleep; bool wake_from_pnp_sleep; bool wow_enabled; - __kernel_time_t last_suspend_sec; + time64_t last_suspend_sec; u32 wowlan_fwsize; u8 *wowlan_firmware; -- cgit v1.2.3 From d69b9c3884bf9dceab7d971eaab7a89887b60378 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 10 Nov 2017 16:13:03 -0600 Subject: staging: speakup: selection: replace _manual_ swap with swap macro Make use of the swap macro instead of _manually_ swapping values and remove unnecessary variable tmp. This makes the code easier to read and maintain. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Samuel Thibault Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/selection.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index 66061b5c3427..0ed1fefee0e9 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -64,13 +64,8 @@ int speakup_set_selection(struct tty_struct *tty) ps = spk_ys * vc->vc_size_row + (spk_xs << 1); pe = spk_ye * vc->vc_size_row + (spk_xe << 1); - if (ps > pe) { - /* make sel_start <= sel_end */ - int tmp = ps; - - ps = pe; - pe = tmp; - } + if (ps > pe) /* make sel_start <= sel_end */ + swap(ps, pe); if (spk_sel_cons != vc_cons[fg_console].d) { speakup_clear_selection(); -- cgit v1.2.3 From bc4eec76e66ec5c53b93f9ee0b0a1689f7307ce5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 7 Nov 2017 19:07:24 +0000 Subject: staging: comedi: usbdux: remove redundant initialization of val The early initialization of val is redundant as the value is never read and is updated inside a for-loop. Remove the initialization and move the declaration and initialization to the for-loop scope. Cleans up clang warning: drivers/staging/comedi/drivers/usbdux.c:812:15: warning: Value stored to 'val' during its initialization is never read Signed-off-by: Colin Ian King Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index f4f05d29d30d..ede064b47aac 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -809,7 +809,6 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, { struct usbdux_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int val = s->readback[chan]; __le16 *p = (__le16 *)&devpriv->dux_commands[2]; int ret = -EBUSY; int i; @@ -825,7 +824,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, devpriv->dux_commands[4] = chan << 6; for (i = 0; i < insn->n; i++) { - val = data[i]; + unsigned int val = data[i]; /* one 16 bit value */ *p = cpu_to_le16(val); -- cgit v1.2.3 From 8ba6b44a5aa0358bc98ad84a47f9e9b902c98c48 Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:25 +0200 Subject: staging: fsl-mc: drop unused dpcon APIs Couple of API functions are not used so lets drop them together with the associated structures and defines. Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpcon-cmd.h | 6 --- drivers/staging/fsl-mc/bus/dpcon.c | 69 ---------------------------------- drivers/staging/fsl-mc/include/dpcon.h | 10 ----- 3 files changed, 85 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpcon-cmd.h b/drivers/staging/fsl-mc/bus/dpcon-cmd.h index 2bb66988ecf6..d2ba8193fdef 100644 --- a/drivers/staging/fsl-mc/bus/dpcon-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpcon-cmd.h @@ -45,13 +45,11 @@ /* Command IDs */ #define DPCON_CMDID_CLOSE DPCON_CMD(0x800) #define DPCON_CMDID_OPEN DPCON_CMD(0x808) -#define DPCON_CMDID_GET_API_VERSION DPCON_CMD(0xa08) #define DPCON_CMDID_ENABLE DPCON_CMD(0x002) #define DPCON_CMDID_DISABLE DPCON_CMD(0x003) #define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004) #define DPCON_CMDID_RESET DPCON_CMD(0x005) -#define DPCON_CMDID_IS_ENABLED DPCON_CMD(0x006) #define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100) @@ -61,10 +59,6 @@ struct dpcon_cmd_open { #define DPCON_ENABLE 1 -struct dpcon_rsp_is_enabled { - u8 enabled; -}; - struct dpcon_rsp_get_attr { /* response word 0 */ __le32 id; diff --git a/drivers/staging/fsl-mc/bus/dpcon.c b/drivers/staging/fsl-mc/bus/dpcon.c index ca1da85c6dda..ce7c0bfab4ab 100644 --- a/drivers/staging/fsl-mc/bus/dpcon.c +++ b/drivers/staging/fsl-mc/bus/dpcon.c @@ -155,42 +155,6 @@ int dpcon_disable(struct fsl_mc_io *mc_io, } EXPORT_SYMBOL(dpcon_disable); -/** - * dpcon_is_enabled() - Check if the DPCON is enabled. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPCON object - * @en: Returns '1' if object is enabled; '0' otherwise - * - * Return: '0' on Success; Error code otherwise. - */ -int dpcon_is_enabled(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int *en) -{ - struct mc_command cmd = { 0 }; - struct dpcon_rsp_is_enabled *dpcon_rsp; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED, - cmd_flags, - token); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - dpcon_rsp = (struct dpcon_rsp_is_enabled *)cmd.params; - *en = dpcon_rsp->enabled & DPCON_ENABLE; - - return 0; -} -EXPORT_SYMBOL(dpcon_is_enabled); - /** * dpcon_reset() - Reset the DPCON, returns the object to initial state. * @mc_io: Pointer to MC portal's I/O object @@ -282,36 +246,3 @@ int dpcon_set_notification(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } EXPORT_SYMBOL(dpcon_set_notification); - -/** - * dpcon_get_api_version - Get Data Path Concentrator API version - * @mc_io: Pointer to MC portal's DPCON object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @major_ver: Major version of DPCON API - * @minor_ver: Minor version of DPCON API - * - * Return: '0' on Success; Error code otherwise - */ -int dpcon_get_api_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 *major_ver, - u16 *minor_ver) -{ - struct mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_API_VERSION, - cmd_flags, 0); - - /* send command to mc */ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - mc_cmd_read_api_version(&cmd, major_ver, minor_ver); - - return 0; -} -EXPORT_SYMBOL(dpcon_get_api_version); diff --git a/drivers/staging/fsl-mc/include/dpcon.h b/drivers/staging/fsl-mc/include/dpcon.h index efa23906b364..425749e7c681 100644 --- a/drivers/staging/fsl-mc/include/dpcon.h +++ b/drivers/staging/fsl-mc/include/dpcon.h @@ -62,11 +62,6 @@ int dpcon_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -int dpcon_is_enabled(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - int *en); - int dpcon_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); @@ -107,9 +102,4 @@ int dpcon_set_notification(struct fsl_mc_io *mc_io, u16 token, struct dpcon_notification_cfg *cfg); -int dpcon_get_api_version(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 *major_ver, - u16 *minor_ver); - #endif /* __FSL_DPCON_H */ -- cgit v1.2.3 From 2b0ff43ae5ea8c21ee142cc5ae6b42aadfc3260b Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:26 +0200 Subject: staging: fsl-mc/dpio: remove incomplete refcount implementation There's an unfinished implementation of reference counting for dpaa2_io structure using atomics. Since it's unused lets remove it for now and, if needed at a later time, make use of krefs instead of rolling our own refcounting. Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpio/dpio-service.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c index a609ec82daf3..591d8b7d4f49 100644 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c @@ -43,7 +43,6 @@ #include "qbman-portal.h" struct dpaa2_io { - atomic_t refs; struct dpaa2_io_desc dpio_desc; struct qbman_swp_desc swp_desc; struct qbman_swp *swp; @@ -126,7 +125,6 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) return NULL; } - atomic_set(&obj->refs, 1); obj->dpio_desc = *desc; obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena; obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh; @@ -171,8 +169,6 @@ EXPORT_SYMBOL(dpaa2_io_create); */ void dpaa2_io_down(struct dpaa2_io *d) { - if (!atomic_dec_and_test(&d->refs)) - return; kfree(d); } EXPORT_SYMBOL(dpaa2_io_down); -- cgit v1.2.3 From 9e04d0e20c509d9ac62f06d01675375e19fc435a Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:27 +0200 Subject: staging: fsl-mc/dpio: drop EXPORT_SYMBOL() for a few functions These functions are only used within this driver so no need for EXPORT_SYMBOL(). Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpio/dpio-service.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c index 591d8b7d4f49..fca8c90dc07d 100644 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c @@ -156,7 +156,6 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) return obj; } -EXPORT_SYMBOL(dpaa2_io_create); /** * dpaa2_io_down() - release the dpaa2_io object. @@ -171,7 +170,6 @@ void dpaa2_io_down(struct dpaa2_io *d) { kfree(d); } -EXPORT_SYMBOL(dpaa2_io_down); #define DPAA_POLL_MAX 32 @@ -218,7 +216,6 @@ done: qbman_swp_interrupt_set_inhibit(swp, 0); return IRQ_HANDLED; } -EXPORT_SYMBOL(dpaa2_io_irq); /** * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN -- cgit v1.2.3 From a211c8170b3c348353decb6e175c58a7814f218c Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:28 +0200 Subject: staging: fsl-mc/dpio: remove couple of unused functions These couple of functions are not yet used so lets remove them for now and add them back when/if needed. Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpio/dpio-service.c | 58 -------------------------- drivers/staging/fsl-mc/include/dpaa2-io.h | 4 -- 2 files changed, 62 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c index fca8c90dc07d..871078d0efb0 100644 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c @@ -317,37 +317,6 @@ int dpaa2_io_service_rearm(struct dpaa2_io *d, } EXPORT_SYMBOL(dpaa2_io_service_rearm); -/** - * dpaa2_io_service_pull_fq() - pull dequeue functions from a fq. - * @d: the given DPIO service. - * @fqid: the given frame queue id. - * @s: the dpaa2_io_store object for the result. - * - * Return 0 for success, or error code for failure. - */ -int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid, - struct dpaa2_io_store *s) -{ - struct qbman_pull_desc pd; - int err; - - qbman_pull_desc_clear(&pd); - qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1); - qbman_pull_desc_set_numframes(&pd, (u8)s->max); - qbman_pull_desc_set_fq(&pd, fqid); - - d = service_select(d); - if (!d) - return -ENODEV; - s->swp = d->swp; - err = qbman_swp_pull(d->swp, &pd); - if (err) - s->swp = NULL; - - return err; -} -EXPORT_SYMBOL(dpaa2_io_service_pull_fq); - /** * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel. * @d: the given DPIO service. @@ -380,33 +349,6 @@ int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, } EXPORT_SYMBOL(dpaa2_io_service_pull_channel); -/** - * dpaa2_io_service_enqueue_fq() - Enqueue a frame to a frame queue. - * @d: the given DPIO service. - * @fqid: the given frame queue id. - * @fd: the frame descriptor which is enqueued. - * - * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready, - * or -ENODEV if there is no dpio service. - */ -int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, - u32 fqid, - const struct dpaa2_fd *fd) -{ - struct qbman_eq_desc ed; - - d = service_select(d); - if (!d) - return -ENODEV; - - qbman_eq_desc_clear(&ed); - qbman_eq_desc_set_no_orp(&ed, 0); - qbman_eq_desc_set_fq(&ed, fqid); - - return qbman_swp_enqueue(d->swp, &ed, fd); -} -EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq); - /** * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD. * @d: the given DPIO service. diff --git a/drivers/staging/fsl-mc/include/dpaa2-io.h b/drivers/staging/fsl-mc/include/dpaa2-io.h index afc2d060d077..07ad15ae9b7a 100644 --- a/drivers/staging/fsl-mc/include/dpaa2-io.h +++ b/drivers/staging/fsl-mc/include/dpaa2-io.h @@ -120,13 +120,9 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service, int dpaa2_io_service_rearm(struct dpaa2_io *service, struct dpaa2_io_notification_ctx *ctx); -int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid, - struct dpaa2_io_store *s); int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, struct dpaa2_io_store *s); -int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid, - const struct dpaa2_fd *fd); int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio, u16 qdbin, const struct dpaa2_fd *fd); int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid, -- cgit v1.2.3 From c9d57ea0b6fb0bc09ce351a8ca8187e07fc5a3cc Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:29 +0200 Subject: staging: fsl-mc: consistently use EXPORT_SYMBOL_GPL() The bus driver is mixing EXPORT_SYMBOL()/EXPORT_SYMBOL_GPL() usage. Change it to consistently use EXPORT_SYMBOL_GPL(). Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpbp.c | 16 ++++++++-------- drivers/staging/fsl-mc/bus/dpcon.c | 14 +++++++------- drivers/staging/fsl-mc/bus/dprc.c | 16 ++++++++-------- drivers/staging/fsl-mc/bus/mc-sys.c | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index 363730a80cbb..fc76e900e8c4 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -77,7 +77,7 @@ int dpbp_open(struct fsl_mc_io *mc_io, return err; } -EXPORT_SYMBOL(dpbp_open); +EXPORT_SYMBOL_GPL(dpbp_open); /** * dpbp_close() - Close the control session of the object @@ -103,7 +103,7 @@ int dpbp_close(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpbp_close); +EXPORT_SYMBOL_GPL(dpbp_close); /** * dpbp_enable() - Enable the DPBP. @@ -126,7 +126,7 @@ int dpbp_enable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpbp_enable); +EXPORT_SYMBOL_GPL(dpbp_enable); /** * dpbp_disable() - Disable the DPBP. @@ -149,7 +149,7 @@ int dpbp_disable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpbp_disable); +EXPORT_SYMBOL_GPL(dpbp_disable); /** * dpbp_is_enabled() - Check if the DPBP is enabled. @@ -183,7 +183,7 @@ int dpbp_is_enabled(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpbp_is_enabled); +EXPORT_SYMBOL_GPL(dpbp_is_enabled); /** * dpbp_reset() - Reset the DPBP, returns the object to initial state. @@ -206,7 +206,7 @@ int dpbp_reset(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpbp_reset); +EXPORT_SYMBOL_GPL(dpbp_reset); /** * dpbp_get_attributes - Retrieve DPBP attributes. @@ -243,7 +243,7 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpbp_get_attributes); +EXPORT_SYMBOL_GPL(dpbp_get_attributes); /** * dpbp_get_api_version - Get Data Path Buffer Pool API version @@ -276,4 +276,4 @@ int dpbp_get_api_version(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpbp_get_api_version); +EXPORT_SYMBOL_GPL(dpbp_get_api_version); diff --git a/drivers/staging/fsl-mc/bus/dpcon.c b/drivers/staging/fsl-mc/bus/dpcon.c index ce7c0bfab4ab..5ba1a0f58a41 100644 --- a/drivers/staging/fsl-mc/bus/dpcon.c +++ b/drivers/staging/fsl-mc/bus/dpcon.c @@ -78,7 +78,7 @@ int dpcon_open(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpcon_open); +EXPORT_SYMBOL_GPL(dpcon_open); /** * dpcon_close() - Close the control session of the object @@ -105,7 +105,7 @@ int dpcon_close(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_close); +EXPORT_SYMBOL_GPL(dpcon_close); /** * dpcon_enable() - Enable the DPCON @@ -129,7 +129,7 @@ int dpcon_enable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_enable); +EXPORT_SYMBOL_GPL(dpcon_enable); /** * dpcon_disable() - Disable the DPCON @@ -153,7 +153,7 @@ int dpcon_disable(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_disable); +EXPORT_SYMBOL_GPL(dpcon_disable); /** * dpcon_reset() - Reset the DPCON, returns the object to initial state. @@ -176,7 +176,7 @@ int dpcon_reset(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_reset); +EXPORT_SYMBOL_GPL(dpcon_reset); /** * dpcon_get_attributes() - Retrieve DPCON attributes. @@ -214,7 +214,7 @@ int dpcon_get_attributes(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dpcon_get_attributes); +EXPORT_SYMBOL_GPL(dpcon_get_attributes); /** * dpcon_set_notification() - Set DPCON notification destination @@ -245,4 +245,4 @@ int dpcon_set_notification(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dpcon_set_notification); +EXPORT_SYMBOL_GPL(dpcon_set_notification); diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index 6f6c65a42166..f29ea3e1fd3e 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -71,7 +71,7 @@ int dprc_open(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_open); +EXPORT_SYMBOL_GPL(dprc_open); /** * dprc_close() - Close the control session of the object @@ -97,7 +97,7 @@ int dprc_close(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dprc_close); +EXPORT_SYMBOL_GPL(dprc_close); /** * dprc_get_irq() - Get IRQ information from the DPRC. @@ -475,7 +475,7 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_get_obj_count); +EXPORT_SYMBOL_GPL(dprc_get_obj_count); /** * dprc_get_obj() - Get general information on an object @@ -531,7 +531,7 @@ int dprc_get_obj(struct fsl_mc_io *mc_io, obj_desc->label[15] = '\0'; return 0; } -EXPORT_SYMBOL(dprc_get_obj); +EXPORT_SYMBOL_GPL(dprc_get_obj); /** * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. @@ -572,7 +572,7 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -EXPORT_SYMBOL(dprc_set_obj_irq); +EXPORT_SYMBOL_GPL(dprc_set_obj_irq); /** * dprc_get_obj_irq() - Get IRQ information from object. @@ -626,7 +626,7 @@ int dprc_get_obj_irq(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_get_obj_irq); +EXPORT_SYMBOL_GPL(dprc_get_obj_irq); /** * dprc_get_res_count() - Obtains the number of free resources that are assigned @@ -669,7 +669,7 @@ int dprc_get_res_count(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_get_res_count); +EXPORT_SYMBOL_GPL(dprc_get_res_count); /** * dprc_get_obj_region() - Get region information for a specified object. @@ -717,7 +717,7 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io, return 0; } -EXPORT_SYMBOL(dprc_get_obj_region); +EXPORT_SYMBOL_GPL(dprc_get_obj_region); /** * dprc_get_api_version - Get Data Path Resource Container API version diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 7ce105bd3977..a2854e5f94a0 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -320,4 +320,4 @@ common_exit: return error; } -EXPORT_SYMBOL(mc_send_command); +EXPORT_SYMBOL_GPL(mc_send_command); -- cgit v1.2.3 From 53639c64c686f0d2bdb479b2711df60fa51a7122 Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:30 +0200 Subject: staging: fsl-mc/dpio: change to use EXPORT_SYMBOL_GPL() No need to use EXPORT_SYMBOL() so switch to the GPL variant. Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dpio/dpio-service.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c index 871078d0efb0..a8a8e1578770 100644 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c @@ -258,7 +258,7 @@ int dpaa2_io_service_register(struct dpaa2_io *d, ctx->qman64); return 0; } -EXPORT_SYMBOL(dpaa2_io_service_register); +EXPORT_SYMBOL_GPL(dpaa2_io_service_register); /** * dpaa2_io_service_deregister - The opposite of 'register'. @@ -281,7 +281,7 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service, list_del(&ctx->node); spin_unlock_irqrestore(&d->lock_notifications, irqflags); } -EXPORT_SYMBOL(dpaa2_io_service_deregister); +EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister); /** * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO service. @@ -315,7 +315,7 @@ int dpaa2_io_service_rearm(struct dpaa2_io *d, return err; } -EXPORT_SYMBOL(dpaa2_io_service_rearm); +EXPORT_SYMBOL_GPL(dpaa2_io_service_rearm); /** * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel. @@ -347,7 +347,7 @@ int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, return err; } -EXPORT_SYMBOL(dpaa2_io_service_pull_channel); +EXPORT_SYMBOL_GPL(dpaa2_io_service_pull_channel); /** * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD. @@ -376,7 +376,7 @@ int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, return qbman_swp_enqueue(d->swp, &ed, fd); } -EXPORT_SYMBOL(dpaa2_io_service_enqueue_qd); +EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd); /** * dpaa2_io_service_release() - Release buffers to a buffer pool. @@ -403,7 +403,7 @@ int dpaa2_io_service_release(struct dpaa2_io *d, return qbman_swp_release(d->swp, &rd, buffers, num_buffers); } -EXPORT_SYMBOL(dpaa2_io_service_release); +EXPORT_SYMBOL_GPL(dpaa2_io_service_release); /** * dpaa2_io_service_acquire() - Acquire buffers from a buffer pool. @@ -434,7 +434,7 @@ int dpaa2_io_service_acquire(struct dpaa2_io *d, return err; } -EXPORT_SYMBOL(dpaa2_io_service_acquire); +EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire); /* * 'Stores' are reusable memory blocks for holding dequeue results, and to @@ -488,7 +488,7 @@ struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames, return ret; } -EXPORT_SYMBOL(dpaa2_io_store_create); +EXPORT_SYMBOL_GPL(dpaa2_io_store_create); /** * dpaa2_io_store_destroy() - Frees the dma memory storage for dequeue @@ -502,7 +502,7 @@ void dpaa2_io_store_destroy(struct dpaa2_io_store *s) kfree(s->alloced_addr); kfree(s); } -EXPORT_SYMBOL(dpaa2_io_store_destroy); +EXPORT_SYMBOL_GPL(dpaa2_io_store_destroy); /** * dpaa2_io_store_next() - Determine when the next dequeue result is available. @@ -550,4 +550,4 @@ struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last) return ret; } -EXPORT_SYMBOL(dpaa2_io_store_next); +EXPORT_SYMBOL_GPL(dpaa2_io_store_next); -- cgit v1.2.3 From d8e026a44919edc56e14081e1cf5c34898bca6a4 Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:31 +0200 Subject: staging: fsl-mc: remove some superfluous WARN_ONs These WARN_ONs shouldn't trigger unless something went very wrong. Since the driver is in a stable state let's remove these debug WARN_ONs. Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 8 -------- drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 10 ---------- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 12 ------------ drivers/staging/fsl-mc/bus/fsl-mc-msi.c | 1 - .../staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 3 --- drivers/staging/fsl-mc/bus/mc-io.c | 19 ------------------- 6 files changed, 53 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 06df528f4cfc..d6a84dd42ada 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -39,8 +39,6 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) struct fsl_mc_child_objs *objs; struct fsl_mc_device *mc_dev; - WARN_ON(!dev); - WARN_ON(!data); mc_dev = to_fsl_mc_device(dev); objs = data; @@ -60,8 +58,6 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) static int __fsl_mc_device_remove(struct device *dev, void *data) { - WARN_ON(!dev); - WARN_ON(data); fsl_mc_device_remove(to_fsl_mc_device(dev)); return 0; } @@ -453,8 +449,6 @@ static int disable_dprc_irq(struct fsl_mc_device *mc_dev) int error; struct fsl_mc_io *mc_io = mc_dev->mc_io; - WARN_ON(mc_dev->obj_desc.irq_count != 1); - /* * Disable generation of interrupt, while we configure it: */ @@ -496,8 +490,6 @@ static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) int error; struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; - WARN_ON(mc_dev->obj_desc.irq_count != 1); - /* * NOTE: devm_request_threaded_irq() invokes the device-specific * function that programs the MSI physically in the device diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 8ea3920400a0..d472a85a6f8d 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -199,7 +199,6 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, struct fsl_mc_resource, node); if (!resource) { - WARN_ON(res_pool->free_count != 0); error = -ENXIO; dev_err(&mc_bus_dev->dev, "No more resources of type %s left\n", @@ -474,7 +473,6 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) irqs[i] = to_fsl_mc_irq(resource); res_allocated_count++; - WARN_ON(irqs[i]->mc_dev); irqs[i]->mc_dev = mc_dev; irqs[i]->dev_irq_index = i; } @@ -516,7 +514,6 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) return; for (i = 0; i < irq_count; i++) { - WARN_ON(!irqs[i]->mc_dev); irqs[i]->mc_dev = NULL; fsl_mc_resource_free(&irqs[i]->resource); } @@ -553,17 +550,10 @@ static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, &mc_bus->resource_pools[pool_type]; int free_count = 0; - WARN_ON(res_pool->type != pool_type); - WARN_ON(res_pool->free_count != res_pool->max_count); - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { free_count++; - WARN_ON(resource->type != res_pool->type); - WARN_ON(resource->parent_pool != res_pool); devm_kfree(&mc_bus_dev->dev, resource); } - - WARN_ON(free_count != res_pool->free_count); } void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 409f2b9e70ff..1c2fd8d98f16 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -162,12 +162,7 @@ static int fsl_mc_driver_probe(struct device *dev) struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); int error; - if (WARN_ON(!dev->driver)) - return -EINVAL; - mc_drv = to_fsl_mc_driver(dev->driver); - if (WARN_ON(!mc_drv->probe)) - return -EINVAL; error = mc_drv->probe(mc_dev); if (error < 0) { @@ -184,9 +179,6 @@ static int fsl_mc_driver_remove(struct device *dev) struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); int error; - if (WARN_ON(!dev->driver)) - return -EINVAL; - error = mc_drv->remove(mc_dev); if (error < 0) { dev_err(dev, "%s failed: %d\n", __func__, error); @@ -352,8 +344,6 @@ static int translate_mc_addr(struct fsl_mc_device *mc_dev, struct fsl_mc *mc; fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); - if (WARN_ON(!root_dprc_dev)) - return -EINVAL; mc = dev_get_drvdata(root_dprc_dev->parent); if (mc->num_translation_ranges == 0) { @@ -401,7 +391,6 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, * type, as this object type is not supposed to have MMIO * regions */ - WARN_ON(true); return -EINVAL; } @@ -424,7 +413,6 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, goto error_cleanup_regions; } - WARN_ON(region_desc.size == 0); error = translate_mc_addr(mc_dev, mc_region_type, region_desc.base_offset, ®ions[i].start); diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c index f74a6f1764bb..0ce6117ff74f 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -124,7 +124,6 @@ static void fsl_mc_msi_write_msg(struct irq_data *irq_data, struct fsl_mc_device_irq *mc_dev_irq = &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; - WARN_ON(mc_dev_irq->msi_desc != msi_desc); msi_desc->msg = *msg; /* diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index 123e4af58408..947378f988f8 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -93,9 +93,6 @@ int __init its_fsl_mc_msi_init(void) continue; } - WARN_ON(mc_msi_domain->host_data != - &its_fsl_mc_msi_domain_info); - pr_info("fsl-mc MSI: %pOF domain created\n", np); } diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c index f65c23ce83f1..5530856b0106 100644 --- a/drivers/staging/fsl-mc/bus/mc-io.c +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -68,12 +68,6 @@ static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) int error; struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return; - - if (WARN_ON(dpmcp_dev->mc_io != mc_io)) - return; - error = dpmcp_close(mc_io, 0, dpmcp_dev->mc_handle); @@ -224,8 +218,6 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, error = -EINVAL; dpmcp_dev = resource->data; - if (WARN_ON(!dpmcp_dev)) - goto error_cleanup_resource; if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && @@ -238,15 +230,9 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, goto error_cleanup_resource; } - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) - goto error_cleanup_resource; - mc_portal_phys_addr = dpmcp_dev->regions[0].start; mc_portal_size = resource_size(dpmcp_dev->regions); - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) - goto error_cleanup_resource; - error = fsl_create_mc_io(&mc_bus_dev->dev, mc_portal_phys_addr, mc_portal_size, dpmcp_dev, @@ -279,8 +265,6 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io) * to have a DPMCP object associated with. */ dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return; resource = dpmcp_dev->resource; if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) @@ -304,9 +288,6 @@ int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) int error; struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return -EINVAL; - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); if (error < 0) { dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); -- cgit v1.2.3 From a385dd7b37174aa7956ea092dd9204b395e3f204 Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:32 +0200 Subject: staging: fsl-mc: remove debug WARN_ONs doubling error checks A lot of error checks are doubled by debug WARN_ONs. Given that the driver was thoroughly debugged and is in a stable state, it's time to drop them. Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 20 ++--- drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 86 +++++++++++----------- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 8 +- drivers/staging/fsl-mc/bus/fsl-mc-msi.c | 14 ++-- .../staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 4 +- drivers/staging/fsl-mc/bus/mc-io.c | 13 ++-- drivers/staging/fsl-mc/bus/mc-sys.c | 5 +- 7 files changed, 73 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index d6a84dd42ada..28a6b87f00b3 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -382,11 +382,11 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", irq_num, smp_processor_id()); - if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC))) + if (!(mc_dev->flags & FSL_MC_IS_DPRC)) return IRQ_HANDLED; mutex_lock(&mc_bus->scan_mutex); - if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) + if (!msi_desc || msi_desc->irq != (u32)irq_num) goto out; status = 0; @@ -593,20 +593,20 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) bool msi_domain_set = false; u16 major_ver, minor_ver; - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) + if (strcmp(mc_dev->obj_desc.type, "dprc") != 0) return -EINVAL; - if (WARN_ON(dev_get_msi_domain(&mc_dev->dev))) + if (dev_get_msi_domain(&mc_dev->dev)) return -EINVAL; if (!mc_dev->mc_io) { /* * This is a child DPRC: */ - if (WARN_ON(!dev_is_fsl_mc(parent_dev))) + if (!dev_is_fsl_mc(parent_dev)) return -EINVAL; - if (WARN_ON(mc_dev->obj_desc.region_count == 0)) + if (mc_dev->obj_desc.region_count == 0) return -EINVAL; region_size = resource_size(mc_dev->regions); @@ -634,7 +634,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) */ struct irq_domain *mc_msi_domain; - if (WARN_ON(dev_is_fsl_mc(parent_dev))) + if (dev_is_fsl_mc(parent_dev)) return -EINVAL; error = fsl_mc_find_msi_domain(parent_dev, @@ -745,12 +745,12 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) int error; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) + if (strcmp(mc_dev->obj_desc.type, "dprc") != 0) return -EINVAL; - if (WARN_ON(!mc_dev->mc_io)) + if (!mc_dev->mc_io) return -EINVAL; - if (WARN_ON(!mc_bus->irq_resources)) + if (!mc_bus->irq_resources) return -EINVAL; if (dev_get_msi_domain(&mc_dev->dev)) diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index d472a85a6f8d..f7fbebdba7ce 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -41,25 +41,25 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; int error = -EINVAL; - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) goto out; - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) + if (!fsl_mc_is_allocatable(mc_dev->obj_desc.type)) goto out; - if (WARN_ON(mc_dev->resource)) + if (mc_dev->resource) goto out; res_pool = &mc_bus->resource_pools[pool_type]; - if (WARN_ON(res_pool->type != pool_type)) + if (res_pool->type != pool_type) goto out; - if (WARN_ON(res_pool->mc_bus != mc_bus)) + if (res_pool->mc_bus != mc_bus) goto out; mutex_lock(&res_pool->mutex); - if (WARN_ON(res_pool->max_count < 0)) + if (res_pool->max_count < 0) goto out_unlock; - if (WARN_ON(res_pool->free_count < 0 || - res_pool->free_count > res_pool->max_count)) + if (res_pool->free_count < 0 || + res_pool->free_count > res_pool->max_count) goto out_unlock; resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), @@ -105,25 +105,25 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device struct fsl_mc_resource *resource; int error = -EINVAL; - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) + if (!fsl_mc_is_allocatable(mc_dev->obj_desc.type)) goto out; resource = mc_dev->resource; - if (WARN_ON(!resource || resource->data != mc_dev)) + if (!resource || resource->data != mc_dev) goto out; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); mc_bus = to_fsl_mc_bus(mc_bus_dev); res_pool = resource->parent_pool; - if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type])) + if (res_pool != &mc_bus->resource_pools[resource->type]) goto out; mutex_lock(&res_pool->mutex); - if (WARN_ON(res_pool->max_count <= 0)) + if (res_pool->max_count <= 0) goto out_unlock; - if (WARN_ON(res_pool->free_count <= 0 || - res_pool->free_count > res_pool->max_count)) + if (res_pool->free_count <= 0 || + res_pool->free_count > res_pool->max_count) goto out_unlock; /* @@ -187,11 +187,11 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, FSL_MC_NUM_POOL_TYPES); *new_resource = NULL; - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) goto out; res_pool = &mc_bus->resource_pools[pool_type]; - if (WARN_ON(res_pool->mc_bus != mc_bus)) + if (res_pool->mc_bus != mc_bus) goto out; mutex_lock(&res_pool->mutex); @@ -206,12 +206,12 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, goto out_unlock; } - if (WARN_ON(resource->type != pool_type)) + if (resource->type != pool_type) goto out_unlock; - if (WARN_ON(resource->parent_pool != res_pool)) + if (resource->parent_pool != res_pool) goto out_unlock; - if (WARN_ON(res_pool->free_count <= 0 || - res_pool->free_count > res_pool->max_count)) + if (res_pool->free_count <= 0 || + res_pool->free_count > res_pool->max_count) goto out_unlock; list_del_init(&resource->node); @@ -231,15 +231,15 @@ void fsl_mc_resource_free(struct fsl_mc_resource *resource) struct fsl_mc_resource_pool *res_pool; res_pool = resource->parent_pool; - if (WARN_ON(resource->type != res_pool->type)) + if (resource->type != res_pool->type) return; mutex_lock(&res_pool->mutex); - if (WARN_ON(res_pool->free_count < 0 || - res_pool->free_count >= res_pool->max_count)) + if (res_pool->free_count < 0 || + res_pool->free_count >= res_pool->max_count) goto out_unlock; - if (WARN_ON(!list_empty(&resource->node))) + if (!list_empty(&resource->node)) goto out_unlock; list_add_tail(&resource->node, &res_pool->free_list); @@ -278,13 +278,13 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, struct fsl_mc_resource *resource = NULL; *new_mc_adev = NULL; - if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) + if (mc_dev->flags & FSL_MC_IS_DPRC) goto error; - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) + if (!dev_is_fsl_mc(mc_dev->dev.parent)) goto error; - if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) + if (pool_type == FSL_MC_POOL_DPMCP) goto error; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); @@ -294,7 +294,7 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, goto error; mc_adev = resource->data; - if (WARN_ON(!mc_adev)) + if (!mc_adev) goto error; *new_mc_adev = mc_adev; @@ -317,9 +317,9 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev) struct fsl_mc_resource *resource; resource = mc_adev->resource; - if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP)) + if (resource->type == FSL_MC_POOL_DPMCP) return; - if (WARN_ON(resource->data != mc_adev)) + if (resource->data != mc_adev) return; fsl_mc_resource_free(resource); @@ -348,8 +348,8 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, struct fsl_mc_resource_pool *res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; - if (WARN_ON(irq_count == 0 || - irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) + if (irq_count == 0 || + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) return -EINVAL; error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); @@ -405,13 +405,13 @@ void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) struct fsl_mc_resource_pool *res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; - if (WARN_ON(!mc_bus->irq_resources)) + if (!mc_bus->irq_resources) return; - if (WARN_ON(res_pool->max_count == 0)) + if (res_pool->max_count == 0) return; - if (WARN_ON(res_pool->free_count != res_pool->max_count)) + if (res_pool->free_count != res_pool->max_count) return; INIT_LIST_HEAD(&res_pool->free_list); @@ -435,11 +435,11 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) struct fsl_mc_bus *mc_bus; struct fsl_mc_resource_pool *res_pool; - if (WARN_ON(mc_dev->irqs)) + if (mc_dev->irqs) return -EINVAL; irq_count = mc_dev->obj_desc.irq_count; - if (WARN_ON(irq_count == 0)) + if (irq_count == 0) return -EINVAL; if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) @@ -447,7 +447,7 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) else mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); - if (WARN_ON(!mc_bus->irq_resources)) + if (!mc_bus->irq_resources) return -EINVAL; res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; @@ -500,7 +500,7 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) struct fsl_mc_bus *mc_bus; struct fsl_mc_device_irq **irqs = mc_dev->irqs; - if (WARN_ON(!irqs)) + if (!irqs) return; irq_count = mc_dev->obj_desc.irq_count; @@ -510,7 +510,7 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) else mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); - if (WARN_ON(!mc_bus->irq_resources)) + if (!mc_bus->irq_resources) return; for (i = 0; i < irq_count; i++) { @@ -575,11 +575,11 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) struct fsl_mc_bus *mc_bus; int error; - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) + if (!fsl_mc_is_allocatable(mc_dev->obj_desc.type)) return -EINVAL; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) + if (!dev_is_fsl_mc(&mc_bus_dev->dev)) return -EINVAL; mc_bus = to_fsl_mc_bus(mc_bus_dev); @@ -604,7 +604,7 @@ static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) { int error; - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type))) + if (!fsl_mc_is_allocatable(mc_dev->obj_desc.type)) return -EINVAL; if (mc_dev->resource) { diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 1c2fd8d98f16..854bd80dc740 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -284,9 +284,9 @@ static int mc_get_version(struct fsl_mc_io *mc_io, static void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev) { - if (WARN_ON(!dev)) { + if (!dev) { *root_dprc_dev = NULL; - } else if (WARN_ON(!dev_is_fsl_mc(dev))) { + } else if (!dev_is_fsl_mc(dev)) { *root_dprc_dev = NULL; } else { *root_dprc_dev = dev; @@ -532,7 +532,7 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, /* * device being added is the root DPRC device */ - if (WARN_ON(!mc_io)) { + if (!mc_io) { error = -EINVAL; goto error_cleanup_dev; } @@ -814,7 +814,7 @@ static int fsl_mc_bus_remove(struct platform_device *pdev) { struct fsl_mc *mc = platform_get_drvdata(pdev); - if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))) + if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)) return -EINVAL; fsl_mc_device_remove(mc->root_mc_bus_dev); diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c index 0ce6117ff74f..625ba077f177 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -47,7 +47,7 @@ static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) { struct msi_domain_ops *ops = info->ops; - if (WARN_ON(!ops)) + if (!ops) return; /* @@ -73,7 +73,7 @@ static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) return; - if (WARN_ON(!owner_mc_dev)) + if (!owner_mc_dev) return; irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | @@ -136,7 +136,7 @@ static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) { struct irq_chip *chip = info->chip; - if (WARN_ON(!chip)) + if (!chip) return; /* @@ -238,7 +238,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, struct irq_domain *msi_domain; int error; - if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) + if (!list_empty(dev_to_msi_list(dev))) return -EINVAL; error = fsl_mc_msi_alloc_descs(dev, irq_count); @@ -246,7 +246,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, return error; msi_domain = dev_get_msi_domain(dev); - if (WARN_ON(!msi_domain)) { + if (!msi_domain) { error = -EINVAL; goto cleanup_msi_descs; } @@ -274,12 +274,12 @@ void fsl_mc_msi_domain_free_irqs(struct device *dev) struct irq_domain *msi_domain; msi_domain = dev_get_msi_domain(dev); - if (WARN_ON(!msi_domain)) + if (!msi_domain) return; msi_domain_free_irqs(msi_domain, dev); - if (WARN_ON(list_empty(dev_to_msi_list(dev)))) + if (list_empty(dev_to_msi_list(dev))) return; fsl_mc_msi_free_descs(dev); diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index 947378f988f8..6d81ac022ef1 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -32,11 +32,11 @@ static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, struct fsl_mc_device *mc_bus_dev; struct msi_domain_info *msi_info; - if (WARN_ON(!dev_is_fsl_mc(dev))) + if (!dev_is_fsl_mc(dev)) return -EINVAL; mc_bus_dev = to_fsl_mc_device(dev); - if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC))) + if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC)) return -EINVAL; /* diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c index 5530856b0106..3cbf92d0862e 100644 --- a/drivers/staging/fsl-mc/bus/mc-io.c +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -42,13 +42,10 @@ static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, { int error; - if (WARN_ON(!dpmcp_dev)) + if (mc_io->dpmcp_dev) return -EINVAL; - if (WARN_ON(mc_io->dpmcp_dev)) - return -EINVAL; - - if (WARN_ON(dpmcp_dev->mc_io)) + if (dpmcp_dev->mc_io) return -EINVAL; error = dpmcp_open(mc_io, @@ -204,7 +201,7 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, if (mc_dev->flags & FSL_MC_IS_DPRC) { mc_bus_dev = mc_dev; } else { - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) + if (!dev_is_fsl_mc(mc_dev->dev.parent)) return error; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); @@ -267,10 +264,10 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io) dpmcp_dev = mc_io->dpmcp_dev; resource = dpmcp_dev->resource; - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) + if (!resource || resource->type != FSL_MC_POOL_DPMCP) return; - if (WARN_ON(resource->data != dpmcp_dev)) + if (resource->data != dpmcp_dev) return; fsl_destroy_mc_io(mc_io); diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index a2854e5f94a0..db3636da7bcb 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -85,7 +85,7 @@ static int mc_status_to_error(enum mc_cmd_status status) [MC_CMD_STATUS_INVALID_STATE] = -ENODEV, }; - if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map))) + if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map)) return -EINVAL; return mc_status_to_error_map[status]; @@ -273,8 +273,7 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) enum mc_cmd_status status; unsigned long irq_flags = 0; - if (WARN_ON(in_irq() && - !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))) + if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)) return -EINVAL; if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) -- cgit v1.2.3 From 47433b630b7b30d0daa360c64308c0f4c9632986 Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:33 +0200 Subject: staging: fsl-mc: add support for device type The MC bus has different types of devices and this is supported by device model. This patch adds initial support for device types (defines them, adds helpers and sets the device type). Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 67 +++++++++++++++++++++++++++++++++ drivers/staging/fsl-mc/include/mc.h | 55 +++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 854bd80dc740..aa935f3fda75 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -156,6 +156,68 @@ struct bus_type fsl_mc_bus_type = { }; EXPORT_SYMBOL_GPL(fsl_mc_bus_type); +struct device_type fsl_mc_bus_dprc_type = { + .name = "fsl_mc_bus_dprc" +}; + +struct device_type fsl_mc_bus_dpni_type = { + .name = "fsl_mc_bus_dpni" +}; + +struct device_type fsl_mc_bus_dpio_type = { + .name = "fsl_mc_bus_dpio" +}; + +struct device_type fsl_mc_bus_dpsw_type = { + .name = "fsl_mc_bus_dpsw" +}; + +struct device_type fsl_mc_bus_dpbp_type = { + .name = "fsl_mc_bus_dpbp" +}; + +struct device_type fsl_mc_bus_dpcon_type = { + .name = "fsl_mc_bus_dpcon" +}; + +struct device_type fsl_mc_bus_dpmcp_type = { + .name = "fsl_mc_bus_dpmcp" +}; + +struct device_type fsl_mc_bus_dpmac_type = { + .name = "fsl_mc_bus_dpmac" +}; + +struct device_type fsl_mc_bus_dprtc_type = { + .name = "fsl_mc_bus_dprtc" +}; + +static struct device_type *fsl_mc_get_device_type(const char *type) +{ + static const struct { + struct device_type *dev_type; + const char *type; + } dev_types[] = { + { &fsl_mc_bus_dprc_type, "dprc" }, + { &fsl_mc_bus_dpni_type, "dpni" }, + { &fsl_mc_bus_dpio_type, "dpio" }, + { &fsl_mc_bus_dpsw_type, "dpsw" }, + { &fsl_mc_bus_dpbp_type, "dpbp" }, + { &fsl_mc_bus_dpcon_type, "dpcon" }, + { &fsl_mc_bus_dpmcp_type, "dpmcp" }, + { &fsl_mc_bus_dpmac_type, "dpmac" }, + { &fsl_mc_bus_dprtc_type, "dprtc" }, + { NULL, NULL } + }; + int i; + + for (i = 0; dev_types[i].dev_type; i++) + if (!strcmp(dev_types[i].type, type)) + return dev_types[i].dev_type; + + return NULL; +} + static int fsl_mc_driver_probe(struct device *dev) { struct fsl_mc_driver *mc_drv; @@ -506,6 +568,11 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, mc_dev->dev.parent = parent_dev; mc_dev->dev.bus = &fsl_mc_bus_type; mc_dev->dev.release = fsl_mc_device_release; + mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type); + if (!mc_dev->dev.type) { + dev_err(parent_dev, "unknown device type %s\n", obj_desc->type); + goto error_cleanup_dev; + } dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); if (strcmp(obj_desc->type, "dprc") == 0) { diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index aafe63a21f49..15db93d71f82 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -398,4 +398,59 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); extern struct bus_type fsl_mc_bus_type; +extern struct device_type fsl_mc_bus_dprc_type; +extern struct device_type fsl_mc_bus_dpni_type; +extern struct device_type fsl_mc_bus_dpio_type; +extern struct device_type fsl_mc_bus_dpsw_type; +extern struct device_type fsl_mc_bus_dpbp_type; +extern struct device_type fsl_mc_bus_dpcon_type; +extern struct device_type fsl_mc_bus_dpmcp_type; +extern struct device_type fsl_mc_bus_dpmac_type; +extern struct device_type fsl_mc_bus_dprtc_type; + +static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dprc_type; +} + +static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpni_type; +} + +static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpio_type; +} + +static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpsw_type; +} + +static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpbp_type; +} + +static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpcon_type; +} + +static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type; +} + +static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dpmac_type; +} + +static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev) +{ + return mc_dev->dev.type == &fsl_mc_bus_dprtc_type; +} + #endif /* _FSL_MC_H_ */ -- cgit v1.2.3 From 19e2be77f36cfd5930569cad2d197f31a576cf88 Mon Sep 17 00:00:00 2001 From: Laurentiu Tudor Date: Fri, 17 Nov 2017 15:38:34 +0200 Subject: staging: fsl-mc: use device_type instead of strcmp() Replace strcmp() based device type checks with the standard device model type. Signed-off-by: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 4 ++-- drivers/staging/fsl-mc/bus/fsl-mc-allocator.c | 20 ++++++++++---------- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 28a6b87f00b3..131c71545a25 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -593,7 +593,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) bool msi_domain_set = false; u16 major_ver, minor_ver; - if (strcmp(mc_dev->obj_desc.type, "dprc") != 0) + if (!is_fsl_mc_bus_dprc(mc_dev)) return -EINVAL; if (dev_get_msi_domain(&mc_dev->dev)) @@ -745,7 +745,7 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) int error; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); - if (strcmp(mc_dev->obj_desc.type, "dprc") != 0) + if (!is_fsl_mc_bus_dprc(mc_dev)) return -EINVAL; if (!mc_dev->mc_io) return -EINVAL; diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index f7fbebdba7ce..1000fb3fbff0 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -14,11 +14,11 @@ #include "fsl-mc-private.h" -static bool __must_check fsl_mc_is_allocatable(const char *obj_type) +static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev) { - return strcmp(obj_type, "dpbp") == 0 || - strcmp(obj_type, "dpmcp") == 0 || - strcmp(obj_type, "dpcon") == 0; + return is_fsl_mc_bus_dpbp(mc_dev) || + is_fsl_mc_bus_dpmcp(mc_dev) || + is_fsl_mc_bus_dpcon(mc_dev); } /** @@ -43,7 +43,7 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES) goto out; - if (!fsl_mc_is_allocatable(mc_dev->obj_desc.type)) + if (!fsl_mc_is_allocatable(mc_dev)) goto out; if (mc_dev->resource) goto out; @@ -105,7 +105,7 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device struct fsl_mc_resource *resource; int error = -EINVAL; - if (!fsl_mc_is_allocatable(mc_dev->obj_desc.type)) + if (!fsl_mc_is_allocatable(mc_dev)) goto out; resource = mc_dev->resource; @@ -442,7 +442,7 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) if (irq_count == 0) return -EINVAL; - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + if (is_fsl_mc_bus_dprc(mc_dev)) mc_bus = to_fsl_mc_bus(mc_dev); else mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); @@ -505,7 +505,7 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) irq_count = mc_dev->obj_desc.irq_count; - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + if (is_fsl_mc_bus_dprc(mc_dev)) mc_bus = to_fsl_mc_bus(mc_dev); else mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); @@ -575,7 +575,7 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) struct fsl_mc_bus *mc_bus; int error; - if (!fsl_mc_is_allocatable(mc_dev->obj_desc.type)) + if (!fsl_mc_is_allocatable(mc_dev)) return -EINVAL; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); @@ -604,7 +604,7 @@ static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) { int error; - if (!fsl_mc_is_allocatable(mc_dev->obj_desc.type)) + if (!fsl_mc_is_allocatable(mc_dev)) return -EINVAL; if (mc_dev->resource) { diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index aa935f3fda75..f84bc14ce925 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -442,10 +442,10 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, struct device *parent_dev = mc_dev->dev.parent; enum dprc_region_type mc_region_type; - if (strcmp(obj_desc->type, "dprc") == 0 || - strcmp(obj_desc->type, "dpmcp") == 0) { + if (is_fsl_mc_bus_dprc(mc_dev) || + is_fsl_mc_bus_dpmcp(mc_dev)) { mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; - } else if (strcmp(obj_desc->type, "dpio") == 0) { + } else if (is_fsl_mc_bus_dpio(mc_dev)) { mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; } else { /* @@ -520,7 +520,7 @@ static void fsl_mc_device_release(struct device *dev) kfree(mc_dev->regions); - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + if (is_fsl_mc_bus_dprc(mc_dev)) kfree(to_fsl_mc_bus(mc_dev)); else kfree(mc_dev); -- cgit v1.2.3 From fb17be96eed821f60670adf1748afb3d57fe63bb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Nov 2017 09:25:51 +0100 Subject: staging: fsl-mc-bus: fix build warning error could be unitialized when it is used as a return value in fsl_mc_device_add(). So fix up the warning by properly setting it. Cc: Laurentiu Tudor Reported-by: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/fsl-mc-bus.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index f84bc14ce925..f15bab32fb2f 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -570,6 +570,7 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, mc_dev->dev.release = fsl_mc_device_release; mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type); if (!mc_dev->dev.type) { + error = -ENODEV; dev_err(parent_dev, "unknown device type %s\n", obj_desc->type); goto error_cleanup_dev; } -- cgit v1.2.3 From 90f0d2b344313a8a4c366ef60d0df33008d2be84 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 30 Oct 2017 18:29:58 +0100 Subject: soc: renesas: Identify R-Car M3-W ES1.1 The Product Register of R-Car M3-W ES1.1 incorrectly identifies the SoC revision as ES2.0. Add a workaround to fix this. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- drivers/soc/renesas/renesas-soc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 9f4ee2567c72..926b7fd6db2d 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -250,6 +250,9 @@ static int __init renesas_soc_init(void) if (chipid) { product = readl(chipid); iounmap(chipid); + /* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */ + if ((product & 0x7fff) == 0x5210) + product ^= 0x11; if (soc->id && ((product >> 8) & 0xff) != soc->id) { pr_warn("SoC mismatch (product = 0x%x)\n", product); return -ENODEV; -- cgit v1.2.3 From 544e92581a2ac44607d7cc602c6b54d18656f56d Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 13 Nov 2017 16:12:06 +0000 Subject: EDAC, octeon: Fix an uninitialized variable warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix an uninitialized variable warning in the Octeon EDAC driver, as seen in MIPS cavium_octeon_defconfig builds since v4.14 with Codescape GNU Tools 2016.05-03: drivers/edac/octeon_edac-lmc.c In function ‘octeon_lmc_edac_poll_o2’: drivers/edac/octeon_edac-lmc.c:87:24: warning: ‘((long unsigned int*)&int_reg)[1]’ may \ be used uninitialized in this function [-Wmaybe-uninitialized] if (int_reg.s.sec_err || int_reg.s.ded_err) { ^ Iinitialise the whole int_reg variable to zero before the conditional assignments in the error injection case. Signed-off-by: James Hogan Acked-by: David Daney Cc: linux-edac Cc: linux-mips@linux-mips.org Cc: # 3.15+ Fixes: 1bc021e81565 ("EDAC: Octeon: Add error injection support") Link: http://lkml.kernel.org/r/20171113161206.20990-1-james.hogan@mips.com Signed-off-by: Borislav Petkov --- drivers/edac/octeon_edac-lmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c index 9c1ffe3e912b..aeb222ca3ed1 100644 --- a/drivers/edac/octeon_edac-lmc.c +++ b/drivers/edac/octeon_edac-lmc.c @@ -78,6 +78,7 @@ static void octeon_lmc_edac_poll_o2(struct mem_ctl_info *mci) if (!pvt->inject) int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx)); else { + int_reg.u64 = 0; if (pvt->error_type == 1) int_reg.s.sec_err = 1; if (pvt->error_type == 2) -- cgit v1.2.3 From 700b256be9e8f1079638d630a3b2a60590963023 Mon Sep 17 00:00:00 2001 From: Chang Liu Date: Thu, 16 Nov 2017 10:35:07 +0800 Subject: platform/x86: alienware-wmi: lightbar LED support for Dell Inspiron 5675 Inspiron 5675 lightbar compatible with WMI interface on alienware, the difference lies in the zone number and color control. Add Inspiron 5675 DMI quirks to detect by dmi_check_system(). Signed-off-by: Chang Liu Acked-by: Mario Limonciello [andy: massaged commit message] Signed-off-by: Andy Shevchenko --- drivers/platform/x86/alienware-wmi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 4eb8e1a472b2..9d7dbd925065 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -68,6 +68,14 @@ struct quirk_entry { static struct quirk_entry *quirks; + +static struct quirk_entry quirk_inspiron5675 = { + .num_zones = 2, + .hdmi_mux = 0, + .amplifier = 0, + .deepslp = 0, +}; + static struct quirk_entry quirk_unknown = { .num_zones = 2, .hdmi_mux = 0, @@ -171,6 +179,15 @@ static const struct dmi_system_id alienware_quirks[] __initconst = { }, .driver_data = &quirk_asm201, }, + { + .callback = dmi_matched, + .ident = "Dell Inc. Inspiron 5675", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5675"), + }, + .driver_data = &quirk_inspiron5675, + }, {} }; -- cgit v1.2.3 From db2582afa7444a0ce6bb1ebf1431715969a10b06 Mon Sep 17 00:00:00 2001 From: Kiernan Hager Date: Mon, 20 Nov 2017 14:18:44 -0700 Subject: platform/x86: asus-nb-wmi: Support ALS on the Zenbook UX430UQ This patch adds support for ALS on the Zenbook UX430UQ to the asus_nb_wmi driver. It also renames "quirk_asus_ux330uak" to "quirk_asus_forceals" because it is now used for more than one model of computer, and should thus have a more general name. Signed-off-by: Kiernan Hager [andy: massaged commit message, fixed indentation and commas in the code] Signed-off-by: Andy Shevchenko --- drivers/platform/x86/asus-nb-wmi.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 5269a01d9bdd..136ff2b4cce5 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -111,7 +111,7 @@ static struct quirk_entry quirk_asus_x550lb = { .xusb2pr = 0x01D9, }; -static struct quirk_entry quirk_asus_ux330uak = { +static struct quirk_entry quirk_asus_forceals = { .wmi_force_als_set = true, }; @@ -387,7 +387,7 @@ static const struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "UX330UAK"), }, - .driver_data = &quirk_asus_ux330uak, + .driver_data = &quirk_asus_forceals, }, { .callback = dmi_matched, @@ -398,6 +398,15 @@ static const struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_x550lb, }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. UX430UQ", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "UX430UQ"), + }, + .driver_data = &quirk_asus_forceals, + }, {}, }; -- cgit v1.2.3 From 75971febd9b14a517c14e83fccf6a961b4c759f1 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Tue, 21 Nov 2017 13:30:44 +0800 Subject: platform/x86: Add Acer Wireless Radio Control driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New Acer laptops in 2018 will have a separate ACPI device for notifications from the airplane mode hotkey. The device name in the DSDT is SMKB and its ACPI _HID is 10251229. For these models, when the airplane mode hotkey (Fn+F3) pressed, a query 0x02 is started in the Embedded Controller, and all this query does is a notify SMKB with the value 0x80. Scope (_SB.PCI0.LPCB.EC0) { (...) Method (_Q02, 0, NotSerialized) // _Qxx: EC Query { HKEV (0x2, One) Notify (SMKB, 0x80) // Status Change } } Based on code from asus-wireless Signed-off-by: Chris Chiu Reviewed-by: João Paulo Rechi Vita Signed-off-by: Andy Shevchenko --- drivers/platform/x86/Kconfig | 14 +++++++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/acer-wireless.c | 71 ++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 drivers/platform/x86/acer-wireless.c (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 2c745e8ccad6..9d2a6d642f33 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -36,6 +36,20 @@ config ACER_WMI If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M here. +config ACER_WIRELESS + tristate "Acer Wireless Radio Control Driver" + depends on ACPI + depends on INPUT + ---help--- + The Acer Wireless Radio Control handles the airplane mode hotkey + present on new Acer laptops. + + Say Y or M here if you have an Acer notebook with an airplane mode + hotkey. + + If you choose to compile this driver as a module the module will be + called acer-wireless. + config ACERHDF tristate "Acer Aspire One temperature and fan driver" depends on ACPI && THERMAL diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index c32b34a72467..2996536bf54e 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o obj-$(CONFIG_ACER_WMI) += acer-wmi.o +obj-$(CONFIG_ACER_WIRELESS) += acer-wireless.o obj-$(CONFIG_ACERHDF) += acerhdf.o obj-$(CONFIG_HP_ACCEL) += hp_accel.o obj-$(CONFIG_HP_WIRELESS) += hp-wireless.o diff --git a/drivers/platform/x86/acer-wireless.c b/drivers/platform/x86/acer-wireless.c new file mode 100644 index 000000000000..858037987b33 --- /dev/null +++ b/drivers/platform/x86/acer-wireless.c @@ -0,0 +1,71 @@ +/* + * Acer Wireless Radio Control Driver + * + * Copyright (C) 2017 Endless Mobile, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +static const struct acpi_device_id acer_wireless_acpi_ids[] = { + {"10251229", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, acer_wireless_acpi_ids); + +static void acer_wireless_notify(struct acpi_device *adev, u32 event) +{ + struct input_dev *idev = acpi_driver_data(adev); + + dev_dbg(&adev->dev, "event=%#x\n", event); + if (event != 0x80) { + dev_notice(&adev->dev, "Unknown SMKB event: %#x\n", event); + return; + } + input_report_key(idev, KEY_RFKILL, 1); + input_report_key(idev, KEY_RFKILL, 0); + input_sync(idev); +} + +static int acer_wireless_add(struct acpi_device *adev) +{ + struct input_dev *idev; + + idev = devm_input_allocate_device(&adev->dev); + if (!idev) + return -ENOMEM; + + adev->driver_data = idev; + idev->name = "Acer Wireless Radio Control"; + idev->phys = "acer-wireless/input0"; + idev->id.bustype = BUS_HOST; + idev->id.vendor = PCI_VENDOR_ID_AI; + idev->id.product = 0x1229; + set_bit(EV_KEY, idev->evbit); + set_bit(KEY_RFKILL, idev->keybit); + + return input_register_device(idev); +} + +static struct acpi_driver acer_wireless_driver = { + .name = "Acer Wireless Radio Control Driver", + .class = "hotkey", + .ids = acer_wireless_acpi_ids, + .ops = { + .add = acer_wireless_add, + .notify = acer_wireless_notify, + }, +}; +module_acpi_driver(acer_wireless_driver); + +MODULE_DESCRIPTION("Acer Wireless Radio Control Driver"); +MODULE_AUTHOR("Chris Chiu "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 19a525d80836ff969b34bdf8a502c05c5eaf5f75 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Nov 2017 20:24:02 +0100 Subject: platform/x86: Add support for Dollar Cove TI power button This provides a new input driver for supporting the power button on Dollar Cove TI PMIC, found on Cherrytrail-based devices. The patch is based on the original work by Intel, found at: https://github.com/01org/ProductionKernelQuilts Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=193891 Reviewed-by: Mika Westerberg Signed-off-by: Takashi Iwai Signed-off-by: Andy Shevchenko --- drivers/platform/x86/Kconfig | 11 ++++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel_chtdc_ti_pwrbtn.c | 93 ++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 drivers/platform/x86/intel_chtdc_ti_pwrbtn.c (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 9d2a6d642f33..88bf2f46b7a4 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1184,6 +1184,17 @@ config SILEAD_DMI with the OS-image for the device. This option supplies the missing information. Enable this for x86 tablets with Silead touchscreens. +config INTEL_CHTDC_TI_PWRBTN + tristate "Intel Cherry Trail Dollar Cove TI power button driver" + depends on INTEL_SOC_PMIC_CHTDC_TI + depends on INPUT + ---help--- + This option adds a power button driver driver for Dollar Cove TI + PMIC on Intel Cherry Trail devices. + + To compile this driver as a module, choose M here: the module + will be called intel_chtdc_ti_pwrbtn. + endif # X86_PLATFORM_DEVICES config PMC_ATOM diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 2996536bf54e..4f92dbf30900 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -89,3 +89,4 @@ obj-$(CONFIG_PMC_ATOM) += pmc_atom.o obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o obj-$(CONFIG_MLX_CPLD_PLATFORM) += mlxcpld-hotplug.o obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o +obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o diff --git a/drivers/platform/x86/intel_chtdc_ti_pwrbtn.c b/drivers/platform/x86/intel_chtdc_ti_pwrbtn.c new file mode 100644 index 000000000000..38b8e7cfe88c --- /dev/null +++ b/drivers/platform/x86/intel_chtdc_ti_pwrbtn.c @@ -0,0 +1,93 @@ +/* + * Power-button driver for Dollar Cove TI PMIC + * Copyright (C) 2014 Intel Corp + * Copyright (c) 2017 Takashi Iwai + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHTDC_TI_SIRQ_REG 0x3 +#define SIRQ_PWRBTN_REL BIT(0) + +static irqreturn_t chtdc_ti_pwrbtn_interrupt(int irq, void *dev_id) +{ + struct input_dev *input = dev_id; + struct device *dev = input->dev.parent; + struct regmap *regmap = dev_get_drvdata(dev); + int state; + + if (!regmap_read(regmap, CHTDC_TI_SIRQ_REG, &state)) { + dev_dbg(dev, "SIRQ_REG=0x%x\n", state); + input_report_key(input, KEY_POWER, !(state & SIRQ_PWRBTN_REL)); + input_sync(input); + } + + return IRQ_HANDLED; +} + +static int chtdc_ti_pwrbtn_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent); + struct input_dev *input; + int irq, err; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; + input->name = pdev->name; + input->phys = "power-button/input0"; + input->id.bustype = BUS_HOST; + input_set_capability(input, EV_KEY, KEY_POWER); + err = input_register_device(input); + if (err) + return err; + + dev_set_drvdata(dev, pmic->regmap); + + err = devm_request_threaded_irq(dev, irq, NULL, + chtdc_ti_pwrbtn_interrupt, + 0, KBUILD_MODNAME, input); + if (err) + return err; + + device_init_wakeup(dev, true); + dev_pm_set_wake_irq(dev, irq); + return 0; +} + +static int chtdc_ti_pwrbtn_remove(struct platform_device *pdev) +{ + dev_pm_clear_wake_irq(&pdev->dev); + device_init_wakeup(&pdev->dev, false); + return 0; +} + +static const struct platform_device_id chtdc_ti_pwrbtn_id_table[] = { + { .name = "chtdc_ti_pwrbtn" }, + {}, +}; +MODULE_DEVICE_TABLE(platform, chtdc_ti_pwrbtn_id_table); + +static struct platform_driver chtdc_ti_pwrbtn_driver = { + .driver = { + .name = KBUILD_MODNAME, + }, + .probe = chtdc_ti_pwrbtn_probe, + .remove = chtdc_ti_pwrbtn_remove, + .id_table = chtdc_ti_pwrbtn_id_table, +}; +module_platform_driver(chtdc_ti_pwrbtn_driver); + +MODULE_DESCRIPTION("Power-button driver for Dollar Cove TI PMIC"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 2448f44f31625610ddeafc9c7642da8a78d93c7b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Nov 2017 16:50:33 +0100 Subject: platform/x86: intel_int0002_vgpio: Remove IRQF_NO_THREAD irq flag Remove the IRQF_NO_THREAD irq flag, there is no need for it and it breaks irq-sharing with the "acpi" irq when passing "threadirqs" on the kernel cmdline, as the acpi/osl.c code does not pass IRQF_NO_THREAD. Signed-off-by: Hans de Goede Reported-by: Oleksandr Natalenko Tested-by: Oleksandr Natalenko Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_int0002_vgpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c index f7b67e898abc..a473dc51b18d 100644 --- a/drivers/platform/x86/intel_int0002_vgpio.c +++ b/drivers/platform/x86/intel_int0002_vgpio.c @@ -180,7 +180,7 @@ static int int0002_probe(struct platform_device *pdev) * to gpiochip_set_chained_irqchip, because the irq is shared. */ ret = devm_request_irq(dev, irq, int0002_irq, - IRQF_SHARED | IRQF_NO_THREAD, "INT0002", chip); + IRQF_SHARED, "INT0002", chip); if (ret) { dev_err(dev, "Error requesting IRQ %d: %d\n", irq, ret); return ret; -- cgit v1.2.3 From 9c916549c0345a054431abdc4f2d9ba48e856f80 Mon Sep 17 00:00:00 2001 From: "Chakravarty, Souvik K" Date: Fri, 24 Nov 2017 19:04:41 +0530 Subject: platform/x86: intel_pmc_ipc: Add read64 API Add intel_pmc_gcr_read64() API for reading from 64-bit GCR registers. This API will be called from intel_telemetry. Update description of intel_pmc_gcr_read(). Signed-off-by: Souvik Kumar Chakravarty Signed-off-by: Andy Shevchenko --- arch/x86/include/asm/intel_pmc_ipc.h | 6 ++++++ drivers/platform/x86/intel_pmc_ipc.c | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/arch/x86/include/asm/intel_pmc_ipc.h b/arch/x86/include/asm/intel_pmc_ipc.h index 528ed4be4393..9e7adcdbe031 100644 --- a/arch/x86/include/asm/intel_pmc_ipc.h +++ b/arch/x86/include/asm/intel_pmc_ipc.h @@ -38,6 +38,7 @@ int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out, u32 outlen); int intel_pmc_s0ix_counter_read(u64 *data); int intel_pmc_gcr_read(u32 offset, u32 *data); +int intel_pmc_gcr_read64(u32 offset, u64 *data); int intel_pmc_gcr_write(u32 offset, u32 data); int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val); @@ -70,6 +71,11 @@ static inline int intel_pmc_gcr_read(u32 offset, u32 *data) return -EINVAL; } +static inline int intel_pmc_gcr_read64(u32 offset, u64 *data) +{ + return -EINVAL; +} + static inline int intel_pmc_gcr_write(u32 offset, u32 data) { return -EINVAL; diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index e03fa31446ca..e7edc8c63936 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -215,11 +215,11 @@ static inline int is_gcr_valid(u32 offset) } /** - * intel_pmc_gcr_read() - Read PMC GCR register + * intel_pmc_gcr_read() - Read a 32-bit PMC GCR register * @offset: offset of GCR register from GCR address base * @data: data pointer for storing the register output * - * Reads the PMC GCR register of given offset. + * Reads the 32-bit PMC GCR register at given offset. * * Return: negative value on error or 0 on success. */ @@ -243,6 +243,35 @@ int intel_pmc_gcr_read(u32 offset, u32 *data) } EXPORT_SYMBOL_GPL(intel_pmc_gcr_read); +/** + * intel_pmc_gcr_read64() - Read a 64-bit PMC GCR register + * @offset: offset of GCR register from GCR address base + * @data: data pointer for storing the register output + * + * Reads the 64-bit PMC GCR register at given offset. + * + * Return: negative value on error or 0 on success. + */ +int intel_pmc_gcr_read64(u32 offset, u64 *data) +{ + int ret; + + spin_lock(&ipcdev.gcr_lock); + + ret = is_gcr_valid(offset); + if (ret < 0) { + spin_unlock(&ipcdev.gcr_lock); + return ret; + } + + *data = readq(ipcdev.gcr_mem_base + offset); + + spin_unlock(&ipcdev.gcr_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(intel_pmc_gcr_read64); + /** * intel_pmc_gcr_write() - Write PMC GCR register * @offset: offset of GCR register from GCR address base -- cgit v1.2.3 From 0946a05fd220a24e7f3843011ef696578d02aa29 Mon Sep 17 00:00:00 2001 From: "Chakravarty, Souvik K" Date: Fri, 24 Nov 2017 19:04:42 +0530 Subject: platform/x86: intel_telemetry: Fix suspend stats Suspend stats are not reported consistently due to a limitation in the PMC firmware. This limitation causes a delay in updating the s0ix counters and residencies in the telemetry log upon s0ix exit. As a consequence, reading these counters from the suspend-exit notifier may result in zero read. This patch fixes this issue by cross-verifying the s0ix residencies from the GCR TELEM registers in case the counters are not incremented in the telemetry log after suspend. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=197833 Reported-and-tested-by: Rajneesh Bhardwaj Signed-off-by: Souvik Kumar Chakravarty Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_telemetry_debugfs.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c index 4249e8267bbc..5bc4f208cc8b 100644 --- a/drivers/platform/x86/intel_telemetry_debugfs.c +++ b/drivers/platform/x86/intel_telemetry_debugfs.c @@ -890,6 +890,31 @@ static int pm_suspend_exit_cb(void) goto out; } + /* + * Due to some design limitations in the firmware, sometimes the + * counters do not get updated by the time we reach here. As a + * workaround, we try to see if this was a genuine case of sleep + * failure or not by cross-checking from PMC GCR registers directly. + */ + if (suspend_shlw_ctr_exit == suspend_shlw_ctr_temp && + suspend_deep_ctr_exit == suspend_deep_ctr_temp) { + ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_SHLW_S0IX_REG, + &suspend_shlw_res_exit); + if (ret < 0) + goto out; + + ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_DEEP_S0IX_REG, + &suspend_deep_res_exit); + if (ret < 0) + goto out; + + if (suspend_shlw_res_exit > suspend_shlw_res_temp) + suspend_shlw_ctr_exit++; + + if (suspend_deep_res_exit > suspend_deep_res_temp) + suspend_deep_ctr_exit++; + } + suspend_shlw_ctr_exit -= suspend_shlw_ctr_temp; suspend_deep_ctr_exit -= suspend_deep_ctr_temp; suspend_shlw_res_exit -= suspend_shlw_res_temp; -- cgit v1.2.3 From ffd623d4c5315a9767a5ee183159baf7295219a6 Mon Sep 17 00:00:00 2001 From: "Chakravarty, Souvik K" Date: Fri, 24 Nov 2017 19:04:43 +0530 Subject: platform/x86: intel_telemetry: Improve S0ix logs Suspend with shallow wakes is not a useful parameter since the phenomena does not exist on deployed devices and is only a parameter of use during device power-on phase. The field always reads zero. Additionally there are other easier methods to detect it, e.g., if the S0ix counter increments by more than one during suspend. Hence the field is superfluous and can be removed. This patch also slightly renames the S0ix total field for better viewability. Signed-off-by: Souvik Kumar Chakravarty Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_telemetry_debugfs.c | 45 ++++---------------------- 1 file changed, 7 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c index 5bc4f208cc8b..97aae982d2bd 100644 --- a/drivers/platform/x86/intel_telemetry_debugfs.c +++ b/drivers/platform/x86/intel_telemetry_debugfs.c @@ -98,10 +98,6 @@ static u32 suspend_shlw_ctr_temp, suspend_deep_ctr_temp; static u64 suspend_shlw_res_temp, suspend_deep_res_temp; struct telemetry_susp_stats { - u32 shlw_swake_ctr; - u32 deep_swake_ctr; - u64 shlw_swake_res; - u64 deep_swake_res; u32 shlw_ctr; u32 deep_ctr; u64 shlw_res; @@ -598,19 +594,15 @@ static int telem_soc_states_show(struct seq_file *s, void *unused) seq_printf(s, "S0IX Shallow\t\t\t %10u\t %10llu\n", s0ix_shlw_ctr - - conf->suspend_stats.shlw_ctr - - conf->suspend_stats.shlw_swake_ctr, + conf->suspend_stats.shlw_ctr, (u64)((s0ix_shlw_res - - conf->suspend_stats.shlw_res - - conf->suspend_stats.shlw_swake_res)*10/192)); + conf->suspend_stats.shlw_res)*10/192)); seq_printf(s, "S0IX Deep\t\t\t %10u\t %10llu\n", s0ix_deep_ctr - - conf->suspend_stats.deep_ctr - - conf->suspend_stats.deep_swake_ctr, + conf->suspend_stats.deep_ctr, (u64)((s0ix_deep_res - - conf->suspend_stats.deep_res - - conf->suspend_stats.deep_swake_res)*10/192)); + conf->suspend_stats.deep_res)*10/192)); seq_printf(s, "Suspend(With S0ixShallow)\t %10u\t %10llu\n", conf->suspend_stats.shlw_ctr, @@ -620,13 +612,7 @@ static int telem_soc_states_show(struct seq_file *s, void *unused) conf->suspend_stats.deep_ctr, (u64)(conf->suspend_stats.deep_res*10)/192); - seq_printf(s, "Suspend(With Shallow-Wakes)\t %10u\t %10llu\n", - conf->suspend_stats.shlw_swake_ctr + - conf->suspend_stats.deep_swake_ctr, - (u64)((conf->suspend_stats.shlw_swake_res + - conf->suspend_stats.deep_swake_res)*10/192)); - - seq_printf(s, "S0IX+Suspend Total\t\t %10u\t %10llu\n", s0ix_total_ctr, + seq_printf(s, "TOTAL S0IX\t\t\t %10u\t %10llu\n", s0ix_total_ctr, (u64)(s0ix_total_res*10/192)); seq_puts(s, "\n-------------------------------------------------\n"); seq_puts(s, "\t\tDEVICE STATES\n"); @@ -920,23 +906,15 @@ static int pm_suspend_exit_cb(void) suspend_shlw_res_exit -= suspend_shlw_res_temp; suspend_deep_res_exit -= suspend_deep_res_temp; - if (suspend_shlw_ctr_exit == 1) { + if (suspend_shlw_ctr_exit != 0) { conf->suspend_stats.shlw_ctr += suspend_shlw_ctr_exit; conf->suspend_stats.shlw_res += suspend_shlw_res_exit; } - /* Shallow Wakes Case */ - else if (suspend_shlw_ctr_exit > 1) { - conf->suspend_stats.shlw_swake_ctr += - suspend_shlw_ctr_exit; - - conf->suspend_stats.shlw_swake_res += - suspend_shlw_res_exit; - } - if (suspend_deep_ctr_exit == 1) { + if (suspend_deep_ctr_exit != 0) { conf->suspend_stats.deep_ctr += suspend_deep_ctr_exit; @@ -944,15 +922,6 @@ static int pm_suspend_exit_cb(void) suspend_deep_res_exit; } - /* Shallow Wakes Case */ - else if (suspend_deep_ctr_exit > 1) { - conf->suspend_stats.deep_swake_ctr += - suspend_deep_ctr_exit; - - conf->suspend_stats.deep_swake_res += - suspend_deep_res_exit; - } - out: suspend_prep_ok = 0; return NOTIFY_OK; -- cgit v1.2.3 From c622cbe5d11657a12c473356826017fed0c7669e Mon Sep 17 00:00:00 2001 From: "Chakravarty, Souvik K" Date: Fri, 24 Nov 2017 19:04:44 +0530 Subject: platform/x86: intel_telemetry: Remove redundancies This patch removes unnecessary header files and newlines. It also fixes some alignment issues. Signed-off-by: Souvik Kumar Chakravarty Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_telemetry_debugfs.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c index 97aae982d2bd..ffd0474b0531 100644 --- a/drivers/platform/x86/intel_telemetry_debugfs.c +++ b/drivers/platform/x86/intel_telemetry_debugfs.c @@ -23,7 +23,6 @@ */ #include #include -#include #include #include #include @@ -32,11 +31,10 @@ #include #include #include -#include #include -#define DRIVER_NAME "telemetry_soc_debugfs" -#define DRIVER_VERSION "1.0.0" +#define DRIVER_NAME "telemetry_soc_debugfs" +#define DRIVER_VERSION "1.0.0" /* ApolloLake SoC Event-IDs */ #define TELEM_APL_PSS_PSTATES_ID 0x2802 @@ -246,7 +244,6 @@ static struct telem_ioss_pg_info telem_apl_ioss_pg_data[] = { {"PRTC", 25}, }; - struct telemetry_debugfs_conf { struct telemetry_susp_stats suspend_stats; struct dentry *telemetry_dbg_dir; @@ -381,7 +378,6 @@ static int telem_pss_states_show(struct seq_file *s, void *unused) TELEM_APL_MASK_PCS_STATE; } - TELEM_CHECK_AND_PARSE_EVTS(conf->pss_idle_id, conf->pss_idle_evts - 1, pss_idle, evtlog[index].telem_evtlog, @@ -401,7 +397,6 @@ static int telem_pss_states_show(struct seq_file *s, void *unused) conf->pcs_s0ix_blkd_data, TELEM_MASK_BYTE); - TELEM_CHECK_AND_PARSE_EVTS(conf->pss_wakeup_id, conf->pss_wakeup_evts, pss_s0ix_wakeup, @@ -494,7 +489,6 @@ static const struct file_operations telem_pss_ops = { .release = single_release, }; - static int telem_ioss_states_show(struct seq_file *s, void *unused) { struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS]; @@ -613,7 +607,7 @@ static int telem_soc_states_show(struct seq_file *s, void *unused) (u64)(conf->suspend_stats.deep_res*10)/192); seq_printf(s, "TOTAL S0IX\t\t\t %10u\t %10llu\n", s0ix_total_ctr, - (u64)(s0ix_total_res*10/192)); + (u64)(s0ix_total_res*10/192)); seq_puts(s, "\n-------------------------------------------------\n"); seq_puts(s, "\t\tDEVICE STATES\n"); seq_puts(s, "-------------------------------------------------\n"); @@ -758,7 +752,6 @@ static const struct file_operations telem_pss_trc_verb_ops = { .release = single_release, }; - static int telem_ioss_trc_verb_show(struct seq_file *s, void *unused) { u32 verbosity; -- cgit v1.2.3 From 5f0337b549e97fda07ccf48b9eebcee983c255bf Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 20 Nov 2017 17:40:15 +0000 Subject: USB: serial: iuu_phoenix: remove redundant assignment of DIV to itself The assignment of DIV to itself is redundant and can be removed. Signed-off-by: Colin Ian King Signed-off-by: Johan Hovold --- drivers/usb/serial/iuu_phoenix.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 397a8012ffa3..62c91e360baf 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -472,7 +472,6 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq) } } P2 = ((P - PO) / 2) - 4; - DIV = DIV; PUMP = 0x04; PBmsb = (P2 >> 8 & 0x03); PBlsb = P2 & 0xFF; -- cgit v1.2.3 From 86a18ee21e5eecf56ca02aec24807ffa87bb57b6 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 13 Nov 2017 15:08:10 +0200 Subject: EDAC, ti: Add support for TI keystone and DRA7xx EDAC TI Keystone and DRA7xx SoCs have support for EDAC on DDR3 memory that can correct one bit errors and detect two bit errors. Add EDAC driver for this feature which plugs into the generic kernel EDAC framework. Signed-off-by: Tero Kristo Cc: linux-arm-kernel@lists.infradead.org Cc: linux-edac Cc: linux-omap@vger.kernel.org Link: http://lkml.kernel.org/r/1510578490-14510-1-git-send-email-t-kristo@ti.com [ Add SPDX tag and make _emif_get_id() use edac_printk(). ] Signed-off-by: Borislav Petkov --- MAINTAINERS | 6 + drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/ti_edac.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 355 insertions(+) create mode 100644 drivers/edac/ti_edac.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index aa71ab52fd76..27abd1524042 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5140,6 +5140,12 @@ L: linux-edac@vger.kernel.org S: Maintained F: drivers/edac/skx_edac.c +EDAC-TI +M: Tero Kristo +L: linux-edac@vger.kernel.org +S: Maintained +F: drivers/edac/ti_edac.c + EDIROL UA-101/UA-1000 DRIVER M: Clemens Ladisch L: alsa-devel@alsa-project.org (moderated for non-subscribers) diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 96afb2aeed18..3c4017007647 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -457,4 +457,11 @@ config EDAC_XGENE Support for error detection and correction on the APM X-Gene family of SOCs. +config EDAC_TI + tristate "Texas Instruments DDR3 ECC Controller" + depends on ARCH_KEYSTONE || SOC_DRA7XX + help + Support for error detection and correction on the + TI SoCs. + endif # EDAC diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 0fd9ffa63299..b54912eb39af 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -78,3 +78,4 @@ obj-$(CONFIG_EDAC_THUNDERX) += thunderx_edac.o obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o +obj-$(CONFIG_EDAC_TI) += ti_edac.o diff --git a/drivers/edac/ti_edac.c b/drivers/edac/ti_edac.c new file mode 100644 index 000000000000..6ac26d1b929f --- /dev/null +++ b/drivers/edac/ti_edac.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * + * Texas Instruments DDR3 ECC error correction and detection driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "edac_module.h" + +/* EMIF controller registers */ +#define EMIF_SDRAM_CONFIG 0x008 +#define EMIF_IRQ_STATUS 0x0ac +#define EMIF_IRQ_ENABLE_SET 0x0b4 +#define EMIF_ECC_CTRL 0x110 +#define EMIF_1B_ECC_ERR_CNT 0x130 +#define EMIF_1B_ECC_ERR_THRSH 0x134 +#define EMIF_1B_ECC_ERR_ADDR_LOG 0x13c +#define EMIF_2B_ECC_ERR_ADDR_LOG 0x140 + +/* Bit definitions for EMIF_SDRAM_CONFIG */ +#define SDRAM_TYPE_SHIFT 29 +#define SDRAM_TYPE_MASK GENMASK(31, 29) +#define SDRAM_TYPE_DDR3 (3 << SDRAM_TYPE_SHIFT) +#define SDRAM_TYPE_DDR2 (2 << SDRAM_TYPE_SHIFT) +#define SDRAM_NARROW_MODE_MASK GENMASK(15, 14) +#define SDRAM_K2_NARROW_MODE_SHIFT 12 +#define SDRAM_K2_NARROW_MODE_MASK GENMASK(13, 12) +#define SDRAM_ROWSIZE_SHIFT 7 +#define SDRAM_ROWSIZE_MASK GENMASK(9, 7) +#define SDRAM_IBANK_SHIFT 4 +#define SDRAM_IBANK_MASK GENMASK(6, 4) +#define SDRAM_K2_IBANK_SHIFT 5 +#define SDRAM_K2_IBANK_MASK GENMASK(6, 5) +#define SDRAM_K2_EBANK_SHIFT 3 +#define SDRAM_K2_EBANK_MASK BIT(SDRAM_K2_EBANK_SHIFT) +#define SDRAM_PAGESIZE_SHIFT 0 +#define SDRAM_PAGESIZE_MASK GENMASK(2, 0) +#define SDRAM_K2_PAGESIZE_SHIFT 0 +#define SDRAM_K2_PAGESIZE_MASK GENMASK(1, 0) + +#define EMIF_1B_ECC_ERR_THRSH_SHIFT 24 + +/* IRQ bit definitions */ +#define EMIF_1B_ECC_ERR BIT(5) +#define EMIF_2B_ECC_ERR BIT(4) +#define EMIF_WR_ECC_ERR BIT(3) +#define EMIF_SYS_ERR BIT(0) +/* Bit 31 enables ECC and 28 enables RMW */ +#define ECC_ENABLED (BIT(31) | BIT(28)) + +#define EDAC_MOD_NAME "ti-emif-edac" + +enum { + EMIF_TYPE_DRA7, + EMIF_TYPE_K2 +}; + +struct ti_edac { + void __iomem *reg; +}; + +static u32 ti_edac_readl(struct ti_edac *edac, u16 offset) +{ + return readl_relaxed(edac->reg + offset); +} + +static void ti_edac_writel(struct ti_edac *edac, u32 val, u16 offset) +{ + writel_relaxed(val, edac->reg + offset); +} + +static irqreturn_t ti_edac_isr(int irq, void *data) +{ + struct mem_ctl_info *mci = data; + struct ti_edac *edac = mci->pvt_info; + u32 irq_status; + u32 err_addr; + int err_count; + + irq_status = ti_edac_readl(edac, EMIF_IRQ_STATUS); + + if (irq_status & EMIF_1B_ECC_ERR) { + err_addr = ti_edac_readl(edac, EMIF_1B_ECC_ERR_ADDR_LOG); + err_count = ti_edac_readl(edac, EMIF_1B_ECC_ERR_CNT); + ti_edac_writel(edac, err_count, EMIF_1B_ECC_ERR_CNT); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, err_count, + err_addr >> PAGE_SHIFT, + err_addr & ~PAGE_MASK, -1, 0, 0, 0, + mci->ctl_name, "1B"); + } + + if (irq_status & EMIF_2B_ECC_ERR) { + err_addr = ti_edac_readl(edac, EMIF_2B_ECC_ERR_ADDR_LOG); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + err_addr >> PAGE_SHIFT, + err_addr & ~PAGE_MASK, -1, 0, 0, 0, + mci->ctl_name, "2B"); + } + + if (irq_status & EMIF_WR_ECC_ERR) + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + 0, 0, -1, 0, 0, 0, + mci->ctl_name, "WR"); + + ti_edac_writel(edac, irq_status, EMIF_IRQ_STATUS); + + return IRQ_HANDLED; +} + +static void ti_edac_setup_dimm(struct mem_ctl_info *mci, u32 type) +{ + struct dimm_info *dimm; + struct ti_edac *edac = mci->pvt_info; + int bits; + u32 val; + u32 memsize; + + dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, 0, 0, 0); + + val = ti_edac_readl(edac, EMIF_SDRAM_CONFIG); + + if (type == EMIF_TYPE_DRA7) { + bits = ((val & SDRAM_PAGESIZE_MASK) >> SDRAM_PAGESIZE_SHIFT) + 8; + bits += ((val & SDRAM_ROWSIZE_MASK) >> SDRAM_ROWSIZE_SHIFT) + 9; + bits += (val & SDRAM_IBANK_MASK) >> SDRAM_IBANK_SHIFT; + + if (val & SDRAM_NARROW_MODE_MASK) { + bits++; + dimm->dtype = DEV_X16; + } else { + bits += 2; + dimm->dtype = DEV_X32; + } + } else { + bits = 16; + bits += ((val & SDRAM_K2_PAGESIZE_MASK) >> + SDRAM_K2_PAGESIZE_SHIFT) + 8; + bits += (val & SDRAM_K2_IBANK_MASK) >> SDRAM_K2_IBANK_SHIFT; + bits += (val & SDRAM_K2_EBANK_MASK) >> SDRAM_K2_EBANK_SHIFT; + + val = (val & SDRAM_K2_NARROW_MODE_MASK) >> + SDRAM_K2_NARROW_MODE_SHIFT; + switch (val) { + case 0: + bits += 3; + dimm->dtype = DEV_X64; + break; + case 1: + bits += 2; + dimm->dtype = DEV_X32; + break; + case 2: + bits++; + dimm->dtype = DEV_X16; + break; + } + } + + memsize = 1 << bits; + + dimm->nr_pages = memsize >> PAGE_SHIFT; + dimm->grain = 4; + if ((val & SDRAM_TYPE_MASK) == SDRAM_TYPE_DDR2) + dimm->mtype = MEM_DDR2; + else + dimm->mtype = MEM_DDR3; + + val = ti_edac_readl(edac, EMIF_ECC_CTRL); + if (val & ECC_ENABLED) + dimm->edac_mode = EDAC_SECDED; + else + dimm->edac_mode = EDAC_NONE; +} + +static const struct of_device_id ti_edac_of_match[] = { + { .compatible = "ti,emif-keystone", .data = (void *)EMIF_TYPE_K2 }, + { .compatible = "ti,emif-dra7xx", .data = (void *)EMIF_TYPE_DRA7 }, + {}, +}; + +static int _emif_get_id(struct device_node *node) +{ + struct device_node *np; + const __be32 *addrp; + u32 addr, my_addr; + int my_id = 0; + + addrp = of_get_address(node, 0, NULL, NULL); + my_addr = (u32)of_translate_address(node, addrp); + + for_each_matching_node(np, ti_edac_of_match) { + if (np == node) + continue; + + addrp = of_get_address(np, 0, NULL, NULL); + addr = (u32)of_translate_address(np, addrp); + + edac_printk(KERN_INFO, EDAC_MOD_NAME, + "addr=%x, my_addr=%x\n", + addr, my_addr); + + if (addr < my_addr) + my_id++; + } + + return my_id; +} + +static int ti_edac_probe(struct platform_device *pdev) +{ + int error_irq = 0, ret = -ENODEV; + struct device *dev = &pdev->dev; + struct resource *res; + void __iomem *reg; + struct mem_ctl_info *mci; + struct edac_mc_layer layers[1]; + const struct of_device_id *id; + struct ti_edac *edac; + int emif_id; + + id = of_match_device(ti_edac_of_match, &pdev->dev); + if (!id) + return -ENODEV; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg = devm_ioremap_resource(dev, res); + if (IS_ERR(reg)) { + edac_printk(KERN_ERR, EDAC_MOD_NAME, + "EMIF controller regs not defined\n"); + return PTR_ERR(reg); + } + + layers[0].type = EDAC_MC_LAYER_ALL_MEM; + layers[0].size = 1; + + /* Allocate ID number for our EMIF controller */ + emif_id = _emif_get_id(pdev->dev.of_node); + if (emif_id < 0) + return -EINVAL; + + mci = edac_mc_alloc(emif_id, 1, layers, sizeof(*edac)); + if (!mci) + return -ENOMEM; + + mci->pdev = &pdev->dev; + edac = mci->pvt_info; + edac->reg = reg; + platform_set_drvdata(pdev, mci); + + mci->mtype_cap = MEM_FLAG_DDR3 | MEM_FLAG_DDR2; + mci->edac_ctl_cap = EDAC_FLAG_SECDED | EDAC_FLAG_NONE; + mci->mod_name = EDAC_MOD_NAME; + mci->ctl_name = id->compatible; + mci->dev_name = dev_name(&pdev->dev); + + /* Setup memory layout */ + ti_edac_setup_dimm(mci, (u32)(id->data)); + + /* add EMIF ECC error handler */ + error_irq = platform_get_irq(pdev, 0); + if (!error_irq) { + edac_printk(KERN_ERR, EDAC_MOD_NAME, + "EMIF irq number not defined.\n"); + goto err; + } + + ret = devm_request_irq(dev, error_irq, ti_edac_isr, 0, + "emif-edac-irq", mci); + if (ret) { + edac_printk(KERN_ERR, EDAC_MOD_NAME, + "request_irq fail for EMIF EDAC irq\n"); + goto err; + } + + ret = edac_mc_add_mc(mci); + if (ret) { + edac_printk(KERN_ERR, EDAC_MOD_NAME, + "Failed to register mci: %d.\n", ret); + goto err; + } + + /* Generate an interrupt with each 1b error */ + ti_edac_writel(edac, 1 << EMIF_1B_ECC_ERR_THRSH_SHIFT, + EMIF_1B_ECC_ERR_THRSH); + + /* Enable interrupts */ + ti_edac_writel(edac, + EMIF_1B_ECC_ERR | EMIF_2B_ECC_ERR | EMIF_WR_ECC_ERR, + EMIF_IRQ_ENABLE_SET); + + return 0; + +err: + edac_mc_free(mci); + return ret; +} + +static int ti_edac_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + edac_mc_del_mc(&pdev->dev); + edac_mc_free(mci); + + return 0; +} + +static struct platform_driver ti_edac_driver = { + .probe = ti_edac_probe, + .remove = ti_edac_remove, + .driver = { + .name = EDAC_MOD_NAME, + .of_match_table = ti_edac_of_match, + }, +}; + +module_platform_driver(ti_edac_driver); + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("EDAC Driver for Texas Instruments DDR3 MC"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 75eccf5ed83250c0aeaeeb76f7288254ac0a87b4 Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Tue, 7 Nov 2017 22:12:23 +0800 Subject: clk: meson: gxbb: fix wrong clock for SARADC/SANA According to the datasheet, in Meson-GXBB/GXL series, The clock gate bit for SARADC is HHI_GCLK_MPEG2 bit[22], while clock gate bit for SANA is HHI_GCLK_MPEG0 bit[10]. Test passed at gxl-s905x-p212 board. The following published datasheets are wrong and should be updated [1] GXBB v1.1.4 [2] GXL v0.3_20170314 Fixes: 738f66d3211d ("clk: gxbb: add AmLogic GXBB clk controller driver") Tested-by: Xingyu Chen Signed-off-by: Yixun Lan Signed-off-by: Jerome Brunet --- drivers/clk/meson/gxbb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index ae385310e980..2ac9f3fa9578 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -1386,7 +1386,7 @@ static MESON_GATE(gxbb_pl301, HHI_GCLK_MPEG0, 6); static MESON_GATE(gxbb_periphs, HHI_GCLK_MPEG0, 7); static MESON_GATE(gxbb_spicc, HHI_GCLK_MPEG0, 8); static MESON_GATE(gxbb_i2c, HHI_GCLK_MPEG0, 9); -static MESON_GATE(gxbb_sar_adc, HHI_GCLK_MPEG0, 10); +static MESON_GATE(gxbb_sana, HHI_GCLK_MPEG0, 10); static MESON_GATE(gxbb_smart_card, HHI_GCLK_MPEG0, 11); static MESON_GATE(gxbb_rng0, HHI_GCLK_MPEG0, 12); static MESON_GATE(gxbb_uart0, HHI_GCLK_MPEG0, 13); @@ -1437,7 +1437,7 @@ static MESON_GATE(gxbb_usb0_ddr_bridge, HHI_GCLK_MPEG2, 9); static MESON_GATE(gxbb_mmc_pclk, HHI_GCLK_MPEG2, 11); static MESON_GATE(gxbb_dvin, HHI_GCLK_MPEG2, 12); static MESON_GATE(gxbb_uart2, HHI_GCLK_MPEG2, 15); -static MESON_GATE(gxbb_sana, HHI_GCLK_MPEG2, 22); +static MESON_GATE(gxbb_sar_adc, HHI_GCLK_MPEG2, 22); static MESON_GATE(gxbb_vpu_intr, HHI_GCLK_MPEG2, 25); static MESON_GATE(gxbb_sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26); static MESON_GATE(gxbb_clk81_a53, HHI_GCLK_MPEG2, 29); -- cgit v1.2.3 From a094c2fa093cf7fd0fe23d15cc2abca4083c6a45 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Tue, 21 Nov 2017 10:09:03 +0100 Subject: spi: xilinx: Add support for xlnx,axi-quad-spi-1.00.a The driver has been successfully tested with Xilinx's core axi-quad-spi-1.0.0a. Documented on DS843: https://www.xilinx.com/support/documentation/ip_documentation/axi_quad_spi/v1_00_a/ds843_axi_quad_spi.pdf Cc: Mark Brown Cc: Rob Herring Cc: devicetree@vger.kernel.org Signed-off-by: Ricardo Ribalda Delgado Acked-by: Rob Herring Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-xilinx.txt | 2 +- drivers/spi/spi-xilinx.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/spi/spi-xilinx.txt b/Documentation/devicetree/bindings/spi/spi-xilinx.txt index c7b7856bd528..7bf61efc66c8 100644 --- a/Documentation/devicetree/bindings/spi/spi-xilinx.txt +++ b/Documentation/devicetree/bindings/spi/spi-xilinx.txt @@ -2,7 +2,7 @@ Xilinx SPI controller Device Tree Bindings ------------------------------------------------- Required properties: -- compatible : Should be "xlnx,xps-spi-2.00.a" or "xlnx,xps-spi-2.00.b" +- compatible : Should be "xlnx,xps-spi-2.00.a", "xlnx,xps-spi-2.00.b" or "xlnx,axi-quad-spi-1.00.a" - reg : Physical base address and size of SPI registers map. - interrupts : Property with a value describing the interrupt number. diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index e0b9fe1d0e37..63fedc49ae9c 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -381,6 +381,7 @@ static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi) } static const struct of_device_id xilinx_spi_of_match[] = { + { .compatible = "xlnx,axi-quad-spi-1.00.a", }, { .compatible = "xlnx,xps-spi-2.00.a", }, { .compatible = "xlnx,xps-spi-2.00.b", }, {} -- cgit v1.2.3 From 43df43e6ba139e6cd77ea31ca27efc67ea2df44b Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 23 Aug 2017 16:46:12 +0300 Subject: i2c: designware: Don't set SCL timings and speed mode when in slave mode According to data sheet SCL timing parameters and DW_IC_CON SPEED mode bits are not used when operating in slave mode. Signed-off-by: Jarkko Nikula Tested-by: Luis Oliveira Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-platdrv.c | 11 ----- drivers/i2c/busses/i2c-designware-slave.c | 64 ----------------------------- 2 files changed, 75 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 58add69a441c..293f586d78d2 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -201,17 +201,6 @@ static void i2c_dw_configure_slave(struct dw_i2c_dev *dev) DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED; dev->mode = DW_IC_SLAVE; - - switch (dev->clk_freq) { - case 100000: - dev->slave_cfg |= DW_IC_CON_SPEED_STD; - break; - case 3400000: - dev->slave_cfg |= DW_IC_CON_SPEED_HIGH; - break; - default: - dev->slave_cfg |= DW_IC_CON_SPEED_FAST; - } } static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare) diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index ea9578ab19a1..d42558d1b002 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -51,9 +51,7 @@ static void i2c_dw_configure_fifo_slave(struct dw_i2c_dev *dev) */ static int i2c_dw_init_slave(struct dw_i2c_dev *dev) { - u32 sda_falling_time, scl_falling_time; u32 reg, comp_param1; - u32 hcnt, lcnt; int ret; ret = i2c_dw_acquire_lock(dev); @@ -79,68 +77,6 @@ static int i2c_dw_init_slave(struct dw_i2c_dev *dev) /* Disable the adapter. */ __i2c_dw_enable_and_wait(dev, false); - /* Set standard and fast speed deviders for high/low periods. */ - sda_falling_time = dev->sda_falling_time ?: 300; /* ns */ - scl_falling_time = dev->scl_falling_time ?: 300; /* ns */ - - /* Set SCL timing parameters for standard-mode. */ - if (dev->ss_hcnt && dev->ss_lcnt) { - hcnt = dev->ss_hcnt; - lcnt = dev->ss_lcnt; - } else { - hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev), - 4000, /* tHD;STA = tHIGH = 4.0 us */ - sda_falling_time, - 0, /* 0: DW default, 1: Ideal */ - 0); /* No offset */ - lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev), - 4700, /* tLOW = 4.7 us */ - scl_falling_time, - 0); /* No offset */ - } - dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT); - dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); - dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); - - /* Set SCL timing parameters for fast-mode or fast-mode plus. */ - if ((dev->clk_freq == 1000000) && dev->fp_hcnt && dev->fp_lcnt) { - hcnt = dev->fp_hcnt; - lcnt = dev->fp_lcnt; - } else if (dev->fs_hcnt && dev->fs_lcnt) { - hcnt = dev->fs_hcnt; - lcnt = dev->fs_lcnt; - } else { - hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev), - 600, /* tHD;STA = tHIGH = 0.6 us */ - sda_falling_time, - 0, /* 0: DW default, 1: Ideal */ - 0); /* No offset */ - lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev), - 1300, /* tLOW = 1.3 us */ - scl_falling_time, - 0); /* No offset */ - } - dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT); - dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); - dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); - - if ((dev->slave_cfg & DW_IC_CON_SPEED_MASK) == - DW_IC_CON_SPEED_HIGH) { - if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK) - != DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) { - dev_err(dev->dev, "High Speed not supported!\n"); - dev->slave_cfg &= ~DW_IC_CON_SPEED_MASK; - dev->slave_cfg |= DW_IC_CON_SPEED_FAST; - } else if (dev->hs_hcnt && dev->hs_lcnt) { - hcnt = dev->hs_hcnt; - lcnt = dev->hs_lcnt; - dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT); - dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT); - dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n", - hcnt, lcnt); - } - } - /* Configure SDA Hold Time if required. */ reg = dw_readl(dev, DW_IC_COMP_VERSION); if (reg >= DW_IC_SDA_HOLD_MIN_VERS) { -- cgit v1.2.3 From 3991c5c80beaf7eb9bce61e0b2f8f449e351a38e Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Thu, 2 Nov 2017 10:40:24 +0800 Subject: i2c: Switch to using gpiod interface for gpio bus recovery Currently the i2c gpio recovery code uses gpio integer interface instead of the gpiod. This change switch the core code to use the gpiod while still retaining compatibility with the gpio integer interface. This will allow individual driver to be updated and tested individual to switch to using the gpiod interface. Reviewed-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Phil Reid Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 21 +++++++++++++++++---- include/linux/i2c.h | 4 ++++ 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 706164b4c5be..fdc6a9d1394e 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -134,17 +134,17 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) /* i2c bus recovery routines */ static int get_scl_gpio_value(struct i2c_adapter *adap) { - return gpio_get_value(adap->bus_recovery_info->scl_gpio); + return gpiod_get_value_cansleep(adap->bus_recovery_info->scl_gpiod); } static void set_scl_gpio_value(struct i2c_adapter *adap, int val) { - gpio_set_value(adap->bus_recovery_info->scl_gpio, val); + gpiod_set_value_cansleep(adap->bus_recovery_info->scl_gpiod, val); } static int get_sda_gpio_value(struct i2c_adapter *adap) { - return gpio_get_value(adap->bus_recovery_info->sda_gpio); + return gpiod_get_value_cansleep(adap->bus_recovery_info->sda_gpiod); } static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap) @@ -159,6 +159,7 @@ static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap) dev_warn(dev, "Can't get SCL gpio: %d\n", bri->scl_gpio); return ret; } + bri->scl_gpiod = gpio_to_desc(bri->scl_gpio); if (bri->get_sda) { if (gpio_request_one(bri->sda_gpio, GPIOF_IN, "i2c-sda")) { @@ -167,6 +168,7 @@ static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap) bri->sda_gpio); bri->get_sda = NULL; } + bri->sda_gpiod = gpio_to_desc(bri->sda_gpio); } return ret; @@ -176,10 +178,13 @@ static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap) { struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; - if (bri->get_sda) + if (bri->get_sda) { gpio_free(bri->sda_gpio); + bri->sda_gpiod = NULL; + } gpio_free(bri->scl_gpio); + bri->scl_gpiod = NULL; } /* @@ -277,6 +282,14 @@ static void i2c_init_recovery(struct i2c_adapter *adap) goto err; } + if (bri->scl_gpiod && bri->recover_bus == i2c_generic_scl_recovery) { + bri->get_scl = get_scl_gpio_value; + bri->set_scl = set_scl_gpio_value; + if (bri->sda_gpiod) + bri->get_sda = get_sda_gpio_value; + return; + } + /* Generic GPIO recovery */ if (bri->recover_bus == i2c_generic_gpio_recovery) { if (!gpio_is_valid(bri->scl_gpio)) { diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 5857236919cf..bf62c4a97a09 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -499,6 +499,8 @@ struct i2c_timings { * may configure padmux here for SDA/SCL line or something else they want. * @scl_gpio: gpio number of the SCL line. Only required for GPIO recovery. * @sda_gpio: gpio number of the SDA line. Only required for GPIO recovery. + * @scl_gpiod: gpiod of the SCL line. Only required for GPIO recovery. + * @sda_gpiod: gpiod of the SDA line. Only required for GPIO recovery. */ struct i2c_bus_recovery_info { int (*recover_bus)(struct i2c_adapter *); @@ -513,6 +515,8 @@ struct i2c_bus_recovery_info { /* gpio recovery */ int scl_gpio; int sda_gpio; + struct gpio_desc *scl_gpiod; + struct gpio_desc *sda_gpiod; }; int i2c_recover_bus(struct i2c_adapter *adap); -- cgit v1.2.3 From a34a0b6da22540d19e578131bbb60994892473d3 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Thu, 2 Nov 2017 10:40:25 +0800 Subject: i2c: designware: move i2c_dw_plat_prepare_clk to common Move the i2c_dw_plat_prepare_clk funciton to common file in preparation for its use also by the master driver. Acked-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Phil Reid Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-common.c | 13 +++++++++++++ drivers/i2c/busses/i2c-designware-core.h | 1 + drivers/i2c/busses/i2c-designware-platdrv.c | 12 ------------ 3 files changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index d1a69372432f..b79f34245930 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -21,6 +21,7 @@ * ---------------------------------------------------------------------------- * */ +#include #include #include #include @@ -185,6 +186,18 @@ unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev) return dev->get_clk_rate_khz(dev); } +int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare) +{ + if (IS_ERR(i_dev->clk)) + return PTR_ERR(i_dev->clk); + + if (prepare) + return clk_prepare_enable(i_dev->clk); + + clk_disable_unprepare(i_dev->clk); + return 0; +} + int i2c_dw_acquire_lock(struct dw_i2c_dev *dev) { int ret; diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 21bf619a86c5..e80a14c40347 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -301,6 +301,7 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset); void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable); void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable); unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev); +int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare); int i2c_dw_acquire_lock(struct dw_i2c_dev *dev); void i2c_dw_release_lock(struct dw_i2c_dev *dev); int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 293f586d78d2..6a3fd8d7c273 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -203,18 +203,6 @@ static void i2c_dw_configure_slave(struct dw_i2c_dev *dev) dev->mode = DW_IC_SLAVE; } -static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare) -{ - if (IS_ERR(i_dev->clk)) - return PTR_ERR(i_dev->clk); - - if (prepare) - return clk_prepare_enable(i_dev->clk); - - clk_disable_unprepare(i_dev->clk); - return 0; -} - static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id) { u32 param, tx_fifo_depth, rx_fifo_depth; -- cgit v1.2.3 From 0326f9f801b2411811906361db870ccdada98b92 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Thu, 2 Nov 2017 10:40:26 +0800 Subject: i2c: designware: rename i2c_dw_plat_prepare_clk to i2c_dw_prepare_clk For consistency with the rest of the file rename function and parameter to be consistent with the reset of the common file. Acked-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Phil Reid Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-common.c | 10 +++++----- drivers/i2c/busses/i2c-designware-core.h | 2 +- drivers/i2c/busses/i2c-designware-platdrv.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index b79f34245930..3d684c6650b5 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -186,15 +186,15 @@ unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev) return dev->get_clk_rate_khz(dev); } -int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare) +int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare) { - if (IS_ERR(i_dev->clk)) - return PTR_ERR(i_dev->clk); + if (IS_ERR(dev->clk)) + return PTR_ERR(dev->clk); if (prepare) - return clk_prepare_enable(i_dev->clk); + return clk_prepare_enable(dev->clk); - clk_disable_unprepare(i_dev->clk); + clk_disable_unprepare(dev->clk); return 0; } diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index e80a14c40347..33c6c8f03061 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -301,7 +301,7 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset); void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable); void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable); unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev); -int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare); +int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare); int i2c_dw_acquire_lock(struct dw_i2c_dev *dev); void i2c_dw_release_lock(struct dw_i2c_dev *dev); int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 6a3fd8d7c273..6e0fd94faba1 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -332,7 +332,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) i2c_dw_configure_master(dev); dev->clk = devm_clk_get(&pdev->dev, NULL); - if (!i2c_dw_plat_prepare_clk(dev, true)) { + if (!i2c_dw_prepare_clk(dev, true)) { dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; if (!dev->sda_hold_time && ht) @@ -436,7 +436,7 @@ static int dw_i2c_plat_suspend(struct device *dev) } i_dev->disable(i_dev); - i2c_dw_plat_prepare_clk(i_dev, false); + i2c_dw_prepare_clk(i_dev, false); i_dev->suspended = true; @@ -455,7 +455,7 @@ static int dw_i2c_plat_resume(struct device *dev) return 0; } - i2c_dw_plat_prepare_clk(i_dev, true); + i2c_dw_prepare_clk(i_dev, true); i_dev->init(i_dev); i_dev->suspended = false; -- cgit v1.2.3 From ca382f5b38f367b656c8fd9a0fb93d8f54843520 Mon Sep 17 00:00:00 2001 From: Tim Sander Date: Thu, 2 Nov 2017 10:40:27 +0800 Subject: i2c: designware: add i2c gpio recovery option This patch contains much input from Phil Reid and has been tested on Intel/Altera Cyclone V SOC Hardware with Altera GPIO's for the SCL and SDA GPIO's. Acked-by: Jarkko Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Tim Sander Signed-off-by: Phil Reid Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-common.c | 6 +++- drivers/i2c/busses/i2c-designware-core.h | 1 + drivers/i2c/busses/i2c-designware-master.c | 57 ++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 3d684c6650b5..6b82809647dc 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -230,7 +230,11 @@ int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) { if (timeout <= 0) { dev_warn(dev->dev, "timeout waiting for bus ready\n"); - return -ETIMEDOUT; + i2c_recover_bus(&dev->adapter); + + if (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) + return -ETIMEDOUT; + return 0; } timeout--; usleep_range(1000, 1100); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 33c6c8f03061..d58a336521bf 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -286,6 +286,7 @@ struct dw_i2c_dev { void (*disable_int)(struct dw_i2c_dev *dev); int (*init)(struct dw_i2c_dev *dev); int mode; + struct i2c_bus_recovery_info rinfo; }; #define ACCESS_SWAP 0x00000001 diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 418c233075d3..ae691884d071 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -25,11 +25,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "i2c-designware-core.h" @@ -443,6 +445,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) { dev_err(dev->dev, "controller timed out\n"); /* i2c_dw_init implicitly disables the adapter */ + i2c_recover_bus(&dev->adapter); i2c_dw_init_master(dev); ret = -ETIMEDOUT; goto done; @@ -613,6 +616,56 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) return IRQ_HANDLED; } +static void i2c_dw_prepare_recovery(struct i2c_adapter *adap) +{ + struct dw_i2c_dev *dev = i2c_get_adapdata(adap); + + i2c_dw_disable(dev); + reset_control_assert(dev->rst); + i2c_dw_prepare_clk(dev, false); +} + +static void i2c_dw_unprepare_recovery(struct i2c_adapter *adap) +{ + struct dw_i2c_dev *dev = i2c_get_adapdata(adap); + + i2c_dw_prepare_clk(dev, true); + reset_control_deassert(dev->rst); + i2c_dw_init_master(dev); +} + +static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) +{ + struct i2c_bus_recovery_info *rinfo = &dev->rinfo; + struct i2c_adapter *adap = &dev->adapter; + struct gpio_desc *gpio; + int r; + + gpio = devm_gpiod_get(dev->dev, "scl", GPIOD_OUT_HIGH); + if (IS_ERR(gpio)) { + r = PTR_ERR(gpio); + if (r == -ENOENT) + return 0; + return r; + } + rinfo->scl_gpiod = gpio; + + gpio = devm_gpiod_get_optional(dev->dev, "sda", GPIOD_IN); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + rinfo->sda_gpiod = gpio; + + rinfo->recover_bus = i2c_generic_scl_recovery; + rinfo->prepare_recovery = i2c_dw_prepare_recovery; + rinfo->unprepare_recovery = i2c_dw_unprepare_recovery; + adap->bus_recovery_info = rinfo; + + dev_info(dev->dev, "running with gpio recovery mode! scl%s", + rinfo->sda_gpiod ? ",sda" : ""); + + return 0; +} + int i2c_dw_probe(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; @@ -652,6 +705,10 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) return ret; } + ret = i2c_dw_init_recovery_info(dev); + if (ret) + return ret; + /* * Increment PM usage count during adapter registration in order to * avoid possible spurious runtime suspend when adapter device is -- cgit v1.2.3 From ad36a27959cabb27dfde35ff103d03b22f6ddb36 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Thu, 2 Nov 2017 10:40:28 +0800 Subject: i2c: imx: switch to using gpiod for bus recovery gpios Change the driver to use the gpio descriptors for the bus recovery information instead of the deprecated integer interface. Reviewed-by: Andy Shevchenko Signed-off-by: Phil Reid Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index f96830ffd9f1..c4cf26571b66 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1006,26 +1006,26 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, PINCTRL_STATE_DEFAULT); i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl, "gpio"); - rinfo->sda_gpio = of_get_named_gpio(pdev->dev.of_node, "sda-gpios", 0); - rinfo->scl_gpio = of_get_named_gpio(pdev->dev.of_node, "scl-gpios", 0); + rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_OUT_HIGH); + rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_IN); - if (rinfo->sda_gpio == -EPROBE_DEFER || - rinfo->scl_gpio == -EPROBE_DEFER) { + if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER || + PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) { return -EPROBE_DEFER; - } else if (!gpio_is_valid(rinfo->sda_gpio) || - !gpio_is_valid(rinfo->scl_gpio) || + } else if (IS_ERR(rinfo->sda_gpiod) || + IS_ERR(rinfo->scl_gpiod) || IS_ERR(i2c_imx->pinctrl_pins_default) || IS_ERR(i2c_imx->pinctrl_pins_gpio)) { dev_dbg(&pdev->dev, "recovery information incomplete\n"); return 0; } - dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n", - rinfo->scl_gpio, rinfo->sda_gpio); + dev_dbg(&pdev->dev, "using scl%s for recovery\n", + rinfo->sda_gpiod ? ",sda" : ""); rinfo->prepare_recovery = i2c_imx_prepare_recovery; rinfo->unprepare_recovery = i2c_imx_unprepare_recovery; - rinfo->recover_bus = i2c_generic_gpio_recovery; + rinfo->recover_bus = i2c_generic_scl_recovery; i2c_imx->adapter.bus_recovery_info = rinfo; return 0; -- cgit v1.2.3 From cd2428c368a66c4d61cd416a4f0ad453ce6d57cd Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Thu, 2 Nov 2017 10:40:29 +0800 Subject: i2c: davinci: switch to using gpiod for bus recovery gpios Change the driver to use the gpio descriptors for the bus recovery information instead of the deprecated integer interface. Reviewed-by: Andy Shevchenko Signed-off-by: Phil Reid Reviewed-by: Sekhar Nori Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-davinci.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 2ead9b9eebb7..2afb12a89eb3 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -294,7 +294,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) } /* - * This routine does i2c bus recovery by using i2c_generic_gpio_recovery + * This routine does i2c bus recovery by using i2c_generic_scl_recovery * which is provided by I2C Bus recovery infrastructure. */ static void davinci_i2c_prepare_recovery(struct i2c_adapter *adap) @@ -316,7 +316,7 @@ static void davinci_i2c_unprepare_recovery(struct i2c_adapter *adap) } static struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = { - .recover_bus = i2c_generic_gpio_recovery, + .recover_bus = i2c_generic_scl_recovery, .prepare_recovery = davinci_i2c_prepare_recovery, .unprepare_recovery = davinci_i2c_unprepare_recovery, }; @@ -769,6 +769,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) struct davinci_i2c_dev *dev; struct i2c_adapter *adap; struct resource *mem; + struct i2c_bus_recovery_info *rinfo; int r, irq; irq = platform_get_irq(pdev, 0); @@ -869,9 +870,18 @@ static int davinci_i2c_probe(struct platform_device *pdev) if (dev->pdata->has_pfunc) adap->bus_recovery_info = &davinci_i2c_scl_recovery_info; else if (dev->pdata->scl_pin) { - adap->bus_recovery_info = &davinci_i2c_gpio_recovery_info; - adap->bus_recovery_info->scl_gpio = dev->pdata->scl_pin; - adap->bus_recovery_info->sda_gpio = dev->pdata->sda_pin; + rinfo = &davinci_i2c_gpio_recovery_info; + adap->bus_recovery_info = rinfo; + r = gpio_request_one(dev->pdata->scl_pin, GPIOF_OPEN_DRAIN | + GPIOF_OUT_INIT_HIGH, "i2c-scl"); + if (r) + goto err_unuse_clocks; + rinfo->scl_gpiod = gpio_to_desc(dev->pdata->scl_pin); + + r = gpio_request_one(dev->pdata->sda_pin, GPIOF_IN, "i2c-sda"); + if (r) + goto err_unuse_clocks; + rinfo->sda_gpiod = gpio_to_desc(dev->pdata->scl_pin); } adap->nr = pdev->id; -- cgit v1.2.3 From e1eb7d28c0753ec3e5ff9dce7880c243ffdfd4b3 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Thu, 2 Nov 2017 10:40:30 +0800 Subject: i2c: remove legacy integer scl/sda gpio for recovery Remove all reference to code related to using integer based ids for scl/sda gpio for bus recovery. All in tree drivers are now using the gpio descriptors to specific the required gpios. Reviewed-by: Andy Shevchenko Signed-off-by: Phil Reid Reviewed-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 78 ++------------------------------------------- include/linux/i2c.h | 7 +--- 2 files changed, 3 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index fdc6a9d1394e..54ffc8da40df 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -147,46 +147,6 @@ static int get_sda_gpio_value(struct i2c_adapter *adap) return gpiod_get_value_cansleep(adap->bus_recovery_info->sda_gpiod); } -static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap) -{ - struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; - struct device *dev = &adap->dev; - int ret = 0; - - ret = gpio_request_one(bri->scl_gpio, GPIOF_OPEN_DRAIN | - GPIOF_OUT_INIT_HIGH, "i2c-scl"); - if (ret) { - dev_warn(dev, "Can't get SCL gpio: %d\n", bri->scl_gpio); - return ret; - } - bri->scl_gpiod = gpio_to_desc(bri->scl_gpio); - - if (bri->get_sda) { - if (gpio_request_one(bri->sda_gpio, GPIOF_IN, "i2c-sda")) { - /* work without SDA polling */ - dev_warn(dev, "Can't get SDA gpio: %d. Not using SDA polling\n", - bri->sda_gpio); - bri->get_sda = NULL; - } - bri->sda_gpiod = gpio_to_desc(bri->sda_gpio); - } - - return ret; -} - -static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap) -{ - struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; - - if (bri->get_sda) { - gpio_free(bri->sda_gpio); - bri->sda_gpiod = NULL; - } - - gpio_free(bri->scl_gpio); - bri->scl_gpiod = NULL; -} - /* * We are generating clock pulses. ndelay() determines durating of clk pulses. * We will generate clock with rate 100 KHz and so duration of both clock levels @@ -195,7 +155,7 @@ static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap) #define RECOVERY_NDELAY 5000 #define RECOVERY_CLK_CNT 9 -static int i2c_generic_recovery(struct i2c_adapter *adap) +int i2c_generic_scl_recovery(struct i2c_adapter *adap) { struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; int i = 0, val = 1, ret = 0; @@ -237,28 +197,8 @@ static int i2c_generic_recovery(struct i2c_adapter *adap) return ret; } - -int i2c_generic_scl_recovery(struct i2c_adapter *adap) -{ - return i2c_generic_recovery(adap); -} EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery); -int i2c_generic_gpio_recovery(struct i2c_adapter *adap) -{ - int ret; - - ret = i2c_get_gpios_for_recovery(adap); - if (ret) - return ret; - - ret = i2c_generic_recovery(adap); - i2c_put_gpios_for_recovery(adap); - - return ret; -} -EXPORT_SYMBOL_GPL(i2c_generic_gpio_recovery); - int i2c_recover_bus(struct i2c_adapter *adap) { if (!adap->bus_recovery_info) @@ -290,21 +230,7 @@ static void i2c_init_recovery(struct i2c_adapter *adap) return; } - /* Generic GPIO recovery */ - if (bri->recover_bus == i2c_generic_gpio_recovery) { - if (!gpio_is_valid(bri->scl_gpio)) { - err_str = "invalid SCL gpio"; - goto err; - } - - if (gpio_is_valid(bri->sda_gpio)) - bri->get_sda = get_sda_gpio_value; - else - bri->get_sda = NULL; - - bri->get_scl = get_scl_gpio_value; - bri->set_scl = set_scl_gpio_value; - } else if (bri->recover_bus == i2c_generic_scl_recovery) { + if (bri->recover_bus == i2c_generic_scl_recovery) { /* Generic SCL recovery */ if (!bri->set_scl || !bri->get_scl) { err_str = "no {get|set}_scl() found"; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index bf62c4a97a09..a556db976fc6 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -485,7 +485,7 @@ struct i2c_timings { /** * struct i2c_bus_recovery_info - I2C bus recovery information * @recover_bus: Recover routine. Either pass driver's recover_bus() routine, or - * i2c_generic_scl_recovery() or i2c_generic_gpio_recovery(). + * i2c_generic_scl_recovery(). * @get_scl: This gets current value of SCL line. Mandatory for generic SCL * recovery. Used internally for generic GPIO recovery. * @set_scl: This sets/clears SCL line. Mandatory for generic SCL recovery. Used @@ -497,8 +497,6 @@ struct i2c_timings { * configure padmux here for SDA/SCL line or something else they want. * @unprepare_recovery: This will be called after completing recovery. Platform * may configure padmux here for SDA/SCL line or something else they want. - * @scl_gpio: gpio number of the SCL line. Only required for GPIO recovery. - * @sda_gpio: gpio number of the SDA line. Only required for GPIO recovery. * @scl_gpiod: gpiod of the SCL line. Only required for GPIO recovery. * @sda_gpiod: gpiod of the SDA line. Only required for GPIO recovery. */ @@ -513,8 +511,6 @@ struct i2c_bus_recovery_info { void (*unprepare_recovery)(struct i2c_adapter *); /* gpio recovery */ - int scl_gpio; - int sda_gpio; struct gpio_desc *scl_gpiod; struct gpio_desc *sda_gpiod; }; @@ -522,7 +518,6 @@ struct i2c_bus_recovery_info { int i2c_recover_bus(struct i2c_adapter *adap); /* Generic recovery routines */ -int i2c_generic_gpio_recovery(struct i2c_adapter *adap); int i2c_generic_scl_recovery(struct i2c_adapter *adap); /** -- cgit v1.2.3 From f289800af1fd4379403f2630e7e9420401a4cd8e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 2 Nov 2017 13:47:27 +0100 Subject: i2c: sh_mobile: remove redundant initialization Following the documentation, we initialize the HW before each START in start_ch(). No need to do the same in activate_ch(). Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index c03acdf71397..0ac152586e74 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -303,16 +303,6 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) /* Wake up device and enable clock */ pm_runtime_get_sync(pd->dev); clk_prepare_enable(pd->clk); - - /* Enable channel and configure rx ack */ - iic_set_clr(pd, ICCR, ICCR_ICE, 0); - - /* Mask all interrupts */ - iic_wr(pd, ICIC, 0); - - /* Set the clock */ - iic_wr(pd, ICCL, pd->iccl & 0xff); - iic_wr(pd, ICCH, pd->icch & 0xff); } static void deactivate_ch(struct sh_mobile_i2c_data *pd) -- cgit v1.2.3 From 3f3a513985ce55d69922cc9b5a0e095432cdfbc4 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 2 Nov 2017 13:47:28 +0100 Subject: i2c: sh_mobile: remove redundant deinitialization No need to clear the interrupt registers because right after that we disable the IP core which will reload registers with their initial values anyhow. Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 0ac152586e74..cbaed24fb18f 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -307,10 +307,6 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) static void deactivate_ch(struct sh_mobile_i2c_data *pd) { - /* Clear/disable interrupts */ - iic_wr(pd, ICSR, 0); - iic_wr(pd, ICIC, 0); - /* Disable channel */ iic_set_clr(pd, ICCR, 0, ICCR_ICE); -- cgit v1.2.3 From 91a5e63e3f9879e5030064a3c0d23c3777c4f4d0 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 2 Nov 2017 13:47:29 +0100 Subject: i2c: sh_mobile: manually "inline" two short functions Those two functions are very short and only called once. The code becomes easier to understand if the code is directly put into the main xfer function. Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index cbaed24fb18f..02c2912bebb4 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -298,23 +298,6 @@ static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd) return 0; } -static void activate_ch(struct sh_mobile_i2c_data *pd) -{ - /* Wake up device and enable clock */ - pm_runtime_get_sync(pd->dev); - clk_prepare_enable(pd->clk); -} - -static void deactivate_ch(struct sh_mobile_i2c_data *pd) -{ - /* Disable channel */ - iic_set_clr(pd, ICCR, 0, ICCR_ICE); - - /* Disable clock and mark device as idle */ - clk_disable_unprepare(pd->clk); - pm_runtime_put_sync(pd->dev); -} - static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op op, unsigned char data) { @@ -717,7 +700,9 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, int i; long timeout; - activate_ch(pd); + /* Wake up device and enable clock */ + pm_runtime_get_sync(pd->dev); + clk_prepare_enable(pd->clk); /* Process all messages */ for (i = 0; i < num; i++) { @@ -754,7 +739,12 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, break; } - deactivate_ch(pd); + /* Disable channel */ + iic_set_clr(pd, ICCR, 0, ICCR_ICE); + + /* Disable clock and mark device as idle */ + clk_disable_unprepare(pd->clk); + pm_runtime_put_sync(pd->dev); if (!err) err = num; -- cgit v1.2.3 From 832a522a3ef5e96b517163ee7d4c249545d88626 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 2 Nov 2017 13:47:30 +0100 Subject: i2c: sh_mobile: use direct writes when accessing ICE bit ICE bit is for resetting the module. Other bits don't matter then, so we don't need to use the iic_set_clr() function but can use iic_wr(). Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 02c2912bebb4..72c9483db769 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -620,10 +620,10 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg, if (do_init) { /* Initialize channel registers */ - iic_set_clr(pd, ICCR, 0, ICCR_ICE); + iic_wr(pd, ICCR, 0); /* Enable channel and configure rx ack */ - iic_set_clr(pd, ICCR, ICCR_ICE, 0); + iic_wr(pd, ICCR, ICCR_ICE); /* Set the clock */ iic_wr(pd, ICCL, pd->iccl & 0xff); @@ -740,7 +740,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, } /* Disable channel */ - iic_set_clr(pd, ICCR, 0, ICCR_ICE); + iic_wr(pd, ICCR, 0); /* Disable clock and mark device as idle */ clk_disable_unprepare(pd->clk); -- cgit v1.2.3 From a4d16493be406273320f152814c33ccdb17dcf91 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 2 Nov 2017 13:47:31 +0100 Subject: i2c: sh_mobile: shorten exit of xfer routine We can use the ternary operator for easier reading. Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 72c9483db769..ebd146ccb244 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -746,9 +746,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, clk_disable_unprepare(pd->clk); pm_runtime_put_sync(pd->dev); - if (!err) - err = num; - return err; + return err ?: num; } static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter) -- cgit v1.2.3 From 91701ae85dff9703335b5912673df75f4b6f4c53 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 8 Nov 2017 09:50:37 +0100 Subject: i2c: sh_mobile: let RuntimePM do the clock handling No need to do it manually. Reported-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang Tested-by: Jacopo Mondi Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index ebd146ccb244..80561ffbcf7b 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -702,7 +702,6 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, /* Wake up device and enable clock */ pm_runtime_get_sync(pd->dev); - clk_prepare_enable(pd->clk); /* Process all messages */ for (i = 0; i < num; i++) { @@ -743,7 +742,6 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, iic_wr(pd, ICCR, 0); /* Disable clock and mark device as idle */ - clk_disable_unprepare(pd->clk); pm_runtime_put_sync(pd->dev); return err ?: num; -- cgit v1.2.3 From 2967f9ca8b0dc8d924e0f14c55d1e73d9c6c4975 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 9 Nov 2017 23:20:53 +0100 Subject: i2c: sh_mobile: avoid unnecessary register read There is no data when the first WAIT interrupt arrives. No need to read something then. Signed-off-by: Wolfram Sang Tested-by: Jacopo Mondi Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 80561ffbcf7b..40a66d466c3c 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -433,8 +433,9 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd) break; } data = i2c_op(pd, OP_RX_STOP_DATA, 0); - } else + } else if (real_pos >= 0) { data = i2c_op(pd, OP_RX, 0); + } if (real_pos >= 0) pd->msg->buf[real_pos] = data; -- cgit v1.2.3 From a4fde7e5c9d6432ba863ee53debf27f10b370678 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 10 Nov 2017 12:52:10 +0100 Subject: i2c: sh_mobile: send STOP according to datasheet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We initiate STOP (or REP_START) on the second last WAIT interrupt currently. This works fine but is not according to the datasheet which says to do it on the last WAIT interrupt. This also simplifies the code quite a lot, so let's do it. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Tested-by: Jacopo Mondi Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 40a66d466c3c..c904be631db3 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -40,21 +40,21 @@ /* BUS: S A8 ACK P(*) */ /* IRQ: DTE WAIT */ /* ICIC: */ -/* ICCR: 0x94 0x90 */ +/* ICCR: 0x94 0x90 */ /* ICDR: A8 */ /* */ /* 1 byte transmit */ /* BUS: S A8 ACK D8(1) ACK P(*) */ /* IRQ: DTE WAIT WAIT */ /* ICIC: -DTE */ -/* ICCR: 0x94 0x90 */ +/* ICCR: 0x94 0x90 */ /* ICDR: A8 D8(1) */ /* */ /* 2 byte transmit */ /* BUS: S A8 ACK D8(1) ACK D8(2) ACK P(*) */ /* IRQ: DTE WAIT WAIT WAIT */ /* ICIC: -DTE */ -/* ICCR: 0x94 0x90 */ +/* ICCR: 0x94 0x90 */ /* ICDR: A8 D8(1) D8(2) */ /* */ /* 3 bytes or more, +---------+ gets repeated */ @@ -113,7 +113,6 @@ enum sh_mobile_i2c_op { OP_TX_FIRST, OP_TX, OP_TX_STOP, - OP_TX_STOP_DATA, OP_TX_TO_RX, OP_RX, OP_RX_STOP, @@ -319,10 +318,7 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, case OP_TX: /* write data */ iic_wr(pd, ICDR, data); break; - case OP_TX_STOP_DATA: /* write data and issue a stop afterwards */ - iic_wr(pd, ICDR, data); - /* fallthrough */ - case OP_TX_STOP: /* issue a stop */ + case OP_TX_STOP: /* issue a stop (or rep_start) */ iic_wr(pd, ICCR, pd->send_stop ? ICCR_ICE | ICCR_TRS : ICCR_ICE | ICCR_TRS | ICCR_BBSY); break; @@ -356,11 +352,6 @@ static bool sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd) return pd->pos == -1; } -static bool sh_mobile_i2c_is_last_byte(struct sh_mobile_i2c_data *pd) -{ - return pd->pos == pd->msg->len - 1; -} - static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd, unsigned char *buf) { @@ -378,20 +369,12 @@ static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd) unsigned char data; if (pd->pos == pd->msg->len) { - /* Send stop if we haven't yet (DMA case) */ - if (pd->send_stop && pd->stop_after_dma) - i2c_op(pd, OP_TX_STOP, 0); + i2c_op(pd, OP_TX_STOP, 0); return 1; } sh_mobile_i2c_get_data(pd, &data); - - if (sh_mobile_i2c_is_last_byte(pd)) - i2c_op(pd, OP_TX_STOP_DATA, data); - else if (sh_mobile_i2c_is_first_byte(pd)) - i2c_op(pd, OP_TX_FIRST, data); - else - i2c_op(pd, OP_TX, data); + i2c_op(pd, sh_mobile_i2c_is_first_byte(pd) ? OP_TX_FIRST : OP_TX, data); pd->pos++; return 0; -- cgit v1.2.3 From 4ed152c4daf32d2cd4a5285f3aaca3a4c89a31fb Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 15 Nov 2017 15:32:21 +0100 Subject: i2c: sh_mobile: make sure to not accidently trigger STOP The datasheet was a bit vague, but after consultation with HW designers, we came to the conclusion that we should set the SCP bit always when dealing only with the ICE bit. A set SCP bit is ignored, and thus fine, a cleared one may trigger STOP on the bus. Signed-off-by: Wolfram Sang Tested-by: Jacopo Mondi Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index c904be631db3..bc1605a31534 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -604,10 +604,10 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg, if (do_init) { /* Initialize channel registers */ - iic_wr(pd, ICCR, 0); + iic_wr(pd, ICCR, ICCR_SCP); /* Enable channel and configure rx ack */ - iic_wr(pd, ICCR, ICCR_ICE); + iic_wr(pd, ICCR, ICCR_ICE | ICCR_SCP); /* Set the clock */ iic_wr(pd, ICCL, pd->iccl & 0xff); @@ -723,7 +723,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, } /* Disable channel */ - iic_wr(pd, ICCR, 0); + iic_wr(pd, ICCR, ICCR_SCP); /* Disable clock and mark device as idle */ pm_runtime_put_sync(pd->dev); -- cgit v1.2.3 From e6c8adca20ba459dd88057ca74232bf9f1045075 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 3 Jul 2017 22:25:56 -0400 Subject: anntotate the places where ->poll() return values go Signed-off-by: Al Viro --- drivers/media/platform/soc_camera/soc_camera.c | 2 +- drivers/media/v4l2-core/v4l2-dev.c | 2 +- drivers/staging/comedi/drivers/serial2002.c | 2 +- drivers/tty/tty_io.c | 2 +- drivers/vfio/virqfd.c | 2 +- drivers/vhost/vhost.c | 4 ++-- fs/debugfs/file.c | 2 +- fs/proc/inode.c | 2 +- fs/select.c | 5 +++-- net/smc/af_smc.c | 2 +- net/socket.c | 2 +- virt/kvm/eventfd.c | 2 +- 12 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 916ff68b73d4..f805f45716a3 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -809,7 +809,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) { struct soc_camera_device *icd = file->private_data; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - unsigned res = POLLERR; + __poll_t res = POLLERR; if (icd->streamer != file) return POLLERR; diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index c647ba648805..ef178edc634b 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -334,7 +334,7 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) { struct video_device *vdev = video_devdata(filp); - unsigned int res = POLLERR | POLLHUP; + __poll_t res = POLLERR | POLLHUP; if (!vdev->fops->poll) return DEFAULT_POLLMASK; diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index cc18e25103ca..a557be8a5076 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -119,7 +119,7 @@ static void serial2002_tty_read_poll_wait(struct file *f, int timeout) poll_initwait(&table); while (1) { long elapsed; - int mask; + __poll_t mask; mask = f->f_op->poll(f, &table.pt); if (mask & (POLLRDNORM | POLLRDBAND | POLLIN | diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index dc60aeea87d8..287f9a4eef6d 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2059,7 +2059,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) { struct tty_struct *tty = file_tty(filp); struct tty_ldisc *ld; - int ret = 0; + __poll_t ret = 0; if (tty_paranoia_check(tty, file_inode(filp), "tty_poll")) return 0; diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c index 4797217e5e72..d18b10ff119e 100644 --- a/drivers/vfio/virqfd.c +++ b/drivers/vfio/virqfd.c @@ -113,7 +113,7 @@ int vfio_virqfd_enable(void *opaque, struct eventfd_ctx *ctx; struct virqfd *virqfd; int ret = 0; - unsigned int events; + __poll_t events; virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL); if (!virqfd) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 33ac2b186b85..c18e70bd0466 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -203,7 +203,7 @@ EXPORT_SYMBOL_GPL(vhost_poll_init); * keep a reference to a file until after vhost_poll_stop is called. */ int vhost_poll_start(struct vhost_poll *poll, struct file *file) { - unsigned long mask; + __poll_t mask; int ret = 0; if (poll->wqh) @@ -211,7 +211,7 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file) mask = file->f_op->poll(file, &poll->table); if (mask) - vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); + vhost_poll_wakeup(&poll->wait, 0, 0, (void *)(uintptr_t)mask); if (mask & POLLERR) { if (poll->wqh) remove_wait_queue(poll->wqh, &poll->wait); diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index cd12e6576b48..2571404a072b 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -210,7 +210,7 @@ static unsigned int full_proxy_poll(struct file *filp, struct poll_table_struct *wait) { struct dentry *dentry = F_DENTRY(filp); - unsigned int r = 0; + __poll_t r = 0; const struct file_operations *real_fops; if (debugfs_file_get(dentry)) diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 44e37f38493b..149fd4d75db6 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -237,7 +237,7 @@ static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts) { struct proc_dir_entry *pde = PDE(file_inode(file)); - unsigned int rv = DEFAULT_POLLMASK; + __poll_t rv = DEFAULT_POLLMASK; __poll_t (*poll)(struct file *, struct poll_table_struct *); if (use_pde(pde)) { poll = pde->proc_fops->poll; diff --git a/fs/select.c b/fs/select.c index 6de493bb42a4..b2bf84be5056 100644 --- a/fs/select.c +++ b/fs/select.c @@ -484,8 +484,9 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time) rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; for (i = 0; i < n; ++rinp, ++routp, ++rexp) { - unsigned long in, out, ex, all_bits, bit = 1, mask, j; + unsigned long in, out, ex, all_bits, bit = 1, j; unsigned long res_in = 0, res_out = 0, res_ex = 0; + __poll_t mask; in = *inp++; out = *outp++; ex = *exp++; all_bits = in | out | ex; @@ -806,7 +807,7 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait, bool *can_busy_poll, unsigned int busy_flag) { - unsigned int mask; + __poll_t mask; int fd; mask = 0; diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 6451c5013e06..ae59826230be 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -1130,7 +1130,7 @@ static unsigned int smc_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - unsigned int mask = 0; + __poll_t mask = 0; struct smc_sock *smc; int rc; diff --git a/net/socket.c b/net/socket.c index 42d8e9c9ccd5..dceab22a41fd 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1093,7 +1093,7 @@ EXPORT_SYMBOL(sock_create_lite); /* No kernel lock held - perfect */ static unsigned int sock_poll(struct file *file, poll_table *wait) { - unsigned int busy_flag = 0; + __poll_t busy_flag = 0; struct socket *sock; /* diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index f2ac53ab8243..a1f68ed999d8 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -287,7 +287,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) struct fd f; struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL; int ret; - unsigned int events; + __poll_t events; int idx; if (!kvm_arch_intc_initialized(kvm)) -- cgit v1.2.3 From 3ad6f93e98d6df25d0667d847d3ab9cbdccb3eae Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 3 Jul 2017 20:14:56 -0400 Subject: annotate poll-related wait keys __poll_t is also used as wait key in some waitqueues. Verify that wait_..._poll() gets __poll_t as key and provide a helper for wakeup functions to get back to that __poll_t value. Signed-off-by: Al Viro --- drivers/vfio/virqfd.c | 2 +- drivers/vhost/vhost.c | 4 ++-- fs/eventpoll.c | 9 +++++---- fs/select.c | 2 +- include/linux/wait.h | 10 ++++++---- mm/memcontrol.c | 2 +- net/core/datagram.c | 4 +--- net/unix/af_unix.c | 2 +- virt/kvm/eventfd.c | 2 +- 9 files changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c index d18b10ff119e..8cc4b48ff127 100644 --- a/drivers/vfio/virqfd.c +++ b/drivers/vfio/virqfd.c @@ -46,7 +46,7 @@ static void virqfd_deactivate(struct virqfd *virqfd) static int virqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) { struct virqfd *virqfd = container_of(wait, struct virqfd, wait); - unsigned long flags = (unsigned long)key; + __poll_t flags = key_to_poll(key); if (flags & POLLIN) { /* An event has been signaled, call function */ diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c18e70bd0466..7aad77be0b46 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -170,7 +170,7 @@ static int vhost_poll_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, { struct vhost_poll *poll = container_of(wait, struct vhost_poll, wait); - if (!((unsigned long)key & poll->mask)) + if (!(key_to_poll(key) & poll->mask)) return 0; vhost_poll_queue(poll); @@ -211,7 +211,7 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file) mask = file->f_op->poll(file, &poll->table); if (mask) - vhost_poll_wakeup(&poll->wait, 0, 0, (void *)(uintptr_t)mask); + vhost_poll_wakeup(&poll->wait, 0, 0, poll_to_key(mask)); if (mask & POLLERR) { if (poll->wqh) remove_wait_queue(poll->wqh, &poll->wait); diff --git a/fs/eventpoll.c b/fs/eventpoll.c index afd548ebc328..21e6fee00e8b 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1117,6 +1117,7 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v unsigned long flags; struct epitem *epi = ep_item_from_wait(wait); struct eventpoll *ep = epi->ep; + __poll_t pollflags = key_to_poll(key); int ewake = 0; spin_lock_irqsave(&ep->lock, flags); @@ -1138,7 +1139,7 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v * callback. We need to be able to handle both cases here, hence the * test for "key" != NULL before the event match test. */ - if (key && !((unsigned long) key & epi->event.events)) + if (pollflags && !(pollflags & epi->event.events)) goto out_unlock; /* @@ -1175,8 +1176,8 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v */ if (waitqueue_active(&ep->wq)) { if ((epi->event.events & EPOLLEXCLUSIVE) && - !((unsigned long)key & POLLFREE)) { - switch ((unsigned long)key & EPOLLINOUT_BITS) { + !(pollflags & POLLFREE)) { + switch (pollflags & EPOLLINOUT_BITS) { case POLLIN: if (epi->event.events & POLLIN) ewake = 1; @@ -1205,7 +1206,7 @@ out_unlock: if (!(epi->event.events & EPOLLEXCLUSIVE)) ewake = 1; - if ((unsigned long)key & POLLFREE) { + if (pollflags & POLLFREE) { /* * If we race with ep_remove_wait_queue() it can miss * ->whead = NULL and do another remove_wait_queue() after diff --git a/fs/select.c b/fs/select.c index b2bf84be5056..ffc16fd3673e 100644 --- a/fs/select.c +++ b/fs/select.c @@ -212,7 +212,7 @@ static int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key struct poll_table_entry *entry; entry = container_of(wait, struct poll_table_entry, wait); - if (key && !((unsigned long)key & entry->key)) + if (key && !(key_to_poll(key) & entry->key)) return 0; return __pollwake(wait, mode, sync, key); } diff --git a/include/linux/wait.h b/include/linux/wait.h index 158715445ffb..55a611486bac 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -206,14 +206,16 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode, int nr); /* * Wakeup macros to be used to report events to the targets. */ +#define poll_to_key(m) ((void *)(__force uintptr_t)(__poll_t)(m)) +#define key_to_poll(m) ((__force __poll_t)(uintptr_t)(void *)(m)) #define wake_up_poll(x, m) \ - __wake_up(x, TASK_NORMAL, 1, (void *) (m)) + __wake_up(x, TASK_NORMAL, 1, poll_to_key(m)) #define wake_up_locked_poll(x, m) \ - __wake_up_locked_key((x), TASK_NORMAL, (void *) (m)) + __wake_up_locked_key((x), TASK_NORMAL, poll_to_key(m)) #define wake_up_interruptible_poll(x, m) \ - __wake_up(x, TASK_INTERRUPTIBLE, 1, (void *) (m)) + __wake_up(x, TASK_INTERRUPTIBLE, 1, poll_to_key(m)) #define wake_up_interruptible_sync_poll(x, m) \ - __wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, (void *) (m)) + __wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, poll_to_key(m)) #define ___wait_cond_timeout(condition) \ ({ \ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 50e6906314f8..006aa27f4fb4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3777,7 +3777,7 @@ static int memcg_event_wake(wait_queue_entry_t *wait, unsigned mode, struct mem_cgroup_event *event = container_of(wait, struct mem_cgroup_event, wait); struct mem_cgroup *memcg = event->memcg; - unsigned long flags = (unsigned long)key; + __poll_t flags = key_to_poll(key); if (flags & POLLHUP) { /* diff --git a/net/core/datagram.c b/net/core/datagram.c index 522873ed120b..000da13c01f2 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -72,12 +72,10 @@ static inline int connection_based(struct sock *sk) static int receiver_wake_function(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key) { - unsigned long bits = (unsigned long)key; - /* * Avoid a wakeup if event not interesting for us */ - if (bits && !(bits & (POLLIN | POLLERR))) + if (key && !(key_to_poll(key) & (POLLIN | POLLERR))) return 0; return autoremove_wake_function(wait, mode, sync, key); } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index a9ee634f3c42..72957961ac22 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -367,7 +367,7 @@ static int unix_dgram_peer_wake_relay(wait_queue_entry_t *q, unsigned mode, int /* relaying can only happen while the wq still exists */ u_sleep = sk_sleep(&u->sk); if (u_sleep) - wake_up_interruptible_poll(u_sleep, key); + wake_up_interruptible_poll(u_sleep, key_to_poll(key)); return 0; } diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index a1f68ed999d8..a334399fafec 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -188,7 +188,7 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) { struct kvm_kernel_irqfd *irqfd = container_of(wait, struct kvm_kernel_irqfd, wait); - unsigned long flags = (unsigned long)key; + __poll_t flags = key_to_poll(key); struct kvm_kernel_irq_routing_entry irq; struct kvm *kvm = irqfd->kvm; unsigned seq; -- cgit v1.2.3 From 01699437758328090813212ecefe3ab6f0d5b9cc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 3 Jul 2017 03:14:15 -0400 Subject: annotate poll_table_struct ->_key Only POLL... bitmaps ever end up there and their only use is checking for POLL... bits in them. Signed-off-by: Al Viro --- drivers/dma-buf/dma-buf.c | 2 +- drivers/media/pci/bt8xx/bttv-driver.c | 4 ++-- drivers/media/pci/cx18/cx18-fileops.c | 2 +- drivers/media/pci/ivtv/ivtv-fileops.c | 2 +- drivers/media/pci/saa7164/saa7164-encoder.c | 2 +- drivers/media/platform/fsl-viu.c | 2 +- drivers/media/radio/radio-cadet.c | 2 +- drivers/media/radio/radio-si476x.c | 2 +- drivers/media/radio/si470x/radio-si470x-common.c | 2 +- drivers/media/usb/cx231xx/cx231xx-417.c | 2 +- drivers/media/usb/cx231xx/cx231xx-video.c | 2 +- drivers/media/usb/gspca/gspca.c | 2 +- drivers/media/usb/hdpvr/hdpvr-video.c | 2 +- drivers/media/usb/tm6000/tm6000-video.c | 2 +- drivers/media/v4l2-core/v4l2-mem2mem.c | 2 +- drivers/media/v4l2-core/videobuf-core.c | 2 +- drivers/media/v4l2-core/videobuf2-core.c | 2 +- drivers/media/v4l2-core/videobuf2-v4l2.c | 2 +- drivers/misc/mei/main.c | 2 +- fs/select.c | 4 ++-- include/linux/poll.h | 8 ++++---- 21 files changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index bc1cb284111c..4f313593caf5 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -163,7 +163,7 @@ static unsigned int dma_buf_poll(struct file *file, poll_table *poll) struct reservation_object *resv; struct reservation_object_list *fobj; struct dma_fence *fence_excl; - unsigned long events; + __poll_t events; unsigned shared_count, seq; dmabuf = file->private_data; diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index b366a7e1d976..721f586c0394 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -2961,7 +2961,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) struct bttv_buffer *buf; enum v4l2_field field; unsigned int rc = 0; - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); if (v4l2_event_pending(&fh->fh)) rc = POLLPRI; @@ -3333,7 +3333,7 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct saa6588_command cmd; unsigned int res = 0; diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c index 4f9c2395941b..55130d5abffd 100644 --- a/drivers/media/pci/cx18/cx18-fileops.c +++ b/drivers/media/pci/cx18/cx18-fileops.c @@ -604,7 +604,7 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count, unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct cx18_open_id *id = file2id(filp); struct cx18 *cx = id->cx; struct cx18_stream *s = &cx->streams[id->type]; diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c index c9bd018e53de..22217ef30bd6 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.c +++ b/drivers/media/pci/ivtv/ivtv-fileops.c @@ -766,7 +766,7 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index f21c245a54f7..ab75e5e19884 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -911,7 +911,7 @@ err: static unsigned int fops_poll(struct file *file, poll_table *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct saa7164_encoder_fh *fh = (struct saa7164_encoder_fh *)file->private_data; struct saa7164_port *port = fh->port; diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index dba21215dc84..1e9c1f05d057 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -1268,7 +1268,7 @@ static unsigned int viu_poll(struct file *file, struct poll_table_struct *wait) struct viu_fh *fh = file->private_data; struct videobuf_queue *q = &fh->vb_vidq; struct viu_dev *dev = fh->dev; - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); unsigned int res = v4l2_ctrl_poll(file, wait); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 7575e5370a49..7a6b3efefedb 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -484,7 +484,7 @@ static int cadet_release(struct file *file) static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait) { struct cadet *dev = video_drvdata(file); - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); unsigned int res = v4l2_ctrl_poll(file, wait); poll_wait(file, &dev->read_queue, wait); diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 271f725b17e8..fc1bcda38c69 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -1153,7 +1153,7 @@ static unsigned int si476x_radio_fops_poll(struct file *file, struct poll_table_struct *pts) { struct si476x_radio *radio = video_drvdata(file); - unsigned long req_events = poll_requested_events(pts); + __poll_t req_events = poll_requested_events(pts); unsigned int err = v4l2_ctrl_poll(file, pts); if (req_events & (POLLIN | POLLRDNORM)) { diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index c89a7d5b8c55..b430bbc475fe 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -511,7 +511,7 @@ static unsigned int si470x_fops_poll(struct file *file, struct poll_table_struct *pts) { struct si470x_device *radio = video_drvdata(file); - unsigned long req_events = poll_requested_events(pts); + __poll_t req_events = poll_requested_events(pts); int retval = v4l2_ctrl_poll(file, pts); if (req_events & (POLLIN | POLLRDNORM)) { diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index d538fa407742..80231bdee366 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1815,7 +1815,7 @@ static ssize_t mpeg_read(struct file *file, char __user *data, static unsigned int mpeg_poll(struct file *file, struct poll_table_struct *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct cx231xx_fh *fh = file->private_data; struct cx231xx *dev = fh->dev; unsigned int res = 0; diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 226059fc672b..3c11ed45d679 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -2008,7 +2008,7 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, */ static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct cx231xx_fh *fh = filp->private_data; struct cx231xx *dev = fh->dev; unsigned res = 0; diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 961343873fd0..8ebf96f9a3a2 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1865,7 +1865,7 @@ out: static unsigned int dev_poll(struct file *file, poll_table *wait) { struct gspca_dev *gspca_dev = video_drvdata(file); - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); int ret = 0; PDEBUG(D_FRAM, "poll"); diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 7fb036d6a86e..35f8a834c76c 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -523,7 +523,7 @@ err: static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct hdpvr_buffer *buf = NULL; struct hdpvr_device *dev = video_drvdata(filp); unsigned int mask = v4l2_ctrl_poll(filp, wait); diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index 9fa25de6b5a9..16c9dcf3f2cb 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -1426,7 +1426,7 @@ tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) static unsigned int __tm6000_poll(struct file *file, struct poll_table_struct *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct tm6000_fh *fh = file->private_data; struct tm6000_buffer *buf; int res = 0; diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index f62e68aa04c4..bc6b8f5953be 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -502,7 +502,7 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, struct poll_table_struct *wait) { struct video_device *vfd = video_devdata(file); - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct vb2_queue *src_q, *dst_q; struct vb2_buffer *src_vb = NULL, *dst_vb = NULL; unsigned int rc = 0; diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c index 1dbf6f7785bb..83918bfda167 100644 --- a/drivers/media/v4l2-core/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c @@ -1122,7 +1122,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_queue *q, poll_table *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct videobuf_buffer *buf = NULL; unsigned int rc = 0; diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index cb115ba6a1d2..1a297aea084b 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2021,7 +2021,7 @@ EXPORT_SYMBOL_GPL(vb2_core_queue_release); unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file, poll_table *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct vb2_buffer *vb = NULL; unsigned long flags; diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index 0c0669976bdc..f7cdc66a06e1 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -674,7 +674,7 @@ EXPORT_SYMBOL_GPL(vb2_queue_release); unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) { struct video_device *vfd = video_devdata(file); - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); unsigned int res = 0; if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index e825f013e54e..4f704641c574 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -544,7 +544,7 @@ static long mei_compat_ioctl(struct file *file, */ static unsigned int mei_poll(struct file *file, poll_table *wait) { - unsigned long req_events = poll_requested_events(wait); + __poll_t req_events = poll_requested_events(wait); struct mei_cl *cl = file->private_data; struct mei_device *dev; unsigned int mask = 0; diff --git a/fs/select.c b/fs/select.c index ffc16fd3673e..8d6d47912134 100644 --- a/fs/select.c +++ b/fs/select.c @@ -438,7 +438,7 @@ get_max: static inline void wait_key_set(poll_table *wait, unsigned long in, unsigned long out, unsigned long bit, - unsigned int ll_flag) + __poll_t ll_flag) { wait->_key = POLLEX_SET | ll_flag; if (in & bit) @@ -454,7 +454,7 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time) poll_table *wait; int retval, i, timed_out = 0; u64 slack = 0; - unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; + __poll_t busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; unsigned long busy_start = 0; rcu_read_lock(); diff --git a/include/linux/poll.h b/include/linux/poll.h index d384f12abdd5..8927e2282633 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -37,7 +37,7 @@ typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_ */ typedef struct poll_table_struct { poll_queue_proc _qproc; - unsigned long _key; + __poll_t _key; } poll_table; static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) @@ -62,15 +62,15 @@ static inline bool poll_does_not_wait(const poll_table *p) * to be started implicitly on poll(). You typically only want to do that * if the application is actually polling for POLLIN and/or POLLOUT. */ -static inline unsigned long poll_requested_events(const poll_table *p) +static inline __poll_t poll_requested_events(const poll_table *p) { - return p ? p->_key : ~0UL; + return p ? p->_key : ~(__poll_t)0; } static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) { pt->_qproc = qproc; - pt->_key = ~0UL; /* all events enabled */ + pt->_key = ~(__poll_t)0; /* all events enabled */ } struct poll_table_entry { -- cgit v1.2.3 From 58e3b60298bc9feaf51481ea3e62884bd0146366 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 3 Jul 2017 23:50:40 -0400 Subject: vhost: annotate vhost_poll its ->mask is POLL... bitmap Signed-off-by: Al Viro --- drivers/vhost/vhost.c | 2 +- drivers/vhost/vhost.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 7aad77be0b46..7a897d2f2188 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(vhost_work_init); /* Init poll structure */ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, - unsigned long mask, struct vhost_dev *dev) + __poll_t mask, struct vhost_dev *dev) { init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup); init_poll_funcptr(&poll->table, vhost_poll_func); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 79c6e7a60a5e..d94245b2fcc2 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -34,7 +34,7 @@ struct vhost_poll { wait_queue_head_t *wqh; wait_queue_entry_t wait; struct vhost_work work; - unsigned long mask; + __poll_t mask; struct vhost_dev *dev; }; @@ -43,7 +43,7 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work); bool vhost_has_work(struct vhost_dev *dev); void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, - unsigned long mask, struct vhost_dev *dev); + __poll_t mask, struct vhost_dev *dev); int vhost_poll_start(struct vhost_poll *poll, struct file *file); void vhost_poll_stop(struct vhost_poll *poll); void vhost_poll_flush(struct vhost_poll *poll); -- cgit v1.2.3 From 0d9b87f3ba71eef698ea69ef111b8ba35af8b318 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 2 Jul 2017 23:05:29 -0400 Subject: acpi: annotate ->poll() instances Signed-off-by: Al Viro --- drivers/acpi/acpi_dbg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_dbg.c b/drivers/acpi/acpi_dbg.c index 3ec05aa1a903..2ff5c8c04e3b 100644 --- a/drivers/acpi/acpi_dbg.c +++ b/drivers/acpi/acpi_dbg.c @@ -718,9 +718,9 @@ again: return size > 0 ? size : ret; } -static unsigned int acpi_aml_poll(struct file *file, poll_table *wait) +static __poll_t acpi_aml_poll(struct file *file, poll_table *wait) { - int masks = 0; + __poll_t masks = 0; poll_wait(file, &acpi_aml_io.wait, wait); if (acpi_aml_user_readable()) -- cgit v1.2.3 From ade994f4f6c8c3ef4c3bfc2d02166262fb9d089c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 3 Jul 2017 00:01:49 -0400 Subject: net: annotate ->poll() instances Signed-off-by: Al Viro --- drivers/staging/irda/net/af_irda.c | 4 ++-- drivers/staging/irda/net/irnet/irnet_ppp.c | 8 ++++---- drivers/staging/irda/net/irnet/irnet_ppp.h | 2 +- include/linux/skbuff.h | 2 +- include/net/bluetooth/bluetooth.h | 2 +- include/net/inet_connection_sock.h | 2 +- include/net/iucv/af_iucv.h | 2 +- include/net/sctp/sctp.h | 2 +- include/net/sock.h | 2 +- include/net/tcp.h | 2 +- include/net/udp.h | 2 +- net/atm/common.c | 4 ++-- net/atm/common.h | 2 +- net/batman-adv/icmp_socket.c | 2 +- net/batman-adv/log.c | 2 +- net/bluetooth/af_bluetooth.c | 6 +++--- net/caif/caif_socket.c | 4 ++-- net/core/datagram.c | 4 ++-- net/core/sock.c | 2 +- net/dccp/dccp.h | 2 +- net/dccp/proto.c | 4 ++-- net/decnet/af_decnet.c | 4 ++-- net/ipv4/tcp.c | 4 ++-- net/ipv4/udp.c | 4 ++-- net/iucv/af_iucv.c | 6 +++--- net/nfc/llcp_sock.c | 6 +++--- net/nfc/nci/uart.c | 2 +- net/packet/af_packet.c | 4 ++-- net/phonet/socket.c | 4 ++-- net/rds/af_rds.c | 4 ++-- net/rfkill/core.c | 4 ++-- net/rxrpc/af_rxrpc.c | 4 ++-- net/sctp/socket.c | 4 ++-- net/smc/af_smc.c | 4 ++-- net/socket.c | 4 ++-- net/sunrpc/cache.c | 8 ++++---- net/sunrpc/rpc_pipe.c | 4 ++-- net/tipc/socket.c | 4 ++-- net/unix/af_unix.c | 13 +++++++------ net/vmw_vsock/af_vsock.c | 4 ++-- 40 files changed, 77 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/irda/net/af_irda.c b/drivers/staging/irda/net/af_irda.c index b82a47b9ef0b..f1d128b2dae9 100644 --- a/drivers/staging/irda/net/af_irda.c +++ b/drivers/staging/irda/net/af_irda.c @@ -1737,12 +1737,12 @@ static int irda_shutdown(struct socket *sock, int how) /* * Function irda_poll (file, sock, wait) */ -static unsigned int irda_poll(struct file * file, struct socket *sock, +static __poll_t irda_poll(struct file * file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct irda_sock *self = irda_sk(sk); - unsigned int mask; + __poll_t mask; poll_wait(file, sk_sleep(sk), wait); mask = 0; diff --git a/drivers/staging/irda/net/irnet/irnet_ppp.c b/drivers/staging/irda/net/irnet/irnet_ppp.c index 7025dcb853d0..75bf9e34311d 100644 --- a/drivers/staging/irda/net/irnet/irnet_ppp.c +++ b/drivers/staging/irda/net/irnet/irnet_ppp.c @@ -419,12 +419,12 @@ irnet_ctrl_read(irnet_socket * ap, * Poll : called when someone do a select on /dev/irnet. * Just check if there are new events... */ -static inline unsigned int +static inline __poll_t irnet_ctrl_poll(irnet_socket * ap, struct file * file, poll_table * wait) { - unsigned int mask; + __poll_t mask; DENTER(CTRL_TRACE, "(ap=0x%p)\n", ap); @@ -608,12 +608,12 @@ dev_irnet_read(struct file * file, /* * Poll : called when someone do a select on /dev/irnet */ -static unsigned int +static __poll_t dev_irnet_poll(struct file * file, poll_table * wait) { irnet_socket * ap = file->private_data; - unsigned int mask; + __poll_t mask; DENTER(FS_TRACE, "(file=0x%p, ap=0x%p)\n", file, ap); diff --git a/drivers/staging/irda/net/irnet/irnet_ppp.h b/drivers/staging/irda/net/irnet/irnet_ppp.h index 32061442cc8e..e6d5aa2a8aac 100644 --- a/drivers/staging/irda/net/irnet/irnet_ppp.h +++ b/drivers/staging/irda/net/irnet/irnet_ppp.h @@ -70,7 +70,7 @@ static ssize_t char __user *, size_t, loff_t *); -static unsigned int +static __poll_t dev_irnet_poll(struct file *, poll_table *); static long diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index bc486ef23f20..07564bb28c1f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3242,7 +3242,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, int *peeked, int *off, int *err); struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err); -unsigned int datagram_poll(struct file *file, struct socket *sock, +__poll_t datagram_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait); int skb_copy_datagram_iter(const struct sk_buff *from, int offset, struct iov_iter *to, int size); diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index e89cff0c4c23..ec9d6bc65855 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -271,7 +271,7 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags); int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags); -uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait); +__poll_t bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait); int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo); int bt_sock_wait_ready(struct sock *sk, unsigned long flags); diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 0358745ea059..ec72cdb5bc39 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -305,7 +305,7 @@ void inet_csk_prepare_forced_close(struct sock *sk); /* * LISTEN is a special case for poll.. */ -static inline unsigned int inet_csk_listen_poll(const struct sock *sk) +static inline __poll_t inet_csk_listen_poll(const struct sock *sk) { return !reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue) ? (POLLIN | POLLRDNORM) : 0; diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index 070e93a17c59..f4c21b5a1242 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h @@ -153,7 +153,7 @@ struct iucv_sock_list { atomic_t autobind_name; }; -unsigned int iucv_sock_poll(struct file *file, struct socket *sock, +__poll_t iucv_sock_poll(struct file *file, struct socket *sock, poll_table *wait); void iucv_sock_link(struct iucv_sock_list *l, struct sock *s); void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s); diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 749a42882437..6b765de288d8 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -107,7 +107,7 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb); int sctp_inet_listen(struct socket *sock, int backlog); void sctp_write_space(struct sock *sk); void sctp_data_ready(struct sock *sk); -unsigned int sctp_poll(struct file *file, struct socket *sock, +__poll_t sctp_poll(struct file *file, struct socket *sock, poll_table *wait); void sctp_sock_rfree(struct sk_buff *skb); void sctp_copy_sock(struct sock *newsk, struct sock *sk, diff --git a/include/net/sock.h b/include/net/sock.h index 79e1a2c7912c..b33078333518 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1582,7 +1582,7 @@ int sock_no_connect(struct socket *, struct sockaddr *, int, int); int sock_no_socketpair(struct socket *, struct socket *); int sock_no_accept(struct socket *, struct socket *, int, bool); int sock_no_getname(struct socket *, struct sockaddr *, int *, int); -unsigned int sock_no_poll(struct file *, struct socket *, +__poll_t sock_no_poll(struct file *, struct socket *, struct poll_table_struct *); int sock_no_ioctl(struct socket *, unsigned int, unsigned long); int sock_no_listen(struct socket *, int); diff --git a/include/net/tcp.h b/include/net/tcp.h index 4e09398009c1..a6343271c629 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -387,7 +387,7 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst); void tcp_close(struct sock *sk, long timeout); void tcp_init_sock(struct sock *sk); void tcp_init_transfer(struct sock *sk, int bpf_op); -unsigned int tcp_poll(struct file *file, struct socket *sock, +__poll_t tcp_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait); int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); diff --git a/include/net/udp.h b/include/net/udp.h index 6c759c8594e2..850a8e581cce 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -275,7 +275,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); int udp_init_sock(struct sock *sk); int __udp_disconnect(struct sock *sk, int flags); int udp_disconnect(struct sock *sk, int flags); -unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait); +__poll_t udp_poll(struct file *file, struct socket *sock, poll_table *wait); struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, netdev_features_t features, bool is_ipv6); diff --git a/net/atm/common.c b/net/atm/common.c index 8a4f99114cd2..8f12f1c6fa14 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -648,11 +648,11 @@ out: return error; } -unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) +__poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct atm_vcc *vcc; - unsigned int mask; + __poll_t mask; sock_poll_wait(file, sk_sleep(sk), wait); mask = 0; diff --git a/net/atm/common.h b/net/atm/common.h index d9d583712a91..5850649068bb 100644 --- a/net/atm/common.h +++ b/net/atm/common.h @@ -17,7 +17,7 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci); int vcc_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags); int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len); -unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait); +__poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait); int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int vcc_setsockopt(struct socket *sock, int level, int optname, diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index bded31121d12..a98e0a986cef 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -292,7 +292,7 @@ out: return len; } -static unsigned int batadv_socket_poll(struct file *file, poll_table *wait) +static __poll_t batadv_socket_poll(struct file *file, poll_table *wait) { struct batadv_socket_client *socket_client = file->private_data; diff --git a/net/batman-adv/log.c b/net/batman-adv/log.c index 4ef4bde2cc2d..76451460c98d 100644 --- a/net/batman-adv/log.c +++ b/net/batman-adv/log.c @@ -176,7 +176,7 @@ static ssize_t batadv_log_read(struct file *file, char __user *buf, return error; } -static unsigned int batadv_log_poll(struct file *file, poll_table *wait) +static __poll_t batadv_log_poll(struct file *file, poll_table *wait) { struct batadv_priv *bat_priv = file->private_data; struct batadv_priv_debug_log *debug_log = bat_priv->debug_log; diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 91e3ba280706..671b907ba678 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -421,7 +421,7 @@ out: } EXPORT_SYMBOL(bt_sock_stream_recvmsg); -static inline unsigned int bt_accept_poll(struct sock *parent) +static inline __poll_t bt_accept_poll(struct sock *parent) { struct bt_sock *s, *n; struct sock *sk; @@ -437,11 +437,11 @@ static inline unsigned int bt_accept_poll(struct sock *parent) return 0; } -unsigned int bt_sock_poll(struct file *file, struct socket *sock, +__poll_t bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - unsigned int mask = 0; + __poll_t mask = 0; BT_DBG("sock %p, sk %p", sock, sk); diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 632d5a416d97..64048cec41e0 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -934,11 +934,11 @@ static int caif_release(struct socket *sock) } /* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */ -static unsigned int caif_poll(struct file *file, +static __poll_t caif_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - unsigned int mask; + __poll_t mask; struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); sock_poll_wait(file, sk_sleep(sk), wait); diff --git a/net/core/datagram.c b/net/core/datagram.c index 000da13c01f2..b7d9293940b5 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -831,11 +831,11 @@ EXPORT_SYMBOL(skb_copy_and_csum_datagram_msg); * and you use a different write policy from sock_writeable() * then please supply your own write_space callback. */ -unsigned int datagram_poll(struct file *file, struct socket *sock, +__poll_t datagram_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - unsigned int mask; + __poll_t mask; sock_poll_wait(file, sk_sleep(sk), wait); mask = 0; diff --git a/net/core/sock.c b/net/core/sock.c index c0b5b2f17412..1211159718ad 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2496,7 +2496,7 @@ int sock_no_getname(struct socket *sock, struct sockaddr *saddr, } EXPORT_SYMBOL(sock_no_getname); -unsigned int sock_no_poll(struct file *file, struct socket *sock, poll_table *pt) +__poll_t sock_no_poll(struct file *file, struct socket *sock, poll_table *pt) { return 0; } diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 0c55ffb859bf..f91e3816806b 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -316,7 +316,7 @@ int dccp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, int flags, int *addr_len); void dccp_shutdown(struct sock *sk, int how); int inet_dccp_listen(struct socket *sock, int backlog); -unsigned int dccp_poll(struct file *file, struct socket *sock, +__poll_t dccp_poll(struct file *file, struct socket *sock, poll_table *wait); int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); void dccp_req_err(struct sock *sk, u64 seq); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index b68168fcc06a..cfa9ca9939ce 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -313,10 +313,10 @@ EXPORT_SYMBOL_GPL(dccp_disconnect); * take care of normal races (between the test and the event) and we don't * go look at any of the socket buffers directly. */ -unsigned int dccp_poll(struct file *file, struct socket *sock, +__poll_t dccp_poll(struct file *file, struct socket *sock, poll_table *wait) { - unsigned int mask; + __poll_t mask; struct sock *sk = sock->sk; sock_poll_wait(file, sk_sleep(sk), wait); diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 518cea17b811..9c2dde819817 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -1209,11 +1209,11 @@ static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int *uaddr_len } -static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table *wait) +static __poll_t dn_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct dn_scp *scp = DN_SK(sk); - int mask = datagram_poll(file, sock, wait); + __poll_t mask = datagram_poll(file, sock, wait); if (!skb_queue_empty(&scp->other_receive_queue)) mask |= POLLRDBAND; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index bf97317e6c97..0b8ca689353b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -493,9 +493,9 @@ static void tcp_tx_timestamp(struct sock *sk, u16 tsflags) * take care of normal races (between the test and the event) and we don't * go look at any of the socket buffers directly. */ -unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) +__poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait) { - unsigned int mask; + __poll_t mask; struct sock *sk = sock->sk; const struct tcp_sock *tp = tcp_sk(sk); int state; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index e4ff25c947c5..ef45adfc0edb 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2502,9 +2502,9 @@ int compat_udp_getsockopt(struct sock *sk, int level, int optname, * but then block when reading it. Add special case code * to work around these arguably broken applications. */ -unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) +__poll_t udp_poll(struct file *file, struct socket *sock, poll_table *wait) { - unsigned int mask = datagram_poll(file, sock, wait); + __poll_t mask = datagram_poll(file, sock, wait); struct sock *sk = sock->sk; if (!skb_queue_empty(&udp_sk(sk)->reader_queue)) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 148533169b1d..64331158d693 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1474,7 +1474,7 @@ done: return copied; } -static inline unsigned int iucv_accept_poll(struct sock *parent) +static inline __poll_t iucv_accept_poll(struct sock *parent) { struct iucv_sock *isk, *n; struct sock *sk; @@ -1489,11 +1489,11 @@ static inline unsigned int iucv_accept_poll(struct sock *parent) return 0; } -unsigned int iucv_sock_poll(struct file *file, struct socket *sock, +__poll_t iucv_sock_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - unsigned int mask = 0; + __poll_t mask = 0; sock_poll_wait(file, sk_sleep(sk), wait); diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index fb7afcaa3004..985909f105eb 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -531,7 +531,7 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr, return 0; } -static inline unsigned int llcp_accept_poll(struct sock *parent) +static inline __poll_t llcp_accept_poll(struct sock *parent) { struct nfc_llcp_sock *llcp_sock, *parent_sock; struct sock *sk; @@ -549,11 +549,11 @@ static inline unsigned int llcp_accept_poll(struct sock *parent) return 0; } -static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, +static __poll_t llcp_sock_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - unsigned int mask = 0; + __poll_t mask = 0; pr_debug("%p\n", sk); diff --git a/net/nfc/nci/uart.c b/net/nfc/nci/uart.c index 8d104c1db628..a66f102c6c01 100644 --- a/net/nfc/nci/uart.c +++ b/net/nfc/nci/uart.c @@ -305,7 +305,7 @@ static ssize_t nci_uart_tty_write(struct tty_struct *tty, struct file *file, return 0; } -static unsigned int nci_uart_tty_poll(struct tty_struct *tty, +static __poll_t nci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait) { return 0; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 737092ca9b4e..ef6340e2406a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -4080,12 +4080,12 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, return 0; } -static unsigned int packet_poll(struct file *file, struct socket *sock, +static __poll_t packet_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct packet_sock *po = pkt_sk(sk); - unsigned int mask = datagram_poll(file, sock, wait); + __poll_t mask = datagram_poll(file, sock, wait); spin_lock_bh(&sk->sk_receive_queue.lock); if (po->rx_ring.pg_vec) { diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 1b050dd17393..44417480dab7 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -341,12 +341,12 @@ static int pn_socket_getname(struct socket *sock, struct sockaddr *addr, return 0; } -static unsigned int pn_socket_poll(struct file *file, struct socket *sock, +static __poll_t pn_socket_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct pep_sock *pn = pep_sk(sk); - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, sk_sleep(sk), wait); diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index b405f77d664c..88aa8ad0f5b6 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -152,12 +152,12 @@ static int rds_getname(struct socket *sock, struct sockaddr *uaddr, * to send to a congested destination, the system call may still fail (and * return ENOBUFS). */ -static unsigned int rds_poll(struct file *file, struct socket *sock, +static __poll_t rds_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct rds_sock *rs = rds_sk_to_rs(sk); - unsigned int mask = 0; + __poll_t mask = 0; unsigned long flags; poll_wait(file, sk_sleep(sk), wait); diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 2064c3a35ef8..124c77e9d058 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -1139,10 +1139,10 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) return -ENOMEM; } -static unsigned int rfkill_fop_poll(struct file *file, poll_table *wait) +static __poll_t rfkill_fop_poll(struct file *file, poll_table *wait) { struct rfkill_data *data = file->private_data; - unsigned int res = POLLOUT | POLLWRNORM; + __poll_t res = POLLOUT | POLLWRNORM; poll_wait(file, &data->read_wait, wait); diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 9b5c46b052fd..f8c8953d9295 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -725,12 +725,12 @@ static int rxrpc_getsockopt(struct socket *sock, int level, int optname, /* * permit an RxRPC socket to be polled */ -static unsigned int rxrpc_poll(struct file *file, struct socket *sock, +static __poll_t rxrpc_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct rxrpc_sock *rx = rxrpc_sk(sk); - unsigned int mask; + __poll_t mask; sock_poll_wait(file, sk_sleep(sk), wait); mask = 0; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3204a9b29407..8d3ac79f82e5 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -7497,11 +7497,11 @@ out: * here, again, by modeling the current TCP/UDP code. We don't have * a good way to test with it yet. */ -unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) +__poll_t sctp_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct sctp_sock *sp = sctp_sk(sk); - unsigned int mask; + __poll_t mask; poll_wait(file, sk_sleep(sk), wait); diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index ae59826230be..449f62e1e270 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -1107,7 +1107,7 @@ out: return rc; } -static unsigned int smc_accept_poll(struct sock *parent) +static __poll_t smc_accept_poll(struct sock *parent) { struct smc_sock *isk; struct sock *sk; @@ -1126,7 +1126,7 @@ static unsigned int smc_accept_poll(struct sock *parent) return 0; } -static unsigned int smc_poll(struct file *file, struct socket *sock, +static __poll_t smc_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; diff --git a/net/socket.c b/net/socket.c index dceab22a41fd..3e5e4f13046c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -118,7 +118,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from); static int sock_mmap(struct file *file, struct vm_area_struct *vma); static int sock_close(struct inode *inode, struct file *file); -static unsigned int sock_poll(struct file *file, +static __poll_t sock_poll(struct file *file, struct poll_table_struct *wait); static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); #ifdef CONFIG_COMPAT @@ -1091,7 +1091,7 @@ out_release: EXPORT_SYMBOL(sock_create_lite); /* No kernel lock held - perfect */ -static unsigned int sock_poll(struct file *file, poll_table *wait) +static __poll_t sock_poll(struct file *file, poll_table *wait) { __poll_t busy_flag = 0; struct socket *sock; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 79d55d949d9a..c20ac7af7a4c 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -930,10 +930,10 @@ out: static DECLARE_WAIT_QUEUE_HEAD(queue_wait); -static unsigned int cache_poll(struct file *filp, poll_table *wait, +static __poll_t cache_poll(struct file *filp, poll_table *wait, struct cache_detail *cd) { - unsigned int mask; + __poll_t mask; struct cache_reader *rp = filp->private_data; struct cache_queue *cq; @@ -1501,7 +1501,7 @@ static ssize_t cache_write_procfs(struct file *filp, const char __user *buf, return cache_write(filp, buf, count, ppos, cd); } -static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait) +static __poll_t cache_poll_procfs(struct file *filp, poll_table *wait) { struct cache_detail *cd = PDE_DATA(file_inode(filp)); @@ -1720,7 +1720,7 @@ static ssize_t cache_write_pipefs(struct file *filp, const char __user *buf, return cache_write(filp, buf, count, ppos, cd); } -static unsigned int cache_poll_pipefs(struct file *filp, poll_table *wait) +static __poll_t cache_poll_pipefs(struct file *filp, poll_table *wait) { struct cache_detail *cd = RPC_I(file_inode(filp))->private; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 7803f3b6aa53..5c4330325787 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -340,12 +340,12 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of return res; } -static unsigned int +static __poll_t rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) { struct inode *inode = file_inode(filp); struct rpc_inode *rpci = RPC_I(inode); - unsigned int mask = POLLOUT | POLLWRNORM; + __poll_t mask = POLLOUT | POLLWRNORM; poll_wait(filp, &rpci->waitq, wait); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 5d18c0caa92b..d94d25855190 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -710,13 +710,13 @@ static int tipc_getname(struct socket *sock, struct sockaddr *uaddr, * imply that the operation will succeed, merely that it should be performed * and will not block. */ -static unsigned int tipc_poll(struct file *file, struct socket *sock, +static __poll_t tipc_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; struct tipc_sock *tsk = tipc_sk(sk); struct tipc_group *grp = tsk->group; - u32 revents = 0; + __poll_t revents = 0; sock_poll_wait(file, sk_sleep(sk), wait); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 72957961ac22..6b7678df41e5 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -638,8 +638,8 @@ static int unix_stream_connect(struct socket *, struct sockaddr *, static int unix_socketpair(struct socket *, struct socket *); static int unix_accept(struct socket *, struct socket *, int, bool); static int unix_getname(struct socket *, struct sockaddr *, int *, int); -static unsigned int unix_poll(struct file *, struct socket *, poll_table *); -static unsigned int unix_dgram_poll(struct file *, struct socket *, +static __poll_t unix_poll(struct file *, struct socket *, poll_table *); +static __poll_t unix_dgram_poll(struct file *, struct socket *, poll_table *); static int unix_ioctl(struct socket *, unsigned int, unsigned long); static int unix_shutdown(struct socket *, int); @@ -2640,10 +2640,10 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return err; } -static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table *wait) +static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; - unsigned int mask; + __poll_t mask; sock_poll_wait(file, sk_sleep(sk), wait); mask = 0; @@ -2675,11 +2675,12 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table return mask; } -static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, +static __poll_t unix_dgram_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk, *other; - unsigned int mask, writable; + unsigned int writable; + __poll_t mask; sock_poll_wait(file, sk_sleep(sk), wait); mask = 0; diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 5d28abf87fbf..bbd97d3bd8fb 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -850,11 +850,11 @@ static int vsock_shutdown(struct socket *sock, int mode) return err; } -static unsigned int vsock_poll(struct file *file, struct socket *sock, +static __poll_t vsock_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk; - unsigned int mask; + __poll_t mask; struct vsock_sock *vsk; sk = sock->sk; -- cgit v1.2.3 From c23e0cb81e4021b9712b1093d54713991fd9b7c2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 3 Jul 2017 03:02:56 -0400 Subject: media: annotate ->poll() instances Signed-off-by: Al Viro --- drivers/media/cec/cec-api.c | 4 ++-- drivers/media/common/saa7146/saa7146_fops.c | 8 ++++---- drivers/media/common/siano/smsdvb-debugfs.c | 7 ++----- drivers/media/dvb-core/dmxdev.c | 8 ++++---- drivers/media/dvb-core/dvb_ca_en50221.c | 4 ++-- drivers/media/dvb-core/dvb_frontend.c | 2 +- drivers/media/firewire/firedtv-ci.c | 2 +- drivers/media/media-devnode.c | 2 +- drivers/media/pci/bt8xx/bttv-driver.c | 8 ++++---- drivers/media/pci/cx18/cx18-fileops.c | 6 +++--- drivers/media/pci/cx18/cx18-fileops.h | 2 +- drivers/media/pci/ddbridge/ddbridge-core.c | 4 ++-- drivers/media/pci/ivtv/ivtv-fileops.c | 8 ++++---- drivers/media/pci/ivtv/ivtv-fileops.h | 4 ++-- drivers/media/pci/meye/meye.c | 4 ++-- drivers/media/pci/saa7134/saa7134-video.c | 4 ++-- drivers/media/pci/saa7164/saa7164-encoder.c | 4 ++-- drivers/media/pci/saa7164/saa7164-vbi.c | 4 ++-- drivers/media/pci/ttpci/av7110_av.c | 8 ++++---- drivers/media/pci/ttpci/av7110_ca.c | 4 ++-- drivers/media/pci/zoran/zoran_driver.c | 4 ++-- drivers/media/platform/davinci/vpfe_capture.c | 2 +- drivers/media/platform/exynos-gsc/gsc-m2m.c | 4 ++-- drivers/media/platform/fsl-viu.c | 4 ++-- drivers/media/platform/m2m-deinterlace.c | 4 ++-- drivers/media/platform/mx2_emmaprp.c | 4 ++-- drivers/media/platform/omap/omap_vout.c | 2 +- drivers/media/platform/omap3isp/ispvideo.c | 4 ++-- drivers/media/platform/s3c-camif/camif-capture.c | 4 ++-- drivers/media/platform/s5p-mfc/s5p_mfc.c | 4 ++-- drivers/media/platform/sh_veu.c | 2 +- drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | 2 +- drivers/media/platform/soc_camera/soc_camera.c | 2 +- drivers/media/platform/via-camera.c | 2 +- drivers/media/platform/vivid/vivid-core.c | 2 +- drivers/media/platform/vivid/vivid-radio-rx.c | 2 +- drivers/media/platform/vivid/vivid-radio-rx.h | 2 +- drivers/media/platform/vivid/vivid-radio-tx.c | 2 +- drivers/media/platform/vivid/vivid-radio-tx.h | 2 +- drivers/media/radio/radio-cadet.c | 4 ++-- drivers/media/radio/radio-si476x.c | 4 ++-- drivers/media/radio/radio-wl1273.c | 2 +- drivers/media/radio/si470x/radio-si470x-common.c | 4 ++-- drivers/media/radio/wl128x/fmdrv_v4l2.c | 2 +- drivers/media/rc/lirc_dev.c | 4 ++-- drivers/media/usb/cpia2/cpia2.h | 2 +- drivers/media/usb/cpia2/cpia2_core.c | 4 ++-- drivers/media/usb/cpia2/cpia2_v4l.c | 4 ++-- drivers/media/usb/cx231xx/cx231xx-417.c | 4 ++-- drivers/media/usb/cx231xx/cx231xx-video.c | 4 ++-- drivers/media/usb/gspca/gspca.c | 4 ++-- drivers/media/usb/hdpvr/hdpvr-video.c | 4 ++-- drivers/media/usb/pvrusb2/pvrusb2-v4l2.c | 4 ++-- drivers/media/usb/stkwebcam/stk-webcam.c | 4 ++-- drivers/media/usb/tm6000/tm6000-video.c | 8 ++++---- drivers/media/usb/uvc/uvc_queue.c | 4 ++-- drivers/media/usb/uvc/uvc_v4l2.c | 2 +- drivers/media/usb/uvc/uvcvideo.h | 2 +- drivers/media/usb/zr364xx/zr364xx.c | 4 ++-- drivers/media/v4l2-core/v4l2-ctrls.c | 2 +- drivers/media/v4l2-core/v4l2-dev.c | 2 +- drivers/media/v4l2-core/v4l2-mem2mem.c | 8 ++++---- drivers/media/v4l2-core/v4l2-subdev.c | 2 +- drivers/media/v4l2-core/videobuf-core.c | 4 ++-- drivers/media/v4l2-core/videobuf2-core.c | 2 +- drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++++---- drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c | 2 +- drivers/staging/media/bcm2048/radio-bcm2048.c | 4 ++-- drivers/staging/media/davinci_vpfe/vpfe_video.c | 2 +- drivers/staging/media/lirc/lirc_zilog.c | 4 ++-- drivers/staging/media/omap4iss/iss_video.c | 2 +- drivers/usb/gadget/function/uvc_queue.c | 2 +- drivers/usb/gadget/function/uvc_queue.h | 2 +- drivers/usb/gadget/function/uvc_v4l2.c | 2 +- include/media/lirc_dev.h | 2 +- include/media/v4l2-ctrls.h | 2 +- include/media/v4l2-mem2mem.h | 4 ++-- include/media/videobuf-core.h | 2 +- include/media/videobuf2-core.h | 2 +- include/media/videobuf2-v4l2.h | 5 ++--- 80 files changed, 143 insertions(+), 147 deletions(-) (limited to 'drivers') diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c index 3dba3aa34a43..9d6c496f756c 100644 --- a/drivers/media/cec/cec-api.c +++ b/drivers/media/cec/cec-api.c @@ -43,13 +43,13 @@ static inline struct cec_devnode *cec_devnode_data(struct file *filp) /* CEC file operations */ -static unsigned int cec_poll(struct file *filp, +static __poll_t cec_poll(struct file *filp, struct poll_table_struct *poll) { struct cec_devnode *devnode = cec_devnode_data(filp); struct cec_fh *fh = filp->private_data; struct cec_adapter *adap = fh->adap; - unsigned int res = 0; + __poll_t res = 0; if (!devnode->registered) return POLLERR | POLLHUP; diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index 8c87d6837c49..8ee3eebef4db 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c @@ -320,13 +320,13 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma) return res; } -static unsigned int __fops_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t __fops_poll(struct file *file, struct poll_table_struct *wait) { struct video_device *vdev = video_devdata(file); struct saa7146_fh *fh = file->private_data; struct videobuf_buffer *buf = NULL; struct videobuf_queue *q; - unsigned int res = v4l2_ctrl_poll(file, wait); + __poll_t res = v4l2_ctrl_poll(file, wait); DEB_EE("file:%p, poll:%p\n", file, wait); @@ -359,10 +359,10 @@ static unsigned int __fops_poll(struct file *file, struct poll_table_struct *wai return res; } -static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t fops_poll(struct file *file, struct poll_table_struct *wait) { struct video_device *vdev = video_devdata(file); - unsigned int res; + __poll_t res; mutex_lock(vdev->lock); res = __fops_poll(file, wait); diff --git a/drivers/media/common/siano/smsdvb-debugfs.c b/drivers/media/common/siano/smsdvb-debugfs.c index 1a8677ade391..0c0878bcf251 100644 --- a/drivers/media/common/siano/smsdvb-debugfs.c +++ b/drivers/media/common/siano/smsdvb-debugfs.c @@ -374,7 +374,7 @@ exit: return rc; } -static unsigned int smsdvb_stats_poll(struct file *file, poll_table *wait) +static __poll_t smsdvb_stats_poll(struct file *file, poll_table *wait) { struct smsdvb_debugfs *debug_data = file->private_data; int rc; @@ -384,12 +384,9 @@ static unsigned int smsdvb_stats_poll(struct file *file, poll_table *wait) poll_wait(file, &debug_data->stats_queue, wait); rc = smsdvb_stats_wait_read(debug_data); - if (rc > 0) - rc = POLLIN | POLLRDNORM; - kref_put(&debug_data->refcount, smsdvb_debugfs_data_release); - return rc; + return rc > 0 ? POLLIN | POLLRDNORM : 0; } static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf, diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 3ddd44e1ee77..3fe0eb740a6d 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -1066,10 +1066,10 @@ static long dvb_demux_ioctl(struct file *file, unsigned int cmd, return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl); } -static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) +static __poll_t dvb_demux_poll(struct file *file, poll_table *wait) { struct dmxdev_filter *dmxdevfilter = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; if ((!dmxdevfilter) || dmxdevfilter->dev->exit) return POLLERR; @@ -1160,11 +1160,11 @@ static long dvb_dvr_ioctl(struct file *file, return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl); } -static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) +static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait) { struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; - unsigned int mask = 0; + __poll_t mask = 0; dprintk("%s\n", __func__); diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index 95b3723282f4..dbb527a2befc 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c @@ -1783,11 +1783,11 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) * * @return Standard poll mask. */ -static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) +static __poll_t dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) { struct dvb_device *dvbdev = file->private_data; struct dvb_ca_private *ca = dvbdev->priv; - unsigned int mask = 0; + __poll_t mask = 0; int slot; int result = 0; diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 3ad83359098b..92e2433415f0 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -2467,7 +2467,7 @@ static int dvb_frontend_handle_ioctl(struct file *file, } -static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c index edbb30fdd9d9..fb8a1d2ffd24 100644 --- a/drivers/media/firewire/firedtv-ci.c +++ b/drivers/media/firewire/firedtv-ci.c @@ -207,7 +207,7 @@ static int fdtv_ca_ioctl(struct file *file, unsigned int cmd, void *arg) return err; } -static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait) +static __poll_t fdtv_ca_io_poll(struct file *file, poll_table *wait) { return POLLIN; } diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index 423248f577b6..3049b1f505e5 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -99,7 +99,7 @@ static ssize_t media_write(struct file *filp, const char __user *buf, return devnode->fops->write(filp, buf, sz, off); } -static unsigned int media_poll(struct file *filp, +static __poll_t media_poll(struct file *filp, struct poll_table_struct *poll) { struct media_devnode *devnode = media_devnode_data(filp); diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 721f586c0394..c988669e22ff 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -2955,12 +2955,12 @@ static ssize_t bttv_read(struct file *file, char __user *data, return retval; } -static unsigned int bttv_poll(struct file *file, poll_table *wait) +static __poll_t bttv_poll(struct file *file, poll_table *wait) { struct bttv_fh *fh = file->private_data; struct bttv_buffer *buf; enum v4l2_field field; - unsigned int rc = 0; + __poll_t rc = 0; __poll_t req_events = poll_requested_events(wait); if (v4l2_event_pending(&fh->fh)) @@ -3329,13 +3329,13 @@ static ssize_t radio_read(struct file *file, char __user *data, return cmd.result; } -static unsigned int radio_poll(struct file *file, poll_table *wait) +static __poll_t radio_poll(struct file *file, poll_table *wait) { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; __poll_t req_events = poll_requested_events(wait); struct saa6588_command cmd; - unsigned int res = 0; + __poll_t res = 0; if (v4l2_event_pending(&fh->fh)) res = POLLPRI; diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c index 55130d5abffd..2b0abd5bbf64 100644 --- a/drivers/media/pci/cx18/cx18-fileops.c +++ b/drivers/media/pci/cx18/cx18-fileops.c @@ -602,14 +602,14 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count, return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); } -unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) +__poll_t cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); struct cx18_open_id *id = file2id(filp); struct cx18 *cx = id->cx; struct cx18_stream *s = &cx->streams[id->type]; int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags); - unsigned res = 0; + __poll_t res = 0; /* Start a capture if there is none */ if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags) && @@ -629,7 +629,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && (id->type == CX18_ENC_STREAM_TYPE_YUV)) { - int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait); + __poll_t videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait); if (v4l2_event_pending(&id->fh)) res |= POLLPRI; diff --git a/drivers/media/pci/cx18/cx18-fileops.h b/drivers/media/pci/cx18/cx18-fileops.h index 37ef34e866cb..5b44d30efd8f 100644 --- a/drivers/media/pci/cx18/cx18-fileops.h +++ b/drivers/media/pci/cx18/cx18-fileops.h @@ -23,7 +23,7 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count, ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos); int cx18_v4l2_close(struct file *filp); -unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait); +__poll_t cx18_v4l2_enc_poll(struct file *filp, poll_table *wait); int cx18_start_capture(struct cx18_open_id *id); void cx18_stop_capture(struct cx18_open_id *id, int gop_end); void cx18_mute(struct cx18 *cx); diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index f4bd4908acdd..09a25d6c2cd1 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -732,13 +732,13 @@ static ssize_t ts_read(struct file *file, __user char *buf, return (count && (left == count)) ? -EAGAIN : (count - left); } -static unsigned int ts_poll(struct file *file, poll_table *wait) +static __poll_t ts_poll(struct file *file, poll_table *wait) { struct dvb_device *dvbdev = file->private_data; struct ddb_output *output = dvbdev->priv; struct ddb_input *input = output->port->input[0]; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &input->dma->wq, wait); poll_wait(file, &output->dma->wq, wait); diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c index 22217ef30bd6..4aa773507201 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.c +++ b/drivers/media/pci/ivtv/ivtv-fileops.c @@ -730,12 +730,12 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c return res; } -unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) +__poll_t ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) { struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; - int res = 0; + __poll_t res = 0; /* add stream's waitq to the poll list */ IVTV_DEBUG_HI_FILE("Decoder poll\n"); @@ -764,14 +764,14 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) return res; } -unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) +__poll_t ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - unsigned res = 0; + __poll_t res = 0; /* Start a capture if there is none */ if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) && diff --git a/drivers/media/pci/ivtv/ivtv-fileops.h b/drivers/media/pci/ivtv/ivtv-fileops.h index 5e08800772ca..e0029b2b8d09 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.h +++ b/drivers/media/pci/ivtv/ivtv-fileops.h @@ -28,8 +28,8 @@ ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count, ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count, loff_t * pos); int ivtv_v4l2_close(struct file *filp); -unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait); -unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait); +__poll_t ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait); +__poll_t ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait); int ivtv_start_capture(struct ivtv_open_id *id); void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end); int ivtv_start_decoding(struct ivtv_open_id *id, int speed); diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 23999a8cef37..f74b08635082 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -1423,9 +1423,9 @@ static long vidioc_default(struct file *file, void *fh, bool valid_prio, } -static unsigned int meye_poll(struct file *file, poll_table *wait) +static __poll_t meye_poll(struct file *file, poll_table *wait) { - unsigned int res = v4l2_ctrl_poll(file, wait); + __poll_t res = v4l2_ctrl_poll(file, wait); mutex_lock(&meye.lock); poll_wait(file, &meye.proc_list, wait); diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 82d2a24644e4..0ceaa3473cf2 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1227,11 +1227,11 @@ static ssize_t radio_read(struct file *file, char __user *data, return cmd.result; } -static unsigned int radio_poll(struct file *file, poll_table *wait) +static __poll_t radio_poll(struct file *file, poll_table *wait) { struct saa7134_dev *dev = video_drvdata(file); struct saa6588_command cmd; - unsigned int rc = v4l2_ctrl_poll(file, wait); + __poll_t rc = v4l2_ctrl_poll(file, wait); cmd.instance = file; cmd.event_list = wait; diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index ab75e5e19884..e7b31a5b14fd 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -909,13 +909,13 @@ err: return ret; } -static unsigned int fops_poll(struct file *file, poll_table *wait) +static __poll_t fops_poll(struct file *file, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); struct saa7164_encoder_fh *fh = (struct saa7164_encoder_fh *)file->private_data; struct saa7164_port *port = fh->port; - unsigned int mask = v4l2_ctrl_poll(file, wait); + __poll_t mask = v4l2_ctrl_poll(file, wait); port->last_poll_msecs_diff = port->last_poll_msecs; port->last_poll_msecs = jiffies_to_msecs(jiffies); diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index 9255d7d23947..6f97c8f2e00d 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -614,11 +614,11 @@ err: return ret; } -static unsigned int fops_poll(struct file *file, poll_table *wait) +static __poll_t fops_poll(struct file *file, poll_table *wait) { struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data; struct saa7164_port *port = fh->port; - unsigned int mask = 0; + __poll_t mask = 0; port->last_poll_msecs_diff = port->last_poll_msecs; port->last_poll_msecs = jiffies_to_msecs(jiffies); diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c index 2aa4ba675194..4d10e2f979d2 100644 --- a/drivers/media/pci/ttpci/av7110_av.c +++ b/drivers/media/pci/ttpci/av7110_av.c @@ -937,11 +937,11 @@ static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event * DVB device file operations ******************************************************************************/ -static unsigned int dvb_video_poll(struct file *file, poll_table *wait) +static __poll_t dvb_video_poll(struct file *file, poll_table *wait) { struct dvb_device *dvbdev = file->private_data; struct av7110 *av7110 = dvbdev->priv; - unsigned int mask = 0; + __poll_t mask = 0; dprintk(2, "av7110:%p, \n", av7110); @@ -989,11 +989,11 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf, return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); } -static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) +static __poll_t dvb_audio_poll(struct file *file, poll_table *wait) { struct dvb_device *dvbdev = file->private_data; struct av7110 *av7110 = dvbdev->priv; - unsigned int mask = 0; + __poll_t mask = 0; dprintk(2, "av7110:%p, \n", av7110); diff --git a/drivers/media/pci/ttpci/av7110_ca.c b/drivers/media/pci/ttpci/av7110_ca.c index 1fe49171d823..96ca227cf51b 100644 --- a/drivers/media/pci/ttpci/av7110_ca.c +++ b/drivers/media/pci/ttpci/av7110_ca.c @@ -223,13 +223,13 @@ static int dvb_ca_open(struct inode *inode, struct file *file) return 0; } -static unsigned int dvb_ca_poll (struct file *file, poll_table *wait) +static __poll_t dvb_ca_poll (struct file *file, poll_table *wait) { struct dvb_device *dvbdev = file->private_data; struct av7110 *av7110 = dvbdev->priv; struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer; struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer; - unsigned int mask = 0; + __poll_t mask = 0; dprintk(8, "av7110:%p\n",av7110); diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index d07840072337..b6a6c4f171d0 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -2501,13 +2501,13 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, return res; } -static unsigned int +static __poll_t zoran_poll (struct file *file, poll_table *wait) { struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; - int res = v4l2_ctrl_poll(file, wait); + __poll_t res = v4l2_ctrl_poll(file, wait); int frame; unsigned long flags; diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 7b3f6f8e3dc8..cf65b39807fe 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -730,7 +730,7 @@ static int vpfe_mmap(struct file *file, struct vm_area_struct *vma) /* * vpfe_poll: It is used for select/poll system call */ -static unsigned int vpfe_poll(struct file *file, poll_table *wait) +static __poll_t vpfe_poll(struct file *file, poll_table *wait) { struct vpfe_device *vpfe_dev = video_drvdata(file); diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 2a2994ef15d5..b2dc524112f7 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -707,12 +707,12 @@ static int gsc_m2m_release(struct file *file) return 0; } -static unsigned int gsc_m2m_poll(struct file *file, +static __poll_t gsc_m2m_poll(struct file *file, struct poll_table_struct *wait) { struct gsc_ctx *ctx = fh_to_ctx(file->private_data); struct gsc_dev *gsc = ctx->gsc_dev; - unsigned int ret; + __poll_t ret; if (mutex_lock_interruptible(&gsc->lock)) return -ERESTARTSYS; diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index 1e9c1f05d057..de285a269390 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -1263,13 +1263,13 @@ static ssize_t viu_read(struct file *file, char __user *data, size_t count, return 0; } -static unsigned int viu_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t viu_poll(struct file *file, struct poll_table_struct *wait) { struct viu_fh *fh = file->private_data; struct videobuf_queue *q = &fh->vb_vidq; struct viu_dev *dev = fh->dev; __poll_t req_events = poll_requested_events(wait); - unsigned int res = v4l2_ctrl_poll(file, wait); + __poll_t res = v4l2_ctrl_poll(file, wait); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) return POLLERR; diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index c8a12493f395..945ef1e2ccc7 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -950,11 +950,11 @@ static int deinterlace_release(struct file *file) return 0; } -static unsigned int deinterlace_poll(struct file *file, +static __poll_t deinterlace_poll(struct file *file, struct poll_table_struct *wait) { struct deinterlace_ctx *ctx = file->private_data; - int ret; + __poll_t ret; deinterlace_lock(ctx); ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index 4a2b1afa19c4..5a8eff60e95f 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -838,12 +838,12 @@ static int emmaprp_release(struct file *file) return 0; } -static unsigned int emmaprp_poll(struct file *file, +static __poll_t emmaprp_poll(struct file *file, struct poll_table_struct *wait) { struct emmaprp_dev *pcdev = video_drvdata(file); struct emmaprp_ctx *ctx = file->private_data; - unsigned int res; + __poll_t res; mutex_lock(&pcdev->dev_mutex); res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 6f1b0c799e58..abb14ee20538 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -839,7 +839,7 @@ static void omap_vout_buffer_release(struct videobuf_queue *q, /* * File operations */ -static unsigned int omap_vout_poll(struct file *file, +static __poll_t omap_vout_poll(struct file *file, struct poll_table_struct *wait) { struct omap_vout_device *vout = file->private_data; diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 218e6d7ae93a..a751c89a3ea8 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -1383,11 +1383,11 @@ static int isp_video_release(struct file *file) return 0; } -static unsigned int isp_video_poll(struct file *file, poll_table *wait) +static __poll_t isp_video_poll(struct file *file, poll_table *wait) { struct isp_video_fh *vfh = to_isp_video_fh(file->private_data); struct isp_video *video = video_drvdata(file); - int ret; + __poll_t ret; mutex_lock(&video->queue_lock); ret = vb2_poll(&vfh->queue, file, wait); diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index 25c7a7d42292..437395a61065 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -590,12 +590,12 @@ static int s3c_camif_close(struct file *file) return ret; } -static unsigned int s3c_camif_poll(struct file *file, +static __poll_t s3c_camif_poll(struct file *file, struct poll_table_struct *wait) { struct camif_vp *vp = video_drvdata(file); struct camif_dev *camif = vp->camif; - int ret; + __poll_t ret; mutex_lock(&camif->lock); if (vp->owner && vp->owner != file->private_data) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index bc68dbbcaec1..fe94bd6b705e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -988,14 +988,14 @@ static int s5p_mfc_release(struct file *file) } /* Poll */ -static unsigned int s5p_mfc_poll(struct file *file, +static __poll_t s5p_mfc_poll(struct file *file, struct poll_table_struct *wait) { struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); struct s5p_mfc_dev *dev = ctx->dev; struct vb2_queue *src_q, *dst_q; struct vb2_buffer *src_vb = NULL, *dst_vb = NULL; - unsigned int rc = 0; + __poll_t rc = 0; unsigned long flags; mutex_lock(&dev->mfc_mutex); diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 15a562af13c7..15cf51f5d280 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -1016,7 +1016,7 @@ static int sh_veu_release(struct file *file) return 0; } -static unsigned int sh_veu_poll(struct file *file, +static __poll_t sh_veu_poll(struct file *file, struct poll_table_struct *wait) { struct sh_veu_file *veu_file = file->private_data; diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 36762ec954e7..9b069783e3ed 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -1553,7 +1553,7 @@ static int sh_mobile_ceu_set_liveselection(struct soc_camera_device *icd, return ret; } -static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) +static __poll_t sh_mobile_ceu_poll(struct file *file, poll_table *pt) { struct soc_camera_device *icd = file->private_data; diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index f805f45716a3..d964c072832c 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -805,7 +805,7 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) return err; } -static unsigned int soc_camera_poll(struct file *file, poll_table *pt) +static __poll_t soc_camera_poll(struct file *file, poll_table *pt) { struct soc_camera_device *icd = file->private_data; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index 805d4a8fc17e..f77be9302120 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -764,7 +764,7 @@ out_unlock: } -static unsigned int viacam_poll(struct file *filp, struct poll_table_struct *pt) +static __poll_t viacam_poll(struct file *filp, struct poll_table_struct *pt) { struct via_camera *cam = video_drvdata(filp); diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index 5f316a5e38db..c80239592088 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -416,7 +416,7 @@ static ssize_t vivid_radio_write(struct file *file, const char __user *buf, return vivid_radio_tx_write(file, buf, size, offset); } -static unsigned int vivid_radio_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t vivid_radio_poll(struct file *file, struct poll_table_struct *wait) { struct video_device *vdev = video_devdata(file); diff --git a/drivers/media/platform/vivid/vivid-radio-rx.c b/drivers/media/platform/vivid/vivid-radio-rx.c index 47c36c26096b..71f3ebb7aecf 100644 --- a/drivers/media/platform/vivid/vivid-radio-rx.c +++ b/drivers/media/platform/vivid/vivid-radio-rx.c @@ -141,7 +141,7 @@ retry: return i; } -unsigned int vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait) +__poll_t vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait) { return POLLIN | POLLRDNORM | v4l2_ctrl_poll(file, wait); } diff --git a/drivers/media/platform/vivid/vivid-radio-rx.h b/drivers/media/platform/vivid/vivid-radio-rx.h index 1077d8f061eb..2b33edb60942 100644 --- a/drivers/media/platform/vivid/vivid-radio-rx.h +++ b/drivers/media/platform/vivid/vivid-radio-rx.h @@ -21,7 +21,7 @@ #define _VIVID_RADIO_RX_H_ ssize_t vivid_radio_rx_read(struct file *, char __user *, size_t, loff_t *); -unsigned int vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait); +__poll_t vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait); int vivid_radio_rx_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band); int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a); diff --git a/drivers/media/platform/vivid/vivid-radio-tx.c b/drivers/media/platform/vivid/vivid-radio-tx.c index 0e8025b7b4dd..f0917f4e7d8c 100644 --- a/drivers/media/platform/vivid/vivid-radio-tx.c +++ b/drivers/media/platform/vivid/vivid-radio-tx.c @@ -105,7 +105,7 @@ retry: return i; } -unsigned int vivid_radio_tx_poll(struct file *file, struct poll_table_struct *wait) +__poll_t vivid_radio_tx_poll(struct file *file, struct poll_table_struct *wait) { return POLLOUT | POLLWRNORM | v4l2_ctrl_poll(file, wait); } diff --git a/drivers/media/platform/vivid/vivid-radio-tx.h b/drivers/media/platform/vivid/vivid-radio-tx.h index 7f8ff7547119..3c3343d70cbc 100644 --- a/drivers/media/platform/vivid/vivid-radio-tx.h +++ b/drivers/media/platform/vivid/vivid-radio-tx.h @@ -21,7 +21,7 @@ #define _VIVID_RADIO_TX_H_ ssize_t vivid_radio_tx_write(struct file *, const char __user *, size_t, loff_t *); -unsigned int vivid_radio_tx_poll(struct file *file, struct poll_table_struct *wait); +__poll_t vivid_radio_tx_poll(struct file *file, struct poll_table_struct *wait); int vidioc_g_modulator(struct file *file, void *fh, struct v4l2_modulator *a); int vidioc_s_modulator(struct file *file, void *fh, const struct v4l2_modulator *a); diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 7a6b3efefedb..dba611003a00 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -481,11 +481,11 @@ static int cadet_release(struct file *file) return 0; } -static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t cadet_poll(struct file *file, struct poll_table_struct *wait) { struct cadet *dev = video_drvdata(file); __poll_t req_events = poll_requested_events(wait); - unsigned int res = v4l2_ctrl_poll(file, wait); + __poll_t res = v4l2_ctrl_poll(file, wait); poll_wait(file, &dev->read_queue, wait); if (dev->rdsstat == 0 && (req_events & (POLLIN | POLLRDNORM))) { diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index fc1bcda38c69..248bd0ffc978 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -1149,12 +1149,12 @@ static ssize_t si476x_radio_fops_read(struct file *file, char __user *buf, return rval; } -static unsigned int si476x_radio_fops_poll(struct file *file, +static __poll_t si476x_radio_fops_poll(struct file *file, struct poll_table_struct *pts) { struct si476x_radio *radio = video_drvdata(file); __poll_t req_events = poll_requested_events(pts); - unsigned int err = v4l2_ctrl_poll(file, pts); + __poll_t err = v4l2_ctrl_poll(file, pts); if (req_events & (POLLIN | POLLRDNORM)) { if (atomic_read(&radio->core->is_alive)) diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index 903fcd5e99c0..4cd4241fc7be 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1089,7 +1089,7 @@ out: return r; } -static unsigned int wl1273_fm_fops_poll(struct file *file, +static __poll_t wl1273_fm_fops_poll(struct file *file, struct poll_table_struct *pts) { struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index b430bbc475fe..68fe9e5c7a70 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -507,12 +507,12 @@ done: /* * si470x_fops_poll - poll RDS data */ -static unsigned int si470x_fops_poll(struct file *file, +static __poll_t si470x_fops_poll(struct file *file, struct poll_table_struct *pts) { struct si470x_device *radio = video_drvdata(file); __poll_t req_events = poll_requested_events(pts); - int retval = v4l2_ctrl_poll(file, pts); + __poll_t retval = v4l2_ctrl_poll(file, pts); if (req_events & (POLLIN | POLLRDNORM)) { /* switch on rds reception */ diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index fc5a7abc83d2..fd603c1b96bb 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -102,7 +102,7 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf, return sizeof(rds); } -static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts) +static __poll_t fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts) { int ret; struct fmdev *fmdev; diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index e16d1138ca48..aab53641838b 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -272,10 +272,10 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file) } EXPORT_SYMBOL(lirc_dev_fop_close); -unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) +__poll_t lirc_dev_fop_poll(struct file *file, poll_table *wait) { struct lirc_dev *d = file->private_data; - unsigned int ret; + __poll_t ret; if (!d->attached) return POLLHUP | POLLERR; diff --git a/drivers/media/usb/cpia2/cpia2.h b/drivers/media/usb/cpia2/cpia2.h index 81f72c0b561f..ab238ac8bfc0 100644 --- a/drivers/media/usb/cpia2/cpia2.h +++ b/drivers/media/usb/cpia2/cpia2.h @@ -444,7 +444,7 @@ int cpia2_allocate_buffers(struct camera_data *cam); void cpia2_free_buffers(struct camera_data *cam); long cpia2_read(struct camera_data *cam, char __user *buf, unsigned long count, int noblock); -unsigned int cpia2_poll(struct camera_data *cam, +__poll_t cpia2_poll(struct camera_data *cam, struct file *filp, poll_table *wait); int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma); void cpia2_set_property_flip(struct camera_data *cam, int prop_val); diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c index 0efba0da0a45..e7524920c618 100644 --- a/drivers/media/usb/cpia2/cpia2_core.c +++ b/drivers/media/usb/cpia2/cpia2_core.c @@ -2370,10 +2370,10 @@ long cpia2_read(struct camera_data *cam, * cpia2_poll * *****************************************************************************/ -unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, +__poll_t cpia2_poll(struct camera_data *cam, struct file *filp, poll_table *wait) { - unsigned int status = v4l2_ctrl_poll(filp, wait); + __poll_t status = v4l2_ctrl_poll(filp, wait); if ((poll_requested_events(wait) & (POLLIN | POLLRDNORM)) && !cam->streaming) { diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index 3dedd83f0b19..74c97565ccc6 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -169,10 +169,10 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, * cpia2_v4l_poll * *****************************************************************************/ -static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) +static __poll_t cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) { struct camera_data *cam = video_drvdata(filp); - unsigned int res; + __poll_t res; mutex_lock(&cam->v4l2_lock); res = cpia2_poll(cam, filp, wait); diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 80231bdee366..103e3299b77f 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1812,13 +1812,13 @@ static ssize_t mpeg_read(struct file *file, char __user *data, file->f_flags & O_NONBLOCK); } -static unsigned int mpeg_poll(struct file *file, +static __poll_t mpeg_poll(struct file *file, struct poll_table_struct *wait) { __poll_t req_events = poll_requested_events(wait); struct cx231xx_fh *fh = file->private_data; struct cx231xx *dev = fh->dev; - unsigned int res = 0; + __poll_t res = 0; if (v4l2_event_pending(&fh->fh)) res |= POLLPRI; diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 3c11ed45d679..d7b2e694bbb9 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -2006,12 +2006,12 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, * cx231xx_v4l2_poll() * will allocate buffers when called for the first time */ -static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait) +static __poll_t cx231xx_v4l2_poll(struct file *filp, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); struct cx231xx_fh *fh = filp->private_data; struct cx231xx *dev = fh->dev; - unsigned res = 0; + __poll_t res = 0; int rc; rc = check_dev(dev); diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 8ebf96f9a3a2..b72d02e225fd 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1862,11 +1862,11 @@ out: return ret; } -static unsigned int dev_poll(struct file *file, poll_table *wait) +static __poll_t dev_poll(struct file *file, poll_table *wait) { struct gspca_dev *gspca_dev = video_drvdata(file); __poll_t req_events = poll_requested_events(wait); - int ret = 0; + __poll_t ret = 0; PDEBUG(D_FRAM, "poll"); diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 35f8a834c76c..d0d638c2e900 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -521,12 +521,12 @@ err: return ret; } -static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) +static __poll_t hdpvr_poll(struct file *filp, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); struct hdpvr_buffer *buf = NULL; struct hdpvr_device *dev = video_drvdata(filp); - unsigned int mask = v4l2_ctrl_poll(filp, wait); + __poll_t mask = v4l2_ctrl_poll(filp, wait); if (!(req_events & (POLLIN | POLLRDNORM))) return mask; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index 4320bda9352d..11cdfe356801 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -1190,9 +1190,9 @@ static ssize_t pvr2_v4l2_read(struct file *file, } -static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait) +static __poll_t pvr2_v4l2_poll(struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; struct pvr2_v4l2_fh *fh = file->private_data; int ret; diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index c0bba773db25..cba0916d33e5 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -721,10 +721,10 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, return ret; } -static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) +static __poll_t v4l_stk_poll(struct file *fp, poll_table *wait) { struct stk_camera *dev = video_drvdata(fp); - unsigned res = v4l2_ctrl_poll(fp, wait); + __poll_t res = v4l2_ctrl_poll(fp, wait); poll_wait(fp, &dev->wait_frame, wait); diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index 16c9dcf3f2cb..317bf5a3933e 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -1423,13 +1423,13 @@ tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) return 0; } -static unsigned int +static __poll_t __tm6000_poll(struct file *file, struct poll_table_struct *wait) { __poll_t req_events = poll_requested_events(wait); struct tm6000_fh *fh = file->private_data; struct tm6000_buffer *buf; - int res = 0; + __poll_t res = 0; if (v4l2_event_pending(&fh->fh)) res = POLLPRI; @@ -1457,11 +1457,11 @@ __tm6000_poll(struct file *file, struct poll_table_struct *wait) return res; } -static unsigned int tm6000_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t tm6000_poll(struct file *file, struct poll_table_struct *wait) { struct tm6000_fh *fh = file->private_data; struct tm6000_core *dev = fh->dev; - unsigned int res; + __poll_t res; mutex_lock(&dev->lock); res = __tm6000_poll(file, wait); diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index c8d78b2f3de4..692c463f14f7 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -340,10 +340,10 @@ unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, } #endif -unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, +__poll_t uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait) { - unsigned int ret; + __poll_t ret; mutex_lock(&queue->mutex); ret = vb2_poll(&queue->queue, file, wait); diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 3e7e283a44a8..ed3bf05e2462 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1423,7 +1423,7 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) return uvc_queue_mmap(&stream->queue, vma); } -static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) +static __poll_t uvc_v4l2_poll(struct file *file, poll_table *wait) { struct uvc_fh *handle = file->private_data; struct uvc_streaming *stream = handle->stream; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 05398784d1c8..9b44a7cd5ec1 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -678,7 +678,7 @@ extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf); extern int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma); -extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, +extern __poll_t uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); #ifndef CONFIG_MMU extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index 1d888661fd03..8b7c19943d46 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -1287,12 +1287,12 @@ static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) return ret; } -static unsigned int zr364xx_poll(struct file *file, +static __poll_t zr364xx_poll(struct file *file, struct poll_table_struct *wait) { struct zr364xx_camera *cam = video_drvdata(file); struct videobuf_queue *q = &cam->vb_vidq; - unsigned res = v4l2_ctrl_poll(file, wait); + __poll_t res = v4l2_ctrl_poll(file, wait); _DBG("%s\n", __func__); diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index cbb2ef43945f..b07657149434 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -3457,7 +3457,7 @@ int v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, } EXPORT_SYMBOL(v4l2_ctrl_subdev_subscribe_event); -unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) +__poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) { struct v4l2_fh *fh = file->private_data; diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index ef178edc634b..8ad8c1627768 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -331,7 +331,7 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, return ret; } -static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) +static __poll_t v4l2_poll(struct file *filp, struct poll_table_struct *poll) { struct video_device *vdev = video_devdata(filp); __poll_t res = POLLERR | POLLHUP; diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index bc6b8f5953be..a879d11866bd 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -498,14 +498,14 @@ int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, } EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff); -unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, +__poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, struct poll_table_struct *wait) { struct video_device *vfd = video_devdata(file); __poll_t req_events = poll_requested_events(wait); struct vb2_queue *src_q, *dst_q; struct vb2_buffer *src_vb = NULL, *dst_vb = NULL; - unsigned int rc = 0; + __poll_t rc = 0; unsigned long flags; if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { @@ -792,11 +792,11 @@ int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma) } EXPORT_SYMBOL_GPL(v4l2_m2m_fop_mmap); -unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait) +__poll_t v4l2_m2m_fop_poll(struct file *file, poll_table *wait) { struct v4l2_fh *fh = file->private_data; struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx; - unsigned int ret; + __poll_t ret; if (m2m_ctx->q_lock) mutex_lock(m2m_ctx->q_lock); diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 43fefa73e0a3..28966fa8c610 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -469,7 +469,7 @@ static long subdev_compat_ioctl32(struct file *file, unsigned int cmd, } #endif -static unsigned int subdev_poll(struct file *file, poll_table *wait) +static __poll_t subdev_poll(struct file *file, poll_table *wait) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c index 83918bfda167..0c5b12b8bb52 100644 --- a/drivers/media/v4l2-core/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c @@ -1118,13 +1118,13 @@ done: } EXPORT_SYMBOL_GPL(videobuf_read_stream); -unsigned int videobuf_poll_stream(struct file *file, +__poll_t videobuf_poll_stream(struct file *file, struct videobuf_queue *q, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); struct videobuf_buffer *buf = NULL; - unsigned int rc = 0; + __poll_t rc = 0; videobuf_queue_lock(q); if (q->streaming) { diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 1a297aea084b..dc1f683c3b71 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2018,7 +2018,7 @@ void vb2_core_queue_release(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_core_queue_release); -unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file, +__poll_t vb2_core_poll(struct vb2_queue *q, struct file *file, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index f7cdc66a06e1..d2b3a74d14fd 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -671,11 +671,11 @@ void vb2_queue_release(struct vb2_queue *q) } EXPORT_SYMBOL_GPL(vb2_queue_release); -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) +__poll_t vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) { struct video_device *vfd = video_devdata(file); __poll_t req_events = poll_requested_events(wait); - unsigned int res = 0; + __poll_t res = 0; if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { struct v4l2_fh *fh = file->private_data; @@ -904,12 +904,12 @@ exit: } EXPORT_SYMBOL_GPL(vb2_fop_read); -unsigned int vb2_fop_poll(struct file *file, poll_table *wait) +__poll_t vb2_fop_poll(struct file *file, poll_table *wait) { struct video_device *vdev = video_devdata(file); struct vb2_queue *q = vdev->queue; struct mutex *lock = q->lock ? q->lock : vdev->lock; - unsigned res; + __poll_t res; void *fileio; /* diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c index dd7596d8763d..6657ebbe068a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c @@ -1255,7 +1255,7 @@ static int atomisp_file_mmap(struct file *file, struct vm_area_struct *vma) return videobuf_mmap_mapper(&pipe->outq, vma); } -static unsigned int atomisp_poll(struct file *file, +static __poll_t atomisp_poll(struct file *file, struct poll_table_struct *pt) { struct video_device *vdev = video_devdata(file); diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index 5d3b0e5a1283..4ffff6f8b809 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -2174,11 +2174,11 @@ static int bcm2048_fops_release(struct file *file) return 0; } -static unsigned int bcm2048_fops_poll(struct file *file, +static __poll_t bcm2048_fops_poll(struct file *file, struct poll_table_struct *pts) { struct bcm2048_device *bdev = video_drvdata(file); - int retval = 0; + __poll_t retval = 0; poll_wait(file, &bdev->read_queue, pts); diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 155e8c758e4b..588743a6fd8a 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -573,7 +573,7 @@ static int vpfe_mmap(struct file *file, struct vm_area_struct *vma) /* * vpfe_poll() - It is used for select/poll system call */ -static unsigned int vpfe_poll(struct file *file, poll_table *wait) +static __poll_t vpfe_poll(struct file *file, poll_table *wait) { struct vpfe_video_device *video = video_drvdata(file); struct vpfe_device *vpfe_dev = video->vpfe_dev; diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 6bd0717bf76e..a003603af725 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -1197,12 +1197,12 @@ static ssize_t write(struct file *filep, const char __user *buf, size_t n, } /* copied from lirc_dev */ -static unsigned int poll(struct file *filep, poll_table *wait) +static __poll_t poll(struct file *filep, poll_table *wait) { struct IR *ir = lirc_get_pdata(filep); struct IR_rx *rx; struct lirc_buffer *rbuf = ir->l->buf; - unsigned int ret; + __poll_t ret; dev_dbg(ir->dev, "%s called\n", __func__); diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 9e2f0421a01e..a3a83424a926 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -1185,7 +1185,7 @@ static int iss_video_release(struct file *file) return 0; } -static unsigned int iss_video_poll(struct file *file, poll_table *wait) +static __poll_t iss_video_poll(struct file *file, poll_table *wait) { struct iss_video_fh *vfh = to_iss_video_fh(file->private_data); diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 278d50ff1eea..9e33d5206d54 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -193,7 +193,7 @@ int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, * This function implements video queue polling and is intended to be used by * the device poll handler. */ -unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file, +__poll_t uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait) { return vb2_poll(&queue->queue, file, wait); diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h index 51ee94e5cf2b..f9f65b5c1062 100644 --- a/drivers/usb/gadget/function/uvc_queue.h +++ b/drivers/usb/gadget/function/uvc_queue.h @@ -72,7 +72,7 @@ int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf); int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, int nonblocking); -unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, +__poll_t uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma); diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index f3069db6f08e..9a9019625496 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -329,7 +329,7 @@ uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) return uvcg_queue_mmap(&uvc->video.queue, vma); } -static unsigned int +static __poll_t uvc_v4l2_poll(struct file *file, poll_table *wait) { struct video_device *vdev = video_devdata(file); diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 857da67bd931..d9c143d17f70 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -185,7 +185,7 @@ void *lirc_get_pdata(struct file *file); */ int lirc_dev_fop_open(struct inode *inode, struct file *file); int lirc_dev_fop_close(struct inode *inode, struct file *file); -unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait); +__poll_t lirc_dev_fop_poll(struct file *file, poll_table *wait); long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg); ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length, loff_t *ppos); diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index dacfe54057f8..a9ced6bbee55 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -1037,7 +1037,7 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, * @file: pointer to struct file * @wait: pointer to struct poll_table_struct */ -unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait); +__poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait); /* Helpers for ioctl_ops */ diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index e157d5c9b224..3d07ba3a8262 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -297,7 +297,7 @@ int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, * indicate that a non-blocking write can be performed, while read will be * returned in case of the destination queue. */ -unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, +__poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, struct poll_table_struct *wait); /** @@ -601,7 +601,7 @@ int v4l2_m2m_ioctl_streamon(struct file *file, void *fh, int v4l2_m2m_ioctl_streamoff(struct file *file, void *fh, enum v4l2_buf_type type); int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma); -unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait); +__poll_t v4l2_m2m_fop_poll(struct file *file, poll_table *wait); #endif /* _MEDIA_V4L2_MEM2MEM_H */ diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index d760aa73ebbb..0bda0adc744f 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -219,7 +219,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, ssize_t videobuf_read_one(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos, int nonblocking); -unsigned int videobuf_poll_stream(struct file *file, +__poll_t videobuf_poll_stream(struct file *file, struct videobuf_queue *q, poll_table *wait); diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index ef9b64398c8c..e55efc62a950 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -871,7 +871,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q, * The return values from this function are intended to be directly returned * from poll handler in driver. */ -unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file, +__poll_t vb2_core_poll(struct vb2_queue *q, struct file *file, poll_table *wait); size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count, diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h index 036127c54bbf..c2fa55657440 100644 --- a/include/media/videobuf2-v4l2.h +++ b/include/media/videobuf2-v4l2.h @@ -226,8 +226,7 @@ void vb2_queue_release(struct vb2_queue *q); * The return values from this function are intended to be directly returned * from poll handler in driver. */ -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, - poll_table *wait); +__poll_t vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait); /* * The following functions are not part of the vb2 core API, but are simple @@ -262,7 +261,7 @@ ssize_t vb2_fop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos); ssize_t vb2_fop_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); -unsigned int vb2_fop_poll(struct file *file, poll_table *wait); +__poll_t vb2_fop_poll(struct file *file, poll_table *wait); #ifndef CONFIG_MMU unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); -- cgit v1.2.3 From 3ad85b08f7789d51e6aad0f535296d1c31e319b9 Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Sun, 10 Sep 2017 03:39:27 +0200 Subject: soc: actions: sps: Add S700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add power domains for S700 SoC. Signed-off-by: Andreas Färber --- drivers/soc/actions/owl-sps.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/actions/owl-sps.c b/drivers/soc/actions/owl-sps.c index 875225bfa21c..8477f0f18e24 100644 --- a/drivers/soc/actions/owl-sps.c +++ b/drivers/soc/actions/owl-sps.c @@ -17,6 +17,7 @@ #include #include #include +#include struct owl_sps_domain_info { const char *name; @@ -203,8 +204,49 @@ static const struct owl_sps_info s500_sps_info = { .domains = s500_sps_domains, }; +static const struct owl_sps_domain_info s700_sps_domains[] = { + [S700_PD_VDE] = { + .name = "VDE", + .pwr_bit = 0, + }, + [S700_PD_VCE_SI] = { + .name = "VCE_SI", + .pwr_bit = 1, + }, + [S700_PD_USB2_1] = { + .name = "USB2_1", + .pwr_bit = 2, + }, + [S700_PD_HDE] = { + .name = "HDE", + .pwr_bit = 7, + }, + [S700_PD_DMA] = { + .name = "DMA", + .pwr_bit = 8, + }, + [S700_PD_DS] = { + .name = "DS", + .pwr_bit = 9, + }, + [S700_PD_USB3] = { + .name = "USB3", + .pwr_bit = 10, + }, + [S700_PD_USB2_0] = { + .name = "USB2_0", + .pwr_bit = 11, + }, +}; + +static const struct owl_sps_info s700_sps_info = { + .num_domains = ARRAY_SIZE(s700_sps_domains), + .domains = s700_sps_domains, +}; + static const struct of_device_id owl_sps_of_matches[] = { { .compatible = "actions,s500-sps", .data = &s500_sps_info }, + { .compatible = "actions,s700-sps", .data = &s700_sps_info }, { } }; -- cgit v1.2.3 From d8a42b1ff8a3755cc710785c7e4b5e59636399ca Mon Sep 17 00:00:00 2001 From: Gimcuan Hui Date: Mon, 27 Nov 2017 15:36:51 +0000 Subject: USB: serial: ark3116: clean up return values of register accessors write_reg returns 0 on success, we can make it more explicit by returning number 0 instead of result variable. read_reg should return 0 on success since this is a more common pattern. The user of read_reg has been clean-up and should be at the same commit. Signed-off-by: Gimcuan Hui Signed-off-by: Johan Hovold --- drivers/usb/serial/ark3116.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 3c544782f60b..23d46ef87d64 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -83,7 +83,10 @@ static int ark3116_write_reg(struct usb_serial *serial, usb_sndctrlpipe(serial->dev, 0), 0xfe, 0x40, val, reg, NULL, 0, ARK_TIMEOUT); - return result; + if (result) + return result; + + return 0; } static int ark3116_read_reg(struct usb_serial *serial, @@ -105,7 +108,7 @@ static int ark3116_read_reg(struct usb_serial *serial, return result; } - return buf[0]; + return 0; } static inline int calc_divisor(int bps) @@ -355,13 +358,13 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) /* read modem status */ result = ark3116_read_reg(serial, UART_MSR, buf); - if (result < 0) + if (result) goto err_close; priv->msr = *buf; /* read line status */ result = ark3116_read_reg(serial, UART_LSR, buf); - if (result < 0) + if (result) goto err_close; priv->lsr = *buf; -- cgit v1.2.3 From 3f35221842305e82494e10fcfc1f5750c8bc682a Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Tue, 7 Nov 2017 15:10:43 +0000 Subject: pinctrl: sh-pfc: r8a7745: Add CAN[01] support This patch adds PFC CAN0 and CAN1 pin groups and functions, enabling CAN bus on the RZ/G1E. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7794.c | 146 +++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c index 333a3470e842..e5b3d5fa4aa0 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c @@ -1608,6 +1608,116 @@ static const unsigned int avb_gmii_mux[] = { AVB_TX_EN_MARK, AVB_TX_ER_MARK, AVB_TX_CLK_MARK, AVB_COL_MARK, }; + +/* - CAN -------------------------------------------------------------------- */ +static const unsigned int can0_data_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(6, 15), RCAR_GP_PIN(6, 14), +}; + +static const unsigned int can0_data_mux[] = { + CAN0_TX_MARK, CAN0_RX_MARK, +}; + +static const unsigned int can0_data_b_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 15), +}; + +static const unsigned int can0_data_b_mux[] = { + CAN0_TX_B_MARK, CAN0_RX_B_MARK, +}; + +static const unsigned int can0_data_c_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 16), +}; + +static const unsigned int can0_data_c_mux[] = { + CAN0_TX_C_MARK, CAN0_RX_C_MARK, +}; + +static const unsigned int can0_data_d_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(5, 12), RCAR_GP_PIN(5, 11), +}; + +static const unsigned int can0_data_d_mux[] = { + CAN0_TX_D_MARK, CAN0_RX_D_MARK, +}; + +static const unsigned int can1_data_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(6, 25), RCAR_GP_PIN(6, 24), +}; + +static const unsigned int can1_data_mux[] = { + CAN1_TX_MARK, CAN1_RX_MARK, +}; + +static const unsigned int can1_data_b_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 1), +}; + +static const unsigned int can1_data_b_mux[] = { + CAN1_TX_B_MARK, CAN1_RX_B_MARK, +}; + +static const unsigned int can1_data_c_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 5), +}; + +static const unsigned int can1_data_c_mux[] = { + CAN1_TX_C_MARK, CAN1_RX_C_MARK, +}; + +static const unsigned int can1_data_d_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(3, 31), RCAR_GP_PIN(3, 30), +}; + +static const unsigned int can1_data_d_mux[] = { + CAN1_TX_D_MARK, CAN1_RX_D_MARK, +}; + +static const unsigned int can_clk_pins[] = { + /* CLK */ + RCAR_GP_PIN(3, 31), +}; + +static const unsigned int can_clk_mux[] = { + CAN_CLK_MARK, +}; + +static const unsigned int can_clk_b_pins[] = { + /* CLK */ + RCAR_GP_PIN(1, 23), +}; + +static const unsigned int can_clk_b_mux[] = { + CAN_CLK_B_MARK, +}; + +static const unsigned int can_clk_c_pins[] = { + /* CLK */ + RCAR_GP_PIN(1, 0), +}; + +static const unsigned int can_clk_c_mux[] = { + CAN_CLK_C_MARK, +}; + +static const unsigned int can_clk_d_pins[] = { + /* CLK */ + RCAR_GP_PIN(5, 0), +}; + +static const unsigned int can_clk_d_mux[] = { + CAN_CLK_D_MARK, +}; + /* - DU --------------------------------------------------------------------- */ static const unsigned int du0_rgb666_pins[] = { /* R[7:2], G[7:2], B[7:2] */ @@ -3459,6 +3569,18 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(avb_mdio), SH_PFC_PIN_GROUP(avb_mii), SH_PFC_PIN_GROUP(avb_gmii), + SH_PFC_PIN_GROUP(can0_data), + SH_PFC_PIN_GROUP(can0_data_b), + SH_PFC_PIN_GROUP(can0_data_c), + SH_PFC_PIN_GROUP(can0_data_d), + SH_PFC_PIN_GROUP(can1_data), + SH_PFC_PIN_GROUP(can1_data_b), + SH_PFC_PIN_GROUP(can1_data_c), + SH_PFC_PIN_GROUP(can1_data_d), + SH_PFC_PIN_GROUP(can_clk), + SH_PFC_PIN_GROUP(can_clk_b), + SH_PFC_PIN_GROUP(can_clk_c), + SH_PFC_PIN_GROUP(can_clk_d), SH_PFC_PIN_GROUP(du0_rgb666), SH_PFC_PIN_GROUP(du0_rgb888), SH_PFC_PIN_GROUP(du0_clk0_out), @@ -3731,6 +3853,28 @@ static const char * const avb_groups[] = { "avb_gmii", }; +static const char * const can0_groups[] = { + "can0_data", + "can0_data_b", + "can0_data_c", + "can0_data_d", + "can_clk", + "can_clk_b", + "can_clk_c", + "can_clk_d", +}; + +static const char * const can1_groups[] = { + "can1_data", + "can1_data_b", + "can1_data_c", + "can1_data_d", + "can_clk", + "can_clk_b", + "can_clk_c", + "can_clk_d", +}; + static const char * const du0_groups[] = { "du0_rgb666", "du0_rgb888", @@ -4102,6 +4246,8 @@ static const char * const vin1_groups[] = { static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(audio_clk), SH_PFC_FUNCTION(avb), + SH_PFC_FUNCTION(can0), + SH_PFC_FUNCTION(can1), SH_PFC_FUNCTION(du0), SH_PFC_FUNCTION(du1), SH_PFC_FUNCTION(eth), -- cgit v1.2.3 From a678abfee7ab5d2dcfc2079158ec799c7f4cf204 Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Fri, 10 Nov 2017 13:58:49 +0000 Subject: pinctrl: sh-pfc: r8a7795: Add CAN support This patch adds CAN[0-1] pinmux support for R-Car H3 ES2.0. The pin config is identical to H3 ES1.*. Signed-off-by: Ramesh Shanmugasundaram Reviewed-by: Fabrizio Castro Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index d1cec6d12e81..59249a990cef 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -1781,6 +1781,38 @@ static const unsigned int avb_avtp_capture_b_mux[] = { AVB_AVTP_CAPTURE_B_MARK, }; +/* - CAN ------------------------------------------------------------------ */ +static const unsigned int can0_data_a_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24), +}; +static const unsigned int can0_data_a_mux[] = { + CAN0_TX_A_MARK, CAN0_RX_A_MARK, +}; +static const unsigned int can0_data_b_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1), +}; +static const unsigned int can0_data_b_mux[] = { + CAN0_TX_B_MARK, CAN0_RX_B_MARK, +}; +static const unsigned int can1_data_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 26), +}; +static const unsigned int can1_data_mux[] = { + CAN1_TX_MARK, CAN1_RX_MARK, +}; + +/* - CAN Clock -------------------------------------------------------------- */ +static const unsigned int can_clk_pins[] = { + /* CLK */ + RCAR_GP_PIN(1, 25), +}; +static const unsigned int can_clk_mux[] = { + CAN_CLK_MARK, +}; + /* - DRIF0 --------------------------------------------------------------- */ static const unsigned int drif0_ctrl_a_pins[] = { /* CLK, SYNC */ @@ -3843,6 +3875,10 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(avb_avtp_capture_a), SH_PFC_PIN_GROUP(avb_avtp_match_b), SH_PFC_PIN_GROUP(avb_avtp_capture_b), + SH_PFC_PIN_GROUP(can0_data_a), + SH_PFC_PIN_GROUP(can0_data_b), + SH_PFC_PIN_GROUP(can1_data), + SH_PFC_PIN_GROUP(can_clk), SH_PFC_PIN_GROUP(drif0_ctrl_a), SH_PFC_PIN_GROUP(drif0_data0_a), SH_PFC_PIN_GROUP(drif0_data1_a), @@ -4154,6 +4190,19 @@ static const char * const avb_groups[] = { "avb_avtp_capture_b", }; +static const char * const can0_groups[] = { + "can0_data_a", + "can0_data_b", +}; + +static const char * const can1_groups[] = { + "can1_data", +}; + +static const char * const can_clk_groups[] = { + "can_clk", +}; + static const char * const drif0_groups[] = { "drif0_ctrl_a", "drif0_data0_a", @@ -4559,6 +4608,9 @@ static const char * const usb30_groups[] = { static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(audio_clk), SH_PFC_FUNCTION(avb), + SH_PFC_FUNCTION(can0), + SH_PFC_FUNCTION(can1), + SH_PFC_FUNCTION(can_clk), SH_PFC_FUNCTION(drif0), SH_PFC_FUNCTION(drif1), SH_PFC_FUNCTION(drif2), -- cgit v1.2.3 From 0e1c7a94c6def25fa2458ad4577b0b9b40443c3b Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Fri, 10 Nov 2017 13:58:50 +0000 Subject: pinctrl: sh-pfc: r8a7795: Add CAN FD support This patch adds CAN FD[0-1] pinmux support for R-Car H3 ES2.0. The pin config is identical to H3 ES1.*. Signed-off-by: Ramesh Shanmugasundaram Reviewed-by: Fabrizio Castro Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index 59249a990cef..34a2dc471e5a 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -1813,6 +1813,29 @@ static const unsigned int can_clk_mux[] = { CAN_CLK_MARK, }; +/* - CAN FD --------------------------------------------------------------- */ +static const unsigned int canfd0_data_a_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24), +}; +static const unsigned int canfd0_data_a_mux[] = { + CANFD0_TX_A_MARK, CANFD0_RX_A_MARK, +}; +static const unsigned int canfd0_data_b_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1), +}; +static const unsigned int canfd0_data_b_mux[] = { + CANFD0_TX_B_MARK, CANFD0_RX_B_MARK, +}; +static const unsigned int canfd1_data_pins[] = { + /* TX, RX */ + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 26), +}; +static const unsigned int canfd1_data_mux[] = { + CANFD1_TX_MARK, CANFD1_RX_MARK, +}; + /* - DRIF0 --------------------------------------------------------------- */ static const unsigned int drif0_ctrl_a_pins[] = { /* CLK, SYNC */ @@ -3879,6 +3902,9 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(can0_data_b), SH_PFC_PIN_GROUP(can1_data), SH_PFC_PIN_GROUP(can_clk), + SH_PFC_PIN_GROUP(canfd0_data_a), + SH_PFC_PIN_GROUP(canfd0_data_b), + SH_PFC_PIN_GROUP(canfd1_data), SH_PFC_PIN_GROUP(drif0_ctrl_a), SH_PFC_PIN_GROUP(drif0_data0_a), SH_PFC_PIN_GROUP(drif0_data1_a), @@ -4203,6 +4229,15 @@ static const char * const can_clk_groups[] = { "can_clk", }; +static const char * const canfd0_groups[] = { + "canfd0_data_a", + "canfd0_data_b", +}; + +static const char * const canfd1_groups[] = { + "canfd1_data", +}; + static const char * const drif0_groups[] = { "drif0_ctrl_a", "drif0_data0_a", @@ -4611,6 +4646,8 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(can0), SH_PFC_FUNCTION(can1), SH_PFC_FUNCTION(can_clk), + SH_PFC_FUNCTION(canfd0), + SH_PFC_FUNCTION(canfd1), SH_PFC_FUNCTION(drif0), SH_PFC_FUNCTION(drif1), SH_PFC_FUNCTION(drif2), -- cgit v1.2.3 From 5a0e698876479b71de885fdc181c00ecee5a61a9 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 10 Nov 2017 20:59:00 +0300 Subject: pinctrl: sh-pfc: Add PORT_GP_CFG_{6|22}() helper macros They follow the style of the existing PORT_GP_CFG_() macros and will be used by a follow-up patch for the R8A77970 SoC. Based on the original (and large) patch by Daisuke Matsushita . Signed-off-by: Vladimir Barinov Signed-off-by: Sergei Shtylyov Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/sh_pfc.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 213108a058fe..efe07bcca8d0 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -389,10 +389,14 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info; PORT_GP_CFG_1(bank, 3, fn, sfx, cfg) #define PORT_GP_4(bank, fn, sfx) PORT_GP_CFG_4(bank, fn, sfx, 0) -#define PORT_GP_CFG_8(bank, fn, sfx, cfg) \ +#define PORT_GP_CFG_6(bank, fn, sfx, cfg) \ PORT_GP_CFG_4(bank, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), \ - PORT_GP_CFG_1(bank, 5, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 5, fn, sfx, cfg) +#define PORT_GP_6(bank, fn, sfx) PORT_GP_CFG_6(bank, fn, sfx, 0) + +#define PORT_GP_CFG_8(bank, fn, sfx, cfg) \ + PORT_GP_CFG_6(bank, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 6, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 7, fn, sfx, cfg) #define PORT_GP_8(bank, fn, sfx) PORT_GP_CFG_8(bank, fn, sfx, 0) @@ -450,9 +454,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info; PORT_GP_CFG_1(bank, 20, fn, sfx, cfg) #define PORT_GP_21(bank, fn, sfx) PORT_GP_CFG_21(bank, fn, sfx, 0) -#define PORT_GP_CFG_23(bank, fn, sfx, cfg) \ +#define PORT_GP_CFG_22(bank, fn, sfx, cfg) \ PORT_GP_CFG_21(bank, fn, sfx, cfg), \ - PORT_GP_CFG_1(bank, 21, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 21, fn, sfx, cfg) +#define PORT_GP_22(bank, fn, sfx) PORT_GP_CFG_22(bank, fn, sfx, 0) + +#define PORT_GP_CFG_23(bank, fn, sfx, cfg) \ + PORT_GP_CFG_22(bank, fn, sfx, cfg), \ PORT_GP_CFG_1(bank, 22, fn, sfx, cfg) #define PORT_GP_23(bank, fn, sfx) PORT_GP_CFG_23(bank, fn, sfx, 0) -- cgit v1.2.3 From 10c9ef045a7e19e9fd4c829c7321f9d2048808c0 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Tue, 28 Nov 2017 11:09:10 +0800 Subject: i2c: core: fix compile issue related to incorrect gpio header The correct header to include for the gpiod interface is . Fixes: 3991c5c80beaf7eb9 ("i2c: Switch to using gpiod interface for gpio bus recovery") Signed-off-by: Phil Reid Reviewed-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 54ffc8da40df..bf52cca87363 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 4d67c2e7f60dbf5a3cf65f6773c73e12970b0fe0 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Tue, 28 Nov 2017 11:09:11 +0800 Subject: i2c: designware: fix building driver as module The designware core and platform are built as separate modules. Export i2c_dw_prepare_clk() so it can be used by the platform driver. Fixes: a34a0b6da22540d19e57 ("i2c: designware: move i2c_dw_plat_prepare_clk to common") Signed-off-by: Phil Reid Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 6b82809647dc..27ebd90de43b 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -197,6 +197,7 @@ int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare) clk_disable_unprepare(dev->clk); return 0; } +EXPORT_SYMBOL_GPL(i2c_dw_prepare_clk); int i2c_dw_acquire_lock(struct dw_i2c_dev *dev) { -- cgit v1.2.3 From e184e2bed8fc895ce930624524d319289c1f1082 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 14:58:43 +0100 Subject: staging: comedi: add SPDX identifiers to all greybus driver files It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the drivers/staging/comedi files files with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: Ian Abbott Cc: H Hartley Sweeten Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 1 + drivers/staging/comedi/comedi_buf.c | 1 + drivers/staging/comedi/comedi_compat32.c | 1 + drivers/staging/comedi/comedi_compat32.h | 1 + drivers/staging/comedi/comedi_fops.c | 1 + drivers/staging/comedi/comedi_pci.c | 1 + drivers/staging/comedi/comedi_pci.h | 1 + drivers/staging/comedi/comedi_pcmcia.c | 1 + drivers/staging/comedi/comedi_pcmcia.h | 1 + drivers/staging/comedi/comedi_usb.c | 1 + drivers/staging/comedi/comedi_usb.h | 1 + drivers/staging/comedi/comedidev.h | 1 + drivers/staging/comedi/comedilib.h | 1 + drivers/staging/comedi/drivers.c | 1 + drivers/staging/comedi/drivers/8255.c | 1 + drivers/staging/comedi/drivers/8255.h | 1 + drivers/staging/comedi/drivers/8255_pci.c | 1 + drivers/staging/comedi/drivers/addi_apci_1032.c | 1 + drivers/staging/comedi/drivers/addi_apci_1500.c | 1 + drivers/staging/comedi/drivers/addi_apci_1516.c | 1 + drivers/staging/comedi/drivers/addi_apci_1564.c | 1 + drivers/staging/comedi/drivers/addi_apci_16xx.c | 1 + drivers/staging/comedi/drivers/addi_apci_2032.c | 1 + drivers/staging/comedi/drivers/addi_apci_2200.c | 1 + drivers/staging/comedi/drivers/addi_apci_3120.c | 1 + drivers/staging/comedi/drivers/addi_apci_3501.c | 1 + drivers/staging/comedi/drivers/addi_apci_3xxx.c | 1 + drivers/staging/comedi/drivers/addi_watchdog.c | 1 + drivers/staging/comedi/drivers/adl_pci6208.c | 1 + drivers/staging/comedi/drivers/adl_pci7x3x.c | 1 + drivers/staging/comedi/drivers/adl_pci8164.c | 1 + drivers/staging/comedi/drivers/adl_pci9111.c | 1 + drivers/staging/comedi/drivers/adl_pci9118.c | 1 + drivers/staging/comedi/drivers/adq12b.c | 1 + drivers/staging/comedi/drivers/adv_pci1710.c | 1 + drivers/staging/comedi/drivers/adv_pci1720.c | 1 + drivers/staging/comedi/drivers/adv_pci1723.c | 1 + drivers/staging/comedi/drivers/adv_pci1724.c | 1 + drivers/staging/comedi/drivers/adv_pci1760.c | 1 + drivers/staging/comedi/drivers/adv_pci_dio.c | 1 + drivers/staging/comedi/drivers/aio_aio12_8.c | 1 + drivers/staging/comedi/drivers/aio_iiro_16.c | 1 + drivers/staging/comedi/drivers/amplc_dio200.c | 1 + drivers/staging/comedi/drivers/amplc_dio200.h | 1 + drivers/staging/comedi/drivers/amplc_dio200_common.c | 1 + drivers/staging/comedi/drivers/amplc_dio200_pci.c | 1 + drivers/staging/comedi/drivers/amplc_pc236.c | 1 + drivers/staging/comedi/drivers/amplc_pc236.h | 1 + drivers/staging/comedi/drivers/amplc_pc236_common.c | 1 + drivers/staging/comedi/drivers/amplc_pc263.c | 1 + drivers/staging/comedi/drivers/amplc_pci224.c | 1 + drivers/staging/comedi/drivers/amplc_pci230.c | 1 + drivers/staging/comedi/drivers/amplc_pci236.c | 1 + drivers/staging/comedi/drivers/amplc_pci263.c | 1 + drivers/staging/comedi/drivers/c6xdigio.c | 1 + drivers/staging/comedi/drivers/cb_das16_cs.c | 1 + drivers/staging/comedi/drivers/cb_pcidas.c | 1 + drivers/staging/comedi/drivers/cb_pcidas64.c | 1 + drivers/staging/comedi/drivers/cb_pcidda.c | 1 + drivers/staging/comedi/drivers/cb_pcimdas.c | 1 + drivers/staging/comedi/drivers/cb_pcimdda.c | 1 + drivers/staging/comedi/drivers/comedi_8254.c | 1 + drivers/staging/comedi/drivers/comedi_8254.h | 1 + drivers/staging/comedi/drivers/comedi_8255.c | 1 + drivers/staging/comedi/drivers/comedi_bond.c | 1 + drivers/staging/comedi/drivers/comedi_isadma.c | 1 + drivers/staging/comedi/drivers/comedi_isadma.h | 1 + drivers/staging/comedi/drivers/comedi_parport.c | 1 + drivers/staging/comedi/drivers/comedi_test.c | 1 + drivers/staging/comedi/drivers/contec_pci_dio.c | 1 + drivers/staging/comedi/drivers/dac02.c | 1 + drivers/staging/comedi/drivers/daqboard2000.c | 1 + drivers/staging/comedi/drivers/das08.c | 1 + drivers/staging/comedi/drivers/das08.h | 1 + drivers/staging/comedi/drivers/das08_cs.c | 1 + drivers/staging/comedi/drivers/das08_isa.c | 1 + drivers/staging/comedi/drivers/das08_pci.c | 1 + drivers/staging/comedi/drivers/das16.c | 1 + drivers/staging/comedi/drivers/das16m1.c | 1 + drivers/staging/comedi/drivers/das1800.c | 1 + drivers/staging/comedi/drivers/das6402.c | 1 + drivers/staging/comedi/drivers/das800.c | 1 + drivers/staging/comedi/drivers/dmm32at.c | 1 + drivers/staging/comedi/drivers/dt2801.c | 1 + drivers/staging/comedi/drivers/dt2811.c | 1 + drivers/staging/comedi/drivers/dt2814.c | 1 + drivers/staging/comedi/drivers/dt2815.c | 1 + drivers/staging/comedi/drivers/dt2817.c | 1 + drivers/staging/comedi/drivers/dt282x.c | 1 + drivers/staging/comedi/drivers/dt3000.c | 1 + drivers/staging/comedi/drivers/dt9812.c | 1 + drivers/staging/comedi/drivers/dyna_pci10xx.c | 1 + drivers/staging/comedi/drivers/fl512.c | 1 + drivers/staging/comedi/drivers/gsc_hpdi.c | 1 + drivers/staging/comedi/drivers/icp_multi.c | 1 + drivers/staging/comedi/drivers/ii_pci20kc.c | 1 + drivers/staging/comedi/drivers/jr3_pci.c | 1 + drivers/staging/comedi/drivers/ke_counter.c | 1 + drivers/staging/comedi/drivers/me4000.c | 1 + drivers/staging/comedi/drivers/me_daq.c | 1 + drivers/staging/comedi/drivers/mf6x4.c | 1 + drivers/staging/comedi/drivers/mite.c | 1 + drivers/staging/comedi/drivers/mite.h | 1 + drivers/staging/comedi/drivers/mpc624.c | 1 + drivers/staging/comedi/drivers/multiq3.c | 1 + drivers/staging/comedi/drivers/ni_6527.c | 1 + drivers/staging/comedi/drivers/ni_65xx.c | 1 + drivers/staging/comedi/drivers/ni_660x.c | 1 + drivers/staging/comedi/drivers/ni_670x.c | 1 + drivers/staging/comedi/drivers/ni_at_a2150.c | 1 + drivers/staging/comedi/drivers/ni_at_ao.c | 1 + drivers/staging/comedi/drivers/ni_atmio.c | 1 + drivers/staging/comedi/drivers/ni_atmio16d.c | 1 + drivers/staging/comedi/drivers/ni_daq_700.c | 1 + drivers/staging/comedi/drivers/ni_daq_dio24.c | 1 + drivers/staging/comedi/drivers/ni_labpc.c | 1 + drivers/staging/comedi/drivers/ni_labpc.h | 1 + drivers/staging/comedi/drivers/ni_labpc_common.c | 1 + drivers/staging/comedi/drivers/ni_labpc_cs.c | 1 + drivers/staging/comedi/drivers/ni_labpc_isadma.c | 1 + drivers/staging/comedi/drivers/ni_labpc_pci.c | 1 + drivers/staging/comedi/drivers/ni_mio_common.c | 1 + drivers/staging/comedi/drivers/ni_mio_cs.c | 1 + drivers/staging/comedi/drivers/ni_pcidio.c | 1 + drivers/staging/comedi/drivers/ni_pcimio.c | 1 + drivers/staging/comedi/drivers/ni_stc.h | 1 + drivers/staging/comedi/drivers/ni_tio.c | 1 + drivers/staging/comedi/drivers/ni_tio.h | 1 + drivers/staging/comedi/drivers/ni_tio_internal.h | 1 + drivers/staging/comedi/drivers/ni_tiocmd.c | 1 + drivers/staging/comedi/drivers/ni_usb6501.c | 1 + drivers/staging/comedi/drivers/pcl711.c | 1 + drivers/staging/comedi/drivers/pcl724.c | 1 + drivers/staging/comedi/drivers/pcl726.c | 1 + drivers/staging/comedi/drivers/pcl730.c | 1 + drivers/staging/comedi/drivers/pcl812.c | 1 + drivers/staging/comedi/drivers/pcl816.c | 1 + drivers/staging/comedi/drivers/pcl818.c | 1 + drivers/staging/comedi/drivers/pcm3724.c | 1 + drivers/staging/comedi/drivers/pcmad.c | 1 + drivers/staging/comedi/drivers/pcmda12.c | 1 + drivers/staging/comedi/drivers/pcmmio.c | 1 + drivers/staging/comedi/drivers/pcmuio.c | 1 + drivers/staging/comedi/drivers/plx9052.h | 1 + drivers/staging/comedi/drivers/plx9080.h | 1 + drivers/staging/comedi/drivers/rtd520.c | 1 + drivers/staging/comedi/drivers/rti800.c | 1 + drivers/staging/comedi/drivers/rti802.c | 1 + drivers/staging/comedi/drivers/s526.c | 1 + drivers/staging/comedi/drivers/s626.c | 1 + drivers/staging/comedi/drivers/s626.h | 1 + drivers/staging/comedi/drivers/serial2002.c | 1 + drivers/staging/comedi/drivers/ssv_dnp.c | 1 + drivers/staging/comedi/drivers/usbdux.c | 1 + drivers/staging/comedi/drivers/usbduxfast.c | 1 + drivers/staging/comedi/drivers/usbduxsigma.c | 1 + drivers/staging/comedi/drivers/vmk80xx.c | 1 + drivers/staging/comedi/kcomedilib/kcomedilib_main.c | 1 + drivers/staging/comedi/proc.c | 1 + drivers/staging/comedi/range.c | 1 + 160 files changed, 160 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index a1c1081906c5..e915e42ab47f 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: LGPL-2.0+ /* * comedi.h * header file for COMEDI user API diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index b455ff6714eb..e75d41ac2a19 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_buf.c * diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index f356386d833a..26c62f7e6249 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/comedi_compat32.c * 32-bit ioctl compatibility for 64-bit comedi kernel module. diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h index 0127c1f98bbf..9fa8ed2b8d41 100644 --- a/drivers/staging/comedi/comedi_compat32.h +++ b/drivers/staging/comedi/comedi_compat32.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/comedi_compat32.h * 32-bit ioctl compatibility for 64-bit comedi kernel module. diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index e19e395b0e44..da7999777d39 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/comedi_fops.c * comedi kernel module diff --git a/drivers/staging/comedi/comedi_pci.c b/drivers/staging/comedi/comedi_pci.c index 51e023a1c0ee..02467227b2dd 100644 --- a/drivers/staging/comedi/comedi_pci.c +++ b/drivers/staging/comedi/comedi_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_pci.c * Comedi PCI driver specific functions. diff --git a/drivers/staging/comedi/comedi_pci.h b/drivers/staging/comedi/comedi_pci.h index 7dfd892c74b0..b1fbec67dd1a 100644 --- a/drivers/staging/comedi/comedi_pci.h +++ b/drivers/staging/comedi/comedi_pci.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_pci.h * header file for Comedi PCI drivers diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c index cd4742851c08..7d4fd01011a9 100644 --- a/drivers/staging/comedi/comedi_pcmcia.c +++ b/drivers/staging/comedi/comedi_pcmcia.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_pcmcia.c * Comedi PCMCIA driver specific functions. diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h index 9e45c7c93278..66fd313902c7 100644 --- a/drivers/staging/comedi/comedi_pcmcia.h +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_pcmcia.h * header file for Comedi PCMCIA drivers diff --git a/drivers/staging/comedi/comedi_usb.c b/drivers/staging/comedi/comedi_usb.c index 9c946d40b894..85e680b5f462 100644 --- a/drivers/staging/comedi/comedi_usb.c +++ b/drivers/staging/comedi/comedi_usb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_usb.c * Comedi USB driver specific functions. diff --git a/drivers/staging/comedi/comedi_usb.h b/drivers/staging/comedi/comedi_usb.h index 132154ec792f..43920b2d2f7e 100644 --- a/drivers/staging/comedi/comedi_usb.h +++ b/drivers/staging/comedi/comedi_usb.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_usb.h * header file for USB Comedi drivers diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 1bb9986f865e..01117344eaed 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedidev.h * header file for kernel-only structures, variables, and constants diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h index f9b56396e161..d37bdebcc7ea 100644 --- a/drivers/staging/comedi/comedilib.h +++ b/drivers/staging/comedi/comedilib.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedilib.h * Header file for kcomedilib diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 0b43db6371c6..393dd5c708ba 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * module/drivers.c * functions for manipulating drivers diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index b79d3764a8a0..ad9488ef97b6 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/8255.c * Driver for 8255 diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h index 55a67af5152d..410dc101f550 100644 --- a/drivers/staging/comedi/drivers/8255.h +++ b/drivers/staging/comedi/drivers/8255.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * module/8255.h * Header file for 8255 diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 38c05d1ec647..cb3db46b3c95 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for generic PCI based 8255 digital i/o boards * Copyright (C) 2012 H Hartley Sweeten diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index ccd1a91290bf..d178b35ba459 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1032.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 63991c49ff23..05d7d3e192c5 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1500.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index f1f8b1c422a7..e1a28d80db45 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1516.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 9bfb79c2e5c8..1956a169f78b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_1564.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index c63133a12a4e..5e81b0008943 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_16xx.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index 50f9eb25d7cb..5ab5a1a99608 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_2032.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index 2b382a52d80d..8ccd0fc81081 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_2200.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 3630d75e36e8..8db5ce609eec 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_3120.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 1fdc0f8d7e1a..2cc87818b148 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_3501.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index be1f6133ff1c..dd9a23af97bd 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * addi_apci_3xxx.c * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c index 9d9853fe54a0..c74ddf62490a 100644 --- a/drivers/staging/comedi/drivers/addi_watchdog.c +++ b/drivers/staging/comedi/drivers/addi_watchdog.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for the watchdog subdevice found on some addi-data boards * Copyright (c) 2013 H Hartley Sweeten diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index ad7e7c4a5232..6901f703cebe 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adl_pci6208.c * Comedi driver for ADLink 6208 series cards diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index b0fc027cf485..7cacb7fb53d3 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for the ADLINK PCI-723x/743x series boards. * Copyright (C) 2012 H Hartley Sweeten diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index da901c8dec0e..0403679d5a58 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/adl_pci8164.c * diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 01d2ee931b28..c5b1d5312178 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adl_pci9111.c * Hardware driver for PCI9111 ADLink cards: PCI-9111HR diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 1cc9b7ef1ff9..2528ca0ede6d 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/adl_pci9118.c * diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 315050454c26..630933d7799a 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adq12b.c * Driver for MicroAxial ADQ12-B data acquisition and control card diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 2c1b6de30da8..6a93b04f1fdf 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * adv_pci1710.c * Comedi driver for Advantech PCI-1710 series boards diff --git a/drivers/staging/comedi/drivers/adv_pci1720.c b/drivers/staging/comedi/drivers/adv_pci1720.c index 4830a1c93d15..7951f8b84649 100644 --- a/drivers/staging/comedi/drivers/adv_pci1720.c +++ b/drivers/staging/comedi/drivers/adv_pci1720.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for Advantech PCI-1720U * Copyright (c) 2015 H Hartley Sweeten diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index f82afd947310..1515fde4d990 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adv_pci1723.c * Comedi driver for the Advantech PCI-1723 card. diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index bf6a8f10118c..2898bd01219b 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * adv_pci1724.c * Comedi driver for the Advantech PCI-1724U card. diff --git a/drivers/staging/comedi/drivers/adv_pci1760.c b/drivers/staging/comedi/drivers/adv_pci1760.c index 9f525ff7290c..fa42255827b1 100644 --- a/drivers/staging/comedi/drivers/adv_pci1760.c +++ b/drivers/staging/comedi/drivers/adv_pci1760.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI driver for the Advantech PCI-1760 * Copyright (C) 2015 H Hartley Sweeten diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index a8186687ca2c..5fef2aef7e03 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/adv_pci_dio.c * diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 43a0ce5721d3..6e018fef315a 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * aio_aio12_8.c * Driver for Access I/O Products PC-104 AIO12-8 Analog I/O Board diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 35b2f98f0de9..1a3e0df689e5 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * aio_iiro_16.c * Comedi driver for Access I/O Products 104-IIRO-16 board diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index f5cfa71a90c6..97f21964546c 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_dio200.c * diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h index 53fb86d59fc3..eeb18d917f07 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.h +++ b/drivers/staging/comedi/drivers/amplc_dio200.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_dio.h * diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index f6e4e984235d..ae22cfcf67fe 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_dio200_common.c * diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c index 2598e6e7d47d..4bd59388a2ff 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* comedi/drivers/amplc_dio200_pci.c * * Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296. diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 875cc19cb969..dfc4fee4cd11 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pc236.c * Driver for Amplicon PC36AT DIO boards. diff --git a/drivers/staging/comedi/drivers/amplc_pc236.h b/drivers/staging/comedi/drivers/amplc_pc236.h index 91d6d9c065b5..af12477c3c85 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.h +++ b/drivers/staging/comedi/drivers/amplc_pc236.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pc236.h * Header for "amplc_pc236", "amplc_pci236" and "amplc_pc236_common". diff --git a/drivers/staging/comedi/drivers/amplc_pc236_common.c b/drivers/staging/comedi/drivers/amplc_pc236_common.c index 0c02d3245679..4e7a37bf76b6 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236_common.c +++ b/drivers/staging/comedi/drivers/amplc_pc236_common.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pc236_common.c * Common support code for "amplc_pc236" and "amplc_pci236". diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 58b0b6b1a693..b5ceaa2f9e6f 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Amplicon PC263 relay board. * diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 4e554944bc71..5c9c67ca0131 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pci224.c * Driver for Amplicon PCI224 and PCI234 AO boards. diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 48c7890c3007..a876d22fb948 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pci230.c * Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards. diff --git a/drivers/staging/comedi/drivers/amplc_pci236.c b/drivers/staging/comedi/drivers/amplc_pci236.c index 31cc38b4bcad..c81562fd12b8 100644 --- a/drivers/staging/comedi/drivers/amplc_pci236.c +++ b/drivers/staging/comedi/drivers/amplc_pci236.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/amplc_pci236.c * Driver for Amplicon PCI236 DIO boards. diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index 8d4069bc5716..a516bc8e424b 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Amplicon PCI263 relay board. * diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 8ee732571588..e0c5fb18c7d6 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * c6xdigio.c * Hardware driver for Mechatronic Systems Inc. C6x_DIGIO DSP daughter card. diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 78d098f9e1f2..481b2f335ea3 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * cb_das16_cs.c * Driver for Computer Boards PC-CARD DAS16/16. diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 3cd008acb657..0d1d71289d91 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * cb_pcidas.c * Developed by Ivan Martinez and Frank Mori Hess, with valuable help from diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index b761f000c1dc..525424efdc1b 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/cb_pcidas64.c * This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 987414741605..94d0c58f2211 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/cb_pcidda.c * Driver for the ComputerBoards / MeasurementComputing PCI-DDA series. diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 47e38398921e..fba25b9249f8 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/cb_pcimdas.c * Comedi driver for Computer Boards PCIM-DAS1602/16 and PCIe-DAS1602/16 diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index 84ef45457c60..d2d944ac8fd5 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/cb_pcimdda.c * Computer Boards PCIM-DDA06-16 Comedi driver diff --git a/drivers/staging/comedi/drivers/comedi_8254.c b/drivers/staging/comedi/drivers/comedi_8254.c index 0d5d56b61f60..7de9601c4531 100644 --- a/drivers/staging/comedi/drivers/comedi_8254.c +++ b/drivers/staging/comedi/drivers/comedi_8254.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_8254.c * Generic 8254 timer/counter support diff --git a/drivers/staging/comedi/drivers/comedi_8254.h b/drivers/staging/comedi/drivers/comedi_8254.h index 326bd44b063e..3e5ab0ca968d 100644 --- a/drivers/staging/comedi/drivers/comedi_8254.h +++ b/drivers/staging/comedi/drivers/comedi_8254.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_8254.h * Generic 8254 timer/counter support diff --git a/drivers/staging/comedi/drivers/comedi_8255.c b/drivers/staging/comedi/drivers/comedi_8255.c index b2441efc61cc..77c5899d9230 100644 --- a/drivers/staging/comedi/drivers/comedi_8255.c +++ b/drivers/staging/comedi/drivers/comedi_8255.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_8255.c * Generic 8255 digital I/O support diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 64a5ea3810d4..0002e64ba86d 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_bond.c * A Comedi driver to 'bond' or merge multiple drivers and devices as one. diff --git a/drivers/staging/comedi/drivers/comedi_isadma.c b/drivers/staging/comedi/drivers/comedi_isadma.c index 68ef9b1750be..40f6a2c2b373 100644 --- a/drivers/staging/comedi/drivers/comedi_isadma.c +++ b/drivers/staging/comedi/drivers/comedi_isadma.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI ISA DMA support functions * Copyright (c) 2014 H Hartley Sweeten diff --git a/drivers/staging/comedi/drivers/comedi_isadma.h b/drivers/staging/comedi/drivers/comedi_isadma.h index a193d3e8d185..39723c71f5a2 100644 --- a/drivers/staging/comedi/drivers/comedi_isadma.h +++ b/drivers/staging/comedi/drivers/comedi_isadma.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * COMEDI ISA DMA support functions * Copyright (c) 2014 H Hartley Sweeten diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 1bf8ddc6f07c..2f06f3addeec 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi_parport.c * Comedi driver for standard parallel port diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index c7e8194984e5..7c920dc1e7ed 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/comedi_test.c * diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 5f848396c2f7..c0bdd62ed27f 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/contec_pci_dio.c * diff --git a/drivers/staging/comedi/drivers/dac02.c b/drivers/staging/comedi/drivers/dac02.c index a562df498b01..0d49a014dc6d 100644 --- a/drivers/staging/comedi/drivers/dac02.c +++ b/drivers/staging/comedi/drivers/dac02.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dac02.c * Comedi driver for DAC02 compatible boards diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 32dd8a857b6b..56f264603a4d 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/daqboard2000.c * hardware driver for IOtech DAQboard/2000 diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 3d8fc6ad44df..1c8f799bccfb 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/das08.c * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h index d27044cb7158..d84169f67bb0 100644 --- a/drivers/staging/comedi/drivers/das08.h +++ b/drivers/staging/comedi/drivers/das08.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das08.h * diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 317a9b5e4a3b..ff43fd5911ff 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for DAS008 PCMCIA boards * diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index cdefc99b6db3..25f908cb17b9 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das08_isa.c * comedi driver for DAS08 ISA/PC-104 boards diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index d8d27fa44491..45a1067e2ecd 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das08_pci.c * comedi driver for DAS08 PCI boards diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index ddd4aeab6365..40c514ae0ecd 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das16.c * DAS16 driver diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index bb8d6ec0632e..f8f8fff6ef5d 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for CIO-DAS16/M1 * Author: Frank Mori Hess, based on code from the das16 driver. diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index e0a34c2687a8..d7fe055ae901 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for Keithley DAS-1700/DAS-1800 series boards * Copyright (C) 2000 Frank Mori Hess diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 0fdf5e02182f..ef6f29677d43 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * das6402.c * Comedi driver for DAS6402 compatible boards diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index fd4cb4911671..115911bbe8ad 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/das800.c * Driver for Keitley das800 series boards and compatibles diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 771cceb71069..1e3d83b97d1f 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dmm32at.c * Diamond Systems Diamond-MM-32-AT Comedi driver diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 30805797a957..a29880981d81 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/dt2801.c * Device Driver for DataTranslation DT2801 diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index fcd85475e429..166c2c18c160 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for Data Translation DT2811 * diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 09984a66dba3..0a2de612e46b 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dt2814.c * Hardware driver for Data Translation DT2814 diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index ce5571971194..882a6e7476f0 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dt2815.c * Hardware driver for Data Translation DT2815 diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 39d2566e49bf..02dc5a7a92d9 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dt2817.c * Hardware driver for Data Translation DT2817 diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 217a4b884689..421652003ffc 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dt282x.c * Comedi driver for Data Translation DT2821 series diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 19e0b7be8495..7b776cb25fa6 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dt3000.c * Data Translation DT3000 series driver diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 7ebca862ecaa..ccef829651bb 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dt9812.c * COMEDI driver for DataTranslation DT9812 USB module diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index bab7ac9e6237..f027454edce9 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/dyna_pci10xx.c * Copyright (C) 2011 Prashant Shah, pshah.mumbai@gmail.com diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 0f278ffdad76..270dea651797 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * fl512.c * Anders Gnistrup diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index e5b948405fd9..39cc17c88607 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * gsc_hpdi.c * Comedi driver the General Standards Corporation diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 28cf53e48b8d..f65b26762354 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * icp_multi.c * Comedi driver for Inova ICP_MULTI board diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 77e1d891f232..3eaf7c59de75 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ii_pci20kc.c * Driver for Intelligent Instruments PCI-20001C carrier board and modules. diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index cbff3b41bb45..296fd8ebd0dc 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/jr3_pci.c * hardware driver for JR3/PCI force sensor board diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 93198abf0ee5..84d77c1da831 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ke_counter.c * Comedi driver for Kolter-Electronic PCI Counter 1 Card diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 15a53204a36a..fb2ed0c96ec0 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * me4000.c * Source code for the Meilhaus ME-4000 board family. diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index c0b7a300e428..4a51b028b5cb 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/me_daq.c * Hardware driver for Meilhaus data acquisition cards: diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c index fbdf181d8ccc..70041d6ee500 100644 --- a/drivers/staging/comedi/drivers/mf6x4.c +++ b/drivers/staging/comedi/drivers/mf6x4.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/mf6x4.c * Driver for Humusoft MF634 and MF624 Data acquisition cards diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 05126ba4ba51..1ddf9c46c67c 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/mite.c * Hardware driver for NI Mite PCI interface chip diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index 02a627d3969d..71a4a18477e6 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * module/mite.h * Hardware driver for NI Mite PCI interface chip diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 9bda761433c2..e73f8b4e2c30 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * mpc624.c * Hardware driver for a Micro/sys inc. MPC-624 PC/104 board diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index b5a26f7b4332..ab9baf90ab73 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * multiq3.c * Hardware driver for Quanser Consulting MultiQ-3 board diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 84c62e256094..6111a39b1623 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ni_6527.c * Comedi driver for National Instruments PCI-6527 diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 07f38e385469..574724649493 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ni_65xx.c * Comedi driver for National Instruments PCI-65xx static dio boards diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 6aa755ad3953..2253a2d69870 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Hardware driver for NI 660x devices * diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 1d3ff60efcb8..c6a724feb1ae 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for NI 670x devices * diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index c69cd676f357..b7934039459b 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for National Instruments AT-A2150 boards * Copyright (C) 2001, 2002 Frank Mori Hess diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 158fa29374fc..5a0ad7cb98ce 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ni_at_ao.c * Driver for NI AT-AO-6/10 boards diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 2d62a8c57332..436ca724bccd 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for NI AT-MIO E series cards * diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index fb59b0ffbba6..d0e1c73845d2 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for National Instruments AT-MIO16D board * Copyright (C) 2000 Chris R. Baugher diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 8f6396edd21c..eb5fb5f55265 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_daq_700.c * Driver for DAQCard-700 DIO/AI diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 733d3fbafa4d..f75d78334d83 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for National Instruments PCMCIA DAQ-Card DIO-24 * Copyright (C) 2002 Daniel Vecino Castel diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 51e5e942b442..3b2782cccf12 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_labpc.c * Driver for National Instruments Lab-PC series boards and compatibles diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index c2edadc7b3c6..9784456f83a8 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Header for ni_labpc ISA/PCMCIA/PCI drivers * diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index b0dfb8eed16d..5c52d39a7241 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_labpc_common.c * diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 3d4d0b9ad4e1..0f329e717744 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for National Instruments daqcard-1200 boards * Copyright (C) 2001, 2002, 2003 Frank Mori Hess diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 29dbdf5ec25d..be0e2367263b 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_labpc_isadma.c * ISA DMA support for National Instruments Lab-PC series boards and diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index cac089193121..196c32122baf 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_labpc_pci.c * Driver for National Instruments Lab-PC PCI-1200 diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 398347fedc47..3d043254b280 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Hardware driver for DAQ-STC based boards * diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 21f823179356..076cd4635b51 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for NI PCMCIA MIO E series cards * diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index b27345abebe1..cd6fdad39f04 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for National Instruments PCI-DIO-32HS * diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 3a96913c025e..71da3206c934 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Comedi driver for NI PCI-MIO E series cards * diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h index 61138e86a455..819140594dde 100644 --- a/drivers/staging/comedi/drivers/ni_stc.h +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Register descriptions for NI DAQ-STC chip * diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 15cb4088467b..1a6334c81525 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Support for NI general purpose counters * diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index 2012033414d3..d995f98eb6ef 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Header file for NI general purpose counter support code (ni_tio.c) * diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index 4e024eb5656b..87b9f771ac4f 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Header file for NI general purpose counter support code (ni_tio.c and * ni_tiocmd.c) diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 9007c57544bf..8157cf663741 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Command support for NI general purpose counters * diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c index 9a0a96329a55..508017b297d1 100644 --- a/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/drivers/staging/comedi/drivers/ni_usb6501.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/ni_usb6501.c * Comedi driver for National Instruments USB-6501 diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 3774daa9d661..45d3c631bd56 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcl711.c * Comedi driver for PC-LabCard PCL-711 and AdSys ACL-8112 and compatibles diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 74b07e1744c7..9c174f1f2fcf 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * pcl724.c * Comedi driver for 8255 based ISA and PC/104 DIO boards diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 256850ccb6fa..66fd1d17b5a0 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcl726.c * Comedi driver for 6/12-Channel D/A Output and DIO cards diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index ce958eef2a61..3d1e9150e5b5 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/pcl730.c * Driver for Advantech PCL-730 and clones diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 9c75065dd26a..aefc1b849cf7 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/pcl812.c * diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index c00a71f538ef..d722079f3327 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * pcl816.c * Comedi driver for Advantech PCL-816 cards diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 5b5df0596ad9..eebb49751713 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * comedi/drivers/pcl818.c * diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 588ae5ecec66..5779e005c0cb 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * pcm3724.c * Comedi driver for Advantech PCM-3724 Digital I/O board diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 12f94fe82f5b..12f5b4b2e211 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcmad.c * Hardware driver for Winsystems PCM-A/D12 and PCM-A/D16 diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index d86c5e2cd0c7..20326146b614 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcmda12.c * Driver for Winsystems PC-104 based PCM-D/A-12 8-channel AO board. diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 70ad497dd20b..3f339cf7e36f 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcmmio.c * Driver for Winsystems PC-104 based multifunction IO board. diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 8ad64f2625fe..74a3545e2d35 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * pcmuio.c * Comedi driver for Winsystems PC-104 based 48/96-channel DIO boards. diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h index 2892e6528967..82ccc13a356d 100644 --- a/drivers/staging/comedi/drivers/plx9052.h +++ b/drivers/staging/comedi/drivers/plx9052.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Definitions for the PLX-9052 PCI interface chip * diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index e23e63a097b5..70e5439173ba 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * plx9080.h * diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index e00e9c6268ae..39595d19b0b9 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/rtd520.c * Comedi driver for Real Time Devices (RTD) PCI4520/DM7520 diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index cd61d2645af4..d8a9b5a8f450 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/rti800.c * Hardware driver for Analog Devices RTI-800/815 board diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 6db58fcfd496..080bb8c7bc56 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * rti802.c * Comedi driver for Analog Devices RTI-802 board diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index e226275972c0..3f867418953c 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * s526.c * Sensoray s526 Comedi driver diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index c906c9a5d944..24e8191e4d74 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/s626.c * Sensoray s626 Comedi driver diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 4cef45263267..924e7d60e713 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/s626.h * Sensoray s626 Comedi driver, header file diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index cc18e25103ca..903498ad0b11 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * serial2002.c * Comedi driver for serial connected hardware diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index f9f634fd53cf..f9254db489cf 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * ssv_dnp.c * generic comedi driver for SSV Embedded Systems' DIL/Net-PCs diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index ede064b47aac..0640d82933c2 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * usbdux.c * Copyright (C) 2003-2014 Bernd Porr, mail@berndporr.me.uk diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 608403c7586b..2015a0cf8314 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2004-2014 Bernd Porr, mail@berndporr.me.uk * diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 456e9f13becb..4ff8e7a87460 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * usbduxsigma.c * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index a004aed0147a..50c12e5db259 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vmk80xx.c * Velleman USB Board Low-Level Driver diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 55d43c076b1c..7d73bdd1e795 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * kcomedilib/kcomedilib.c * a comedlib interface for kernel modules diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c index 2644dd4d6143..2808bb717e95 100644 --- a/drivers/staging/comedi/proc.c +++ b/drivers/staging/comedi/proc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * /proc interface for comedi * diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index ce3a58a7a171..a2321b533639 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * comedi/range.c * comedi routines for voltage ranges -- cgit v1.2.3 From b69839391d444882d83c85a531da8b4e75a2b2e6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 14:58:44 +0100 Subject: staging: comedi: drivers: Remove redundant license text Now that the SPDX tag is in all comedi files, that identifies the license in a specific and legally-defined manner. So the extra GPL text wording can be removed as it is no longer needed at all. This is done on a quest to remove the 700+ different ways that files in the kernel describe the GPL license text. And there's unneeded stuff like the address (sometimes incorrect) for the FSF which is never needed. No copyright headers or other non-license-description text was removed. Cc: Ian Abbott Cc: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/8255.c | 10 ---------- drivers/staging/comedi/drivers/8255.h | 10 ---------- drivers/staging/comedi/drivers/8255_pci.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_1032.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_1500.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_1516.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_1564.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_16xx.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_2032.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_2200.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_3120.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_3501.c | 10 ---------- drivers/staging/comedi/drivers/addi_apci_3xxx.c | 10 ---------- drivers/staging/comedi/drivers/addi_watchdog.c | 10 ---------- drivers/staging/comedi/drivers/adl_pci6208.c | 10 ---------- drivers/staging/comedi/drivers/adl_pci7x3x.c | 10 ---------- drivers/staging/comedi/drivers/adl_pci8164.c | 10 ---------- drivers/staging/comedi/drivers/adl_pci9111.c | 10 ---------- drivers/staging/comedi/drivers/adq12b.c | 10 ---------- drivers/staging/comedi/drivers/adv_pci1720.c | 10 ---------- drivers/staging/comedi/drivers/adv_pci1723.c | 10 ---------- drivers/staging/comedi/drivers/adv_pci1724.c | 10 ---------- drivers/staging/comedi/drivers/adv_pci1760.c | 10 ---------- drivers/staging/comedi/drivers/aio_aio12_8.c | 10 ---------- drivers/staging/comedi/drivers/aio_iiro_16.c | 10 ---------- drivers/staging/comedi/drivers/amplc_dio200.c | 10 ---------- drivers/staging/comedi/drivers/amplc_dio200.h | 10 ---------- drivers/staging/comedi/drivers/amplc_dio200_common.c | 10 ---------- drivers/staging/comedi/drivers/amplc_dio200_pci.c | 10 ---------- drivers/staging/comedi/drivers/amplc_pc236.c | 10 ---------- drivers/staging/comedi/drivers/amplc_pc236.h | 10 ---------- drivers/staging/comedi/drivers/amplc_pc236_common.c | 10 ---------- drivers/staging/comedi/drivers/amplc_pc263.c | 10 ---------- drivers/staging/comedi/drivers/amplc_pci224.c | 10 ---------- drivers/staging/comedi/drivers/amplc_pci230.c | 10 ---------- drivers/staging/comedi/drivers/amplc_pci236.c | 10 ---------- drivers/staging/comedi/drivers/amplc_pci263.c | 10 ---------- drivers/staging/comedi/drivers/c6xdigio.c | 10 ---------- drivers/staging/comedi/drivers/cb_das16_cs.c | 10 ---------- drivers/staging/comedi/drivers/cb_pcidas.c | 10 ---------- drivers/staging/comedi/drivers/cb_pcidas64.c | 10 ---------- drivers/staging/comedi/drivers/cb_pcidda.c | 10 ---------- drivers/staging/comedi/drivers/cb_pcimdas.c | 10 ---------- drivers/staging/comedi/drivers/cb_pcimdda.c | 10 ---------- drivers/staging/comedi/drivers/comedi_8254.c | 10 ---------- drivers/staging/comedi/drivers/comedi_8254.h | 10 ---------- drivers/staging/comedi/drivers/comedi_8255.c | 10 ---------- drivers/staging/comedi/drivers/comedi_bond.c | 10 ---------- drivers/staging/comedi/drivers/comedi_isadma.c | 10 ---------- drivers/staging/comedi/drivers/comedi_isadma.h | 10 ---------- drivers/staging/comedi/drivers/comedi_parport.c | 10 ---------- drivers/staging/comedi/drivers/comedi_test.c | 10 ---------- drivers/staging/comedi/drivers/contec_pci_dio.c | 10 ---------- drivers/staging/comedi/drivers/dac02.c | 10 ---------- drivers/staging/comedi/drivers/daqboard2000.c | 10 ---------- drivers/staging/comedi/drivers/das08.c | 10 ---------- drivers/staging/comedi/drivers/das08.h | 10 ---------- drivers/staging/comedi/drivers/das08_cs.c | 10 ---------- drivers/staging/comedi/drivers/das08_isa.c | 10 ---------- drivers/staging/comedi/drivers/das08_pci.c | 10 ---------- drivers/staging/comedi/drivers/das16.c | 10 ---------- drivers/staging/comedi/drivers/das16m1.c | 10 ---------- drivers/staging/comedi/drivers/das1800.c | 10 ---------- drivers/staging/comedi/drivers/das6402.c | 10 ---------- drivers/staging/comedi/drivers/das800.c | 10 ---------- drivers/staging/comedi/drivers/dmm32at.c | 10 ---------- drivers/staging/comedi/drivers/dt2811.c | 10 ---------- drivers/staging/comedi/drivers/dt2814.c | 10 ---------- drivers/staging/comedi/drivers/dt2815.c | 10 ---------- drivers/staging/comedi/drivers/dt2817.c | 10 ---------- drivers/staging/comedi/drivers/dt282x.c | 10 ---------- drivers/staging/comedi/drivers/dt3000.c | 10 ---------- drivers/staging/comedi/drivers/dt9812.c | 10 ---------- drivers/staging/comedi/drivers/dyna_pci10xx.c | 10 ---------- drivers/staging/comedi/drivers/fl512.c | 10 ---------- drivers/staging/comedi/drivers/gsc_hpdi.c | 10 ---------- drivers/staging/comedi/drivers/icp_multi.c | 10 ---------- drivers/staging/comedi/drivers/jr3_pci.c | 10 ---------- drivers/staging/comedi/drivers/ke_counter.c | 10 ---------- drivers/staging/comedi/drivers/me4000.c | 10 ---------- drivers/staging/comedi/drivers/me_daq.c | 10 ---------- drivers/staging/comedi/drivers/mf6x4.c | 10 ---------- drivers/staging/comedi/drivers/mite.c | 10 ---------- drivers/staging/comedi/drivers/mite.h | 10 ---------- drivers/staging/comedi/drivers/mpc624.c | 10 ---------- drivers/staging/comedi/drivers/multiq3.c | 10 ---------- drivers/staging/comedi/drivers/ni_6527.c | 10 ---------- drivers/staging/comedi/drivers/ni_65xx.c | 10 ---------- drivers/staging/comedi/drivers/ni_660x.c | 10 ---------- drivers/staging/comedi/drivers/ni_670x.c | 10 ---------- drivers/staging/comedi/drivers/ni_at_a2150.c | 10 ---------- drivers/staging/comedi/drivers/ni_at_ao.c | 10 ---------- drivers/staging/comedi/drivers/ni_atmio.c | 10 ---------- drivers/staging/comedi/drivers/ni_atmio16d.c | 10 ---------- drivers/staging/comedi/drivers/ni_daq_700.c | 10 ---------- drivers/staging/comedi/drivers/ni_daq_dio24.c | 10 ---------- drivers/staging/comedi/drivers/ni_labpc.c | 10 ---------- drivers/staging/comedi/drivers/ni_labpc.h | 10 ---------- drivers/staging/comedi/drivers/ni_labpc_common.c | 10 ---------- drivers/staging/comedi/drivers/ni_labpc_cs.c | 10 ---------- drivers/staging/comedi/drivers/ni_labpc_isadma.c | 10 ---------- drivers/staging/comedi/drivers/ni_labpc_pci.c | 10 ---------- drivers/staging/comedi/drivers/ni_mio_common.c | 10 ---------- drivers/staging/comedi/drivers/ni_mio_cs.c | 10 ---------- drivers/staging/comedi/drivers/ni_pcidio.c | 10 ---------- drivers/staging/comedi/drivers/ni_pcimio.c | 10 ---------- drivers/staging/comedi/drivers/ni_stc.h | 10 ---------- drivers/staging/comedi/drivers/ni_tio.c | 10 ---------- drivers/staging/comedi/drivers/ni_tio.h | 10 ---------- drivers/staging/comedi/drivers/ni_tio_internal.h | 10 ---------- drivers/staging/comedi/drivers/ni_tiocmd.c | 10 ---------- drivers/staging/comedi/drivers/ni_usb6501.c | 10 ---------- drivers/staging/comedi/drivers/pcl711.c | 10 ---------- drivers/staging/comedi/drivers/pcl726.c | 10 ---------- drivers/staging/comedi/drivers/pcmad.c | 10 ---------- drivers/staging/comedi/drivers/pcmda12.c | 10 ---------- drivers/staging/comedi/drivers/pcmmio.c | 10 ---------- drivers/staging/comedi/drivers/pcmuio.c | 10 ---------- drivers/staging/comedi/drivers/plx9052.h | 10 ---------- drivers/staging/comedi/drivers/plx9080.h | 5 ----- drivers/staging/comedi/drivers/rtd520.c | 10 ---------- drivers/staging/comedi/drivers/rti800.c | 10 ---------- drivers/staging/comedi/drivers/rti802.c | 10 ---------- drivers/staging/comedi/drivers/s526.c | 10 ---------- drivers/staging/comedi/drivers/s626.c | 10 ---------- drivers/staging/comedi/drivers/s626.h | 10 ---------- drivers/staging/comedi/drivers/serial2002.c | 10 ---------- drivers/staging/comedi/drivers/ssv_dnp.c | 10 ---------- drivers/staging/comedi/drivers/usbdux.c | 10 ---------- drivers/staging/comedi/drivers/usbduxfast.c | 10 ---------- drivers/staging/comedi/drivers/usbduxsigma.c | 10 ---------- drivers/staging/comedi/drivers/vmk80xx.c | 10 ---------- 132 files changed, 1315 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index ad9488ef97b6..3d6105b5a11b 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h index 410dc101f550..6cd1339ab83e 100644 --- a/drivers/staging/comedi/drivers/8255.h +++ b/drivers/staging/comedi/drivers/8255.h @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ #ifndef _8255_H diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index cb3db46b3c95..9ed05f962fdb 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -10,16 +10,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index d178b35ba459..560649be9d13 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -11,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 05d7d3e192c5..45ad4ba92f94 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -10,16 +10,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index e1a28d80db45..6c8213ee1a74 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -11,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 1956a169f78b..10501fe6bb25 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -10,16 +10,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index 5e81b0008943..050d0b4b3209 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -11,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index 5ab5a1a99608..a122f3f3f5ec 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -11,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index 8ccd0fc81081..140d1514a106 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -11,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 8db5ce609eec..d2810fdd5e63 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -10,16 +10,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 2cc87818b148..a38267928e5e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -11,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index dd9a23af97bd..55784f24e2a7 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -11,16 +11,6 @@ * Fax: +49(0)7223/9493-92 * http://www.addi-data.com * info@addi-data.com - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c index c74ddf62490a..69b323fb869f 100644 --- a/drivers/staging/comedi/drivers/addi_watchdog.c +++ b/drivers/staging/comedi/drivers/addi_watchdog.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 6901f703cebe..d39b4eabce8d 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index 7cacb7fb53d3..d0081897fe47 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -10,16 +10,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 0403679d5a58..3022793b1bc5 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -4,16 +4,6 @@ * * Hardware comedi driver for PCI-8164 Adlink card * Copyright (C) 2004 Michel Lachine - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index c5b1d5312178..f4dba6271d0d 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -3,16 +3,6 @@ * adl_pci9111.c * Hardware driver for PCI9111 ADLink cards: PCI-9111HR * Copyright (C) 2002-2005 Emmanuel Pacaud - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 630933d7799a..5d431573bcca 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -10,16 +10,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci1720.c b/drivers/staging/comedi/drivers/adv_pci1720.c index 7951f8b84649..2fcd7e8e7d85 100644 --- a/drivers/staging/comedi/drivers/adv_pci1720.c +++ b/drivers/staging/comedi/drivers/adv_pci1720.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 1515fde4d990..771d61f87427 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index 2898bd01219b..e8ab573c839f 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/adv_pci1760.c b/drivers/staging/comedi/drivers/adv_pci1760.c index fa42255827b1..e692be371f29 100644 --- a/drivers/staging/comedi/drivers/adv_pci1760.c +++ b/drivers/staging/comedi/drivers/adv_pci1760.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 6e018fef315a..f4beda1ed640 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -3,16 +3,6 @@ * aio_aio12_8.c * Driver for Access I/O Products PC-104 AIO12-8 Analog I/O Board * Copyright (C) 2006 C&C Technologies, Inc. - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 1a3e0df689e5..41c9c56816ef 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -3,16 +3,6 @@ * aio_iiro_16.c * Comedi driver for Access I/O Products 104-IIRO-16 board * Copyright (C) 2006 C&C Technologies, Inc. - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 97f21964546c..26e63d64ffc6 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h index eeb18d917f07..88c1d1063d5d 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.h +++ b/drivers/staging/comedi/drivers/amplc_dio200.h @@ -9,16 +9,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef - * - * 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. */ #ifndef AMPLC_DIO200_H_INCLUDED diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index ae22cfcf67fe..82bd41d92509 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c index 4bd59388a2ff..30d239731e0b 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index dfc4fee4cd11..b7dd15f5ec63 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* * Driver: amplc_pc236 diff --git a/drivers/staging/comedi/drivers/amplc_pc236.h b/drivers/staging/comedi/drivers/amplc_pc236.h index af12477c3c85..4b67090aab54 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.h +++ b/drivers/staging/comedi/drivers/amplc_pc236.h @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ #ifndef AMPLC_PC236_H_INCLUDED diff --git a/drivers/staging/comedi/drivers/amplc_pc236_common.c b/drivers/staging/comedi/drivers/amplc_pc236_common.c index 4e7a37bf76b6..01b90e4eca8a 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236_common.c +++ b/drivers/staging/comedi/drivers/amplc_pc236_common.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index b5ceaa2f9e6f..84c989f12faf 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 5c9c67ca0131..657b736ef46d 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index a876d22fb948..15fc7f19051a 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/amplc_pci236.c b/drivers/staging/comedi/drivers/amplc_pci236.c index c81562fd12b8..86ea876a11be 100644 --- a/drivers/staging/comedi/drivers/amplc_pci236.c +++ b/drivers/staging/comedi/drivers/amplc_pci236.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* * Driver: amplc_pci236 diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index a516bc8e424b..c3efe14020a8 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index e0c5fb18c7d6..41cc784320a9 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Dan Block - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 481b2f335ea3..a5d171e71c33 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -6,16 +6,6 @@ * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000, 2001, 2002 David A. Schleef * - * 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. - * * PCMCIA support code for this driver is adapted from the dummy_cs.c * driver of the Linux PCMCIA Card Services package. * diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 0d1d71289d91..8429d57087fd 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -9,16 +9,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 525424efdc1b..b657beedd5ff 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -19,16 +19,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 94d0c58f2211..807a31e75883 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index fba25b9249f8..4e72a0778086 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index d2d944ac8fd5..b33203f6a990 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* * Driver: cb_pcimdda diff --git a/drivers/staging/comedi/drivers/comedi_8254.c b/drivers/staging/comedi/drivers/comedi_8254.c index 7de9601c4531..d1d509e9add9 100644 --- a/drivers/staging/comedi/drivers/comedi_8254.c +++ b/drivers/staging/comedi/drivers/comedi_8254.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/comedi_8254.h b/drivers/staging/comedi/drivers/comedi_8254.h index 3e5ab0ca968d..7faa2185282e 100644 --- a/drivers/staging/comedi/drivers/comedi_8254.h +++ b/drivers/staging/comedi/drivers/comedi_8254.h @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ #ifndef _COMEDI_8254_H diff --git a/drivers/staging/comedi/drivers/comedi_8255.c b/drivers/staging/comedi/drivers/comedi_8255.c index 77c5899d9230..62baa0d79302 100644 --- a/drivers/staging/comedi/drivers/comedi_8255.c +++ b/drivers/staging/comedi/drivers/comedi_8255.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 0002e64ba86d..4392b5927a99 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -6,16 +6,6 @@ * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef * Copyright (C) 2005 Calin A. Culianu - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/comedi_isadma.c b/drivers/staging/comedi/drivers/comedi_isadma.c index 40f6a2c2b373..b77dc8d5d3ff 100644 --- a/drivers/staging/comedi/drivers/comedi_isadma.c +++ b/drivers/staging/comedi/drivers/comedi_isadma.c @@ -2,16 +2,6 @@ /* * COMEDI ISA DMA support functions * Copyright (c) 2014 H Hartley Sweeten - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/comedi_isadma.h b/drivers/staging/comedi/drivers/comedi_isadma.h index 39723c71f5a2..ccef7c9c0a4d 100644 --- a/drivers/staging/comedi/drivers/comedi_isadma.h +++ b/drivers/staging/comedi/drivers/comedi_isadma.h @@ -2,16 +2,6 @@ /* * COMEDI ISA DMA support functions * Copyright (c) 2014 H Hartley Sweeten - * - * 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. */ #ifndef _COMEDI_ISADMA_H diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 2f06f3addeec..efaa57372aeb 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998,2001 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index 7c920dc1e7ed..d437af721bd8 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -12,16 +12,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index c0bdd62ed27f..49be795b4971 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/dac02.c b/drivers/staging/comedi/drivers/dac02.c index 0d49a014dc6d..5ef8114c2c85 100644 --- a/drivers/staging/comedi/drivers/dac02.c +++ b/drivers/staging/comedi/drivers/dac02.c @@ -10,16 +10,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 56f264603a4d..03f98b0287c8 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell - * - * 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. */ /* * Driver: daqboard2000 diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 1c8f799bccfb..327ecf9aea30 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -7,16 +7,6 @@ * Copyright (C) 2000 David A. Schleef * Copyright (C) 2001,2002,2003 Frank Mori Hess * Copyright (C) 2004 Salvador E. Tropea - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h index d84169f67bb0..235d32f7c817 100644 --- a/drivers/staging/comedi/drivers/das08.h +++ b/drivers/staging/comedi/drivers/das08.h @@ -5,16 +5,6 @@ * Header for common DAS08 support (used by ISA/PCI/PCMCIA drivers) * * Copyright (C) 2003 Frank Mori Hess - * - * 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. */ #ifndef _DAS08_H diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index ff43fd5911ff..223479f9ea3c 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -6,16 +6,6 @@ * Copyright (C) 2000 David A. Schleef * Copyright (C) 2001,2002,2003 Frank Mori Hess * - * 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. - * * PCMCIA support code for this driver is adapted from the dummy_cs.c * driver of the Linux PCMCIA Card Services package. * diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index 25f908cb17b9..b22a45bd21d1 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -7,16 +7,6 @@ * Copyright (C) 2000 David A. Schleef * Copyright (C) 2001,2002,2003 Frank Mori Hess * Copyright (C) 2004 Salvador E. Tropea - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index 45a1067e2ecd..7856fc13466a 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -7,16 +7,6 @@ * Copyright (C) 2000 David A. Schleef * Copyright (C) 2001,2002,2003 Frank Mori Hess * Copyright (C) 2004 Salvador E. Tropea - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 40c514ae0ecd..74ff204b585d 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -7,16 +7,6 @@ * Copyright (C) 2000 David A. Schleef * Copyright (C) 2000 Chris R. Baugher * Copyright (C) 2001,2002 Frank Mori Hess - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index f8f8fff6ef5d..72f8ed2c5008 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index d7fe055ae901..f16aa7e9f4f3 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index ef6f29677d43..f99211ec46de 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -6,16 +6,6 @@ * * Rewrite of an experimental driver by: * Copyright (C) 1999 Oystein Svendsen - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 115911bbe8ad..8cf09ef3012f 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* * Driver: das800 diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 1e3d83b97d1f..75693cdde313 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 166c2c18c160..fea0a1baf10b 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 0a2de612e46b..d2c715737361 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* * Driver: dt2814 diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index 882a6e7476f0..83026ba63d1c 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell - * - * 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. */ /* * Driver: dt2815 diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 02dc5a7a92d9..9babb2a5196a 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* * Driver: dt2817 diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 421652003ffc..3be927f1d3a9 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 7b776cb25fa6..2edf3ee91300 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index ccef829651bb..75cc9e8e5b94 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -6,16 +6,6 @@ * Copyright (C) 2005 Anders Blomdell * * COMEDI - Linux Control and Measurement Device Interface - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index f027454edce9..e50536731d11 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -2,16 +2,6 @@ /* * comedi/drivers/dyna_pci10xx.c * Copyright (C) 2011 Prashant Shah, pshah.mumbai@gmail.com - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 270dea651797..41c50c7a8f59 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 39cc17c88607..4bdf44d82879 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -9,16 +9,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index f65b26762354..b14aaed6b525 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2002 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 296fd8ebd0dc..201f4f96c182 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2007 Anders Blomdell - * - * 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. */ /* * Driver: jr3_pci diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 84d77c1da831..e612cf605700 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index fb2ed0c96ec0..ee53571a8969 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 4a51b028b5cb..169742be17b8 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -5,16 +5,6 @@ * ME-2000i, ME-2600i, ME-3000vm1 * * Copyright (C) 2002 Michael Hillmann - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c index 70041d6ee500..ea430237efa7 100644 --- a/drivers/staging/comedi/drivers/mf6x4.c +++ b/drivers/staging/comedi/drivers/mf6x4.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* * Driver: mf6x4 diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 1ddf9c46c67c..61e03ad84123 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2002 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index 71a4a18477e6..d5e27ac25df8 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 David A. Schleef - * - * 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. */ #ifndef _MITE_H_ diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index e73f8b4e2c30..bf3a3a08c7ab 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index ab9baf90ab73..c85c9ab3655f 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 6111a39b1623..4d1eccb5041d 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999,2002,2003 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 574724649493..996074e471d3 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999,2002,2003 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 2253a2d69870..e521ed9d0887 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1,16 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Hardware driver for NI 660x devices - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index c6a724feb1ae..4e4ae31c8d0b 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2001 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index b7934039459b..76e8d047f71e 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 5a0ad7cb98ce..aad0b295ee2b 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000,2002 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 436ca724bccd..45a1dc0ed0f4 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2001 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index d0e1c73845d2..68ad9676f962 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -2,16 +2,6 @@ /* * Comedi driver for National Instruments AT-MIO16D board * Copyright (C) 2000 Chris R. Baugher - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index eb5fb5f55265..b9e525b9beb9 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index f75d78334d83..44fb65afc218 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -8,16 +8,6 @@ * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 3b2782cccf12..c6cf37ccbc92 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -3,16 +3,6 @@ * comedi/drivers/ni_labpc.c * Driver for National Instruments Lab-PC series boards and compatibles * Copyright (C) 2001-2003 Frank Mori Hess - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index 9784456f83a8..f685047efb67 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -3,16 +3,6 @@ * Header for ni_labpc ISA/PCMCIA/PCI drivers * * Copyright (C) 2003 Frank Mori Hess - * - * 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. */ #ifndef _NI_LABPC_H diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index 5c52d39a7241..7fa2d39562db 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -5,16 +5,6 @@ * Common support code for "ni_labpc", "ni_labpc_pci" and "ni_labpc_cs". * * Copyright (C) 2001-2003 Frank Mori Hess - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 0f329e717744..4f7e2fe21254 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -8,16 +8,6 @@ * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. - * - * 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 - * General Public License for more details. */ /* diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index be0e2367263b..5657736a9408 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -6,16 +6,6 @@ * * Extracted from ni_labpc.c: * Copyright (C) 2001-2003 Frank Mori Hess - * - * 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. */ #include diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index 196c32122baf..d7d5a7973558 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -3,16 +3,6 @@ * comedi/drivers/ni_labpc_pci.c * Driver for National Instruments Lab-PC PCI-1200 * Copyright (C) 2001, 2002, 2003 Frank Mori Hess - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 3d043254b280..5d610af6799f 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -5,16 +5,6 @@ * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2001 David A. Schleef * Copyright (C) 2002-2006 Frank Mori Hess - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 076cd4635b51..4f37b4e58f09 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index cd6fdad39f04..6692af5ff79b 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999,2002 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 71da3206c934..f9e466d18b3f 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h index 819140594dde..cb9d4c3a1926 100644 --- a/drivers/staging/comedi/drivers/ni_stc.h +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998-9 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 1a6334c81525..ef919b21b7d9 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -3,16 +3,6 @@ * Support for NI general purpose counters * * Copyright (C) 2006 Frank Mori Hess - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h index d995f98eb6ef..23221cead8ca 100644 --- a/drivers/staging/comedi/drivers/ni_tio.h +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -3,16 +3,6 @@ * Header file for NI general purpose counter support code (ni_tio.c) * * COMEDI - Linux Control and Measurement Device Interface - * - * 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. */ #ifndef _COMEDI_NI_TIO_H diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h index 87b9f771ac4f..f4d99d78208a 100644 --- a/drivers/staging/comedi/drivers/ni_tio_internal.h +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -4,16 +4,6 @@ * ni_tiocmd.c) * * COMEDI - Linux Control and Measurement Device Interface - * - * 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. */ #ifndef _COMEDI_NI_TIO_INTERNAL_H diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 8157cf663741..050bee0b9515 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -3,16 +3,6 @@ * Command support for NI general purpose counters * * Copyright (C) 2006 Frank Mori Hess - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c index 508017b297d1..808ed92ed66f 100644 --- a/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/drivers/staging/comedi/drivers/ni_usb6501.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2014 Luca Ellero - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 45d3c631bd56..a5937206bf1c 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 66fd1d17b5a0..0963d85873a9 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 12f5b4b2e211..fe5449bb1716 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000,2001 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 20326146b614..33e463b193a1 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2006 Calin A. Culianu - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 3f339cf7e36f..72af1776f785 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2007 Calin A. Culianu - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 74a3545e2d35..743fb226e2e4 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2006 Calin A. Culianu - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h index 82ccc13a356d..7950d1f57db6 100644 --- a/drivers/staging/comedi/drivers/plx9052.h +++ b/drivers/staging/comedi/drivers/plx9052.h @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ #ifndef _PLX9052_H_ diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index 70e5439173ba..469a9573acdc 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -10,11 +10,6 @@ * Written by Krzysztof Halasa * * Portions (C) SBE Inc., used by permission. - * - * 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. */ #ifndef __COMEDI_PLX9080_H diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 39595d19b0b9..bb400e08f0bc 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2001 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index d8a9b5a8f450..f7c320c89ee6 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 080bb8c7bc56..c6cf92bfff73 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 3f867418953c..5d567ae78f28 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 24e8191e4d74..8d9187025d51 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -8,16 +8,6 @@ * * Based on Sensoray Model 626 Linux driver Version 0.2 * Copyright (C) 2002-2004 Sensoray Co., Inc. - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 924e7d60e713..4bdc4fba736f 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -8,16 +8,6 @@ * * Based on Sensoray Model 626 Linux driver Version 0.2 * Copyright (C) 2002-2004 Sensoray Co., Inc. - * - * 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. */ #ifndef S626_H_INCLUDED diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 903498ad0b11..1f52fd1c1c08 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2002 Anders Blomdell - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index f9254db489cf..0628060e42ca 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -6,16 +6,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 0640d82933c2..de177418190f 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2,16 +2,6 @@ /* * usbdux.c * Copyright (C) 2003-2014 Bernd Porr, mail@berndporr.me.uk - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 2015a0cf8314..e18c0723b760 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1,16 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2004-2014 Bernd Porr, mail@berndporr.me.uk - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 4ff8e7a87460..af5605a875e2 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -2,16 +2,6 @@ /* * usbduxsigma.c * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk - * - * 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. */ /* diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 50c12e5db259..6234b649d887 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -7,16 +7,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef - * - * 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. */ /* -- cgit v1.2.3 From f814e74c9b5f37f22fe28acc1989566b99adb170 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 14:58:45 +0100 Subject: staging: comedi: Remove redundant license text Now that the SPDX tag is in all comedi files, that identifies the license in a specific and legally-defined manner. So the extra GPL text wording can be removed as it is no longer needed at all. This is done on a quest to remove the 700+ different ways that files in the kernel describe the GPL license text. And there's unneeded stuff like the address (sometimes incorrect) for the FSF which is never needed. No copyright headers or other non-license-description text was removed. Cc: Ian Abbott Cc: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 10 ---------- drivers/staging/comedi/comedi_buf.c | 10 ---------- drivers/staging/comedi/comedi_compat32.c | 10 ---------- drivers/staging/comedi/comedi_compat32.h | 10 ---------- drivers/staging/comedi/comedi_fops.c | 10 ---------- drivers/staging/comedi/comedi_pci.c | 10 ---------- drivers/staging/comedi/comedi_pci.h | 10 ---------- drivers/staging/comedi/comedi_pcmcia.c | 10 ---------- drivers/staging/comedi/comedi_pcmcia.h | 10 ---------- drivers/staging/comedi/comedi_usb.c | 10 ---------- drivers/staging/comedi/comedi_usb.h | 10 ---------- drivers/staging/comedi/comedidev.h | 10 ---------- drivers/staging/comedi/comedilib.h | 10 ---------- drivers/staging/comedi/drivers.c | 10 ---------- drivers/staging/comedi/kcomedilib/kcomedilib_main.c | 10 ---------- drivers/staging/comedi/proc.c | 10 ---------- drivers/staging/comedi/range.c | 10 ---------- 17 files changed, 170 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index e915e42ab47f..c0bc413f7fe0 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998-2001 David A. Schleef - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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. */ #ifndef _COMEDI_H diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index e75d41ac2a19..f693c2c0bec3 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -5,16 +5,6 @@ * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef * Copyright (C) 2002 Frank Mori Hess - * - * 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. */ #include diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 26c62f7e6249..97fb9388bc22 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2007 David A. Schleef - * - * 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. */ #include diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h index 9fa8ed2b8d41..3980e6e1bd0d 100644 --- a/drivers/staging/comedi/comedi_compat32.h +++ b/drivers/staging/comedi/comedi_compat32.h @@ -8,16 +8,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2007 David A. Schleef - * - * 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. */ #ifndef _COMEDI_COMPAT32_H diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index da7999777d39..4dbefc767e1b 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/staging/comedi/comedi_pci.c b/drivers/staging/comedi/comedi_pci.c index 02467227b2dd..126048b03f43 100644 --- a/drivers/staging/comedi/comedi_pci.c +++ b/drivers/staging/comedi/comedi_pci.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #include diff --git a/drivers/staging/comedi/comedi_pci.h b/drivers/staging/comedi/comedi_pci.h index b1fbec67dd1a..647a72441b8a 100644 --- a/drivers/staging/comedi/comedi_pci.h +++ b/drivers/staging/comedi/comedi_pci.h @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #ifndef _COMEDI_PCI_H diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c index 7d4fd01011a9..e16f35eae343 100644 --- a/drivers/staging/comedi/comedi_pcmcia.c +++ b/drivers/staging/comedi/comedi_pcmcia.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #include diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h index 66fd313902c7..c7d37b38e730 100644 --- a/drivers/staging/comedi/comedi_pcmcia.h +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #ifndef _COMEDI_PCMCIA_H diff --git a/drivers/staging/comedi/comedi_usb.c b/drivers/staging/comedi/comedi_usb.c index 85e680b5f462..c632c2bae722 100644 --- a/drivers/staging/comedi/comedi_usb.c +++ b/drivers/staging/comedi/comedi_usb.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #include diff --git a/drivers/staging/comedi/comedi_usb.h b/drivers/staging/comedi/comedi_usb.h index 43920b2d2f7e..50287de7a239 100644 --- a/drivers/staging/comedi/comedi_usb.h +++ b/drivers/staging/comedi/comedi_usb.h @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #ifndef _COMEDI_USB_H diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 01117344eaed..fb1f07fa6fcf 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #ifndef _COMEDIDEV_H diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h index d37bdebcc7ea..e98cb9752dbc 100644 --- a/drivers/staging/comedi/comedilib.h +++ b/drivers/staging/comedi/comedilib.h @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998-2001 David A. Schleef - * - * 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. */ #ifndef _LINUX_COMEDILIB_H diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 393dd5c708ba..e618a87521a3 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -6,16 +6,6 @@ * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef * Copyright (C) 2002 Frank Mori Hess - * - * 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. */ #include diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 7d73bdd1e795..df9bba1b69ed 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2000 David A. Schleef - * - * 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. */ #include diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c index 2808bb717e95..50d38938ac6f 100644 --- a/drivers/staging/comedi/proc.c +++ b/drivers/staging/comedi/proc.c @@ -4,16 +4,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998 David A. Schleef - * - * 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. */ /* diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index a2321b533639..89d599877445 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -5,16 +5,6 @@ * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-8 David A. Schleef - * - * 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. */ #include -- cgit v1.2.3 From b79c0f4f5cc15cdf2b84b3431fa36c65b92260cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 14:58:47 +0100 Subject: staging: unisys: add SPDX identifiers to all unisys driver files It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the drivers/staging/unisys files files with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: David Kershner Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/iochannel.h | 1 + drivers/staging/unisys/include/visorbus.h | 1 + drivers/staging/unisys/visorbus/controlvmchannel.h | 1 + drivers/staging/unisys/visorbus/vbuschannel.h | 1 + drivers/staging/unisys/visorbus/visorbus_main.c | 1 + drivers/staging/unisys/visorbus/visorbus_private.h | 1 + drivers/staging/unisys/visorbus/visorchannel.c | 1 + drivers/staging/unisys/visorbus/visorchipset.c | 1 + drivers/staging/unisys/visorhba/visorhba_main.c | 1 + drivers/staging/unisys/visorinput/ultrainputreport.h | 1 + drivers/staging/unisys/visorinput/visorinput.c | 1 + drivers/staging/unisys/visornic/visornic_main.c | 1 + 12 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index 5cd407ca2251..bac5a04a9c28 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2016 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 1a0986ba3d24..8a0303ba5ed8 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 - 2013 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index 9ee9886a9aed..e10a1018b418 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index 981b180f3c4b..5681640fe7f1 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 6cb6eb0673c6..00ad44e2e18a 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright � 2010 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 4a8b12d7cfaa..17ed63dc55a2 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index aae16073ba03..d9de7eb05f40 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index fed554a43151..d9980a80da2d 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 0bcd3acb7b0c..83eba22a0f21 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2012 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h index 53975a09535f..27d90c78de91 100644 --- a/drivers/staging/unisys/visorinput/ultrainputreport.h +++ b/drivers/staging/unisys/visorinput/ultrainputreport.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 450f003743c0..11de40821f92 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2011 - 2015 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 6d8239163ba5..849c9b4800cf 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2012 - 2015 UNISYS CORPORATION * All rights reserved. * -- cgit v1.2.3 From 184e7e4a1166db0bd66267ae82c1557c4976ccd9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 14:58:48 +0100 Subject: staging: unisys: fix up some SPDX tags One .h file was missing a SPDX tag, and another one was wrong after looking at the text of the license itself, so fix both of these issues up at the same time. Cc: David Kershner Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/iochannel.h | 2 +- drivers/staging/unisys/include/visorchannel.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index bac5a04a9c28..6fc40f9cc768 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 - 2016 UNISYS CORPORATION * All rights reserved. diff --git a/drivers/staging/unisys/include/visorchannel.h b/drivers/staging/unisys/include/visorchannel.h index 33945749c8b6..b4c51d57fe90 100644 --- a/drivers/staging/unisys/include/visorchannel.h +++ b/drivers/staging/unisys/include/visorchannel.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 - 2013 UNISYS CORPORATION * All rights reserved. -- cgit v1.2.3 From 2baffb7205e0f4da158cabcf1116e4422af188a6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 14:58:49 +0100 Subject: staging: unisys: Remove redundant license text Now that the SPDX tag is in all unisys driver files, that identifies the license in a specific and legally-defined manner. So the extra GPL text wording can be removed as it is no longer needed at all. This is done on a quest to remove the 700+ different ways that files in the kernel describe the GPL license text. And there's unneeded stuff like the address (sometimes incorrect) for the FSF which is never needed. No copyright headers or other non-license-description text was removed. Cc: David Kershner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/iochannel.h | 11 ----------- drivers/staging/unisys/include/visorbus.h | 11 ----------- drivers/staging/unisys/include/visorchannel.h | 11 ----------- drivers/staging/unisys/visorbus/controlvmchannel.h | 10 ---------- drivers/staging/unisys/visorbus/vbuschannel.h | 10 ---------- drivers/staging/unisys/visorbus/visorbus_main.c | 10 ---------- drivers/staging/unisys/visorbus/visorbus_private.h | 10 ---------- drivers/staging/unisys/visorbus/visorchannel.c | 10 ---------- drivers/staging/unisys/visorbus/visorchipset.c | 10 ---------- drivers/staging/unisys/visorhba/visorhba_main.c | 11 ----------- drivers/staging/unisys/visorinput/ultrainputreport.h | 10 ---------- drivers/staging/unisys/visorinput/visorinput.c | 10 ---------- drivers/staging/unisys/visornic/visornic_main.c | 10 ---------- 13 files changed, 134 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index 6fc40f9cc768..a3c87544bf96 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -2,17 +2,6 @@ /* * Copyright (C) 2010 - 2016 UNISYS CORPORATION * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __IOCHANNEL_H__ diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 8a0303ba5ed8..fb4d3f814568 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -2,17 +2,6 @@ /* * Copyright (C) 2010 - 2013 UNISYS CORPORATION * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ /* diff --git a/drivers/staging/unisys/include/visorchannel.h b/drivers/staging/unisys/include/visorchannel.h index b4c51d57fe90..0c45b63e973c 100644 --- a/drivers/staging/unisys/include/visorchannel.h +++ b/drivers/staging/unisys/include/visorchannel.h @@ -2,17 +2,6 @@ /* * Copyright (C) 2010 - 2013 UNISYS CORPORATION * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __VISORCHANNEL_H__ diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index e10a1018b418..bcc7b8e3d8eb 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -2,16 +2,6 @@ /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __CONTROLVMCHANNEL_H__ diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index 5681640fe7f1..398b4b12e972 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -2,16 +2,6 @@ /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __VBUSCHANNEL_H__ diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 00ad44e2e18a..a16715525dc9 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -2,16 +2,6 @@ /* * Copyright � 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #include diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 17ed63dc55a2..e48498fedc49 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -2,16 +2,6 @@ /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __VISORBUS_PRIVATE_H__ diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index d9de7eb05f40..f3996a750c3b 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -2,16 +2,6 @@ /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ /* diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index d9980a80da2d..a3fba96dd167 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2,16 +2,6 @@ /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #include diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 83eba22a0f21..da650d64695a 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -2,17 +2,6 @@ /* * Copyright (c) 2012 - 2015 UNISYS CORPORATION * All rights reserved. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #include diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h index 27d90c78de91..67dac430ce0c 100644 --- a/drivers/staging/unisys/visorinput/ultrainputreport.h +++ b/drivers/staging/unisys/visorinput/ultrainputreport.h @@ -2,16 +2,6 @@ /* * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ #ifndef __SPAR_ULTRAINPUTREPORT_H__ diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 11de40821f92..dabc5b44208e 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -2,16 +2,6 @@ /* * Copyright (C) 2011 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ /* diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 849c9b4800cf..112a76ec0628 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1,16 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2012 - 2015 UNISYS CORPORATION * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. */ /* This driver lives in a spar partition, and registers to ethernet io -- cgit v1.2.3 From 1e80af4ccbf5f70bae7d1dde50ed0e66e2e0a8c8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:49 +0100 Subject: staging: xgifb: add SPDX identifiers to the remaining holdout file It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the xgifb/XGI_main_26.c file with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: Arnaud Patard Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index b813f1d460ce..6feecc55d2bc 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * XG20, XG21, XG40, XG42 frame buffer device * for Linux kernels 2.5.x, 2.6.x -- cgit v1.2.3 From 903ac63f918bc27ea34be6117d30ef321989c6a1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:50 +0100 Subject: staging: wilc1000: add SPDX identifiers to all wilc100 files It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the wilc100 driver files with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: Ganesh Krishna Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman Acked-by: Aditya Shankar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 1 + drivers/staging/wilc1000/wilc_debugfs.c | 1 + drivers/staging/wilc1000/wilc_sdio.c | 1 + drivers/staging/wilc1000/wilc_spi.c | 1 + drivers/staging/wilc1000/wilc_wlan.c | 1 + 5 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 119f3459b5bb..da1fe4390707 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include "wilc_wfi_cfgoperations.h" #include "wilc_wlan_if.h" #include "wilc_wlan.h" diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index ce54864569c7..0deb61a21b27 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * NewportMedia WiFi chipset driver test tools - wilc-debug * Copyright (c) 2012 NewportMedia Inc. diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 0189e3edbbbe..bd2b29b8b356 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) Atmel Corporation. All rights reserved. * diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 5ef84410e0f2..ff2ba1057cdf 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) Atmel Corporation. All rights reserved. * diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index f49dfa82f1b8..999fd09ad1cd 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include #include "wilc_wlan_if.h" #include "wilc_wlan.h" -- cgit v1.2.3 From f7056d335d919c15dc9ae26923969673da846e37 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:51 +0100 Subject: staging: wlan-ng: add SPDX identifiers to all wlan-ng driver files It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the wlan-ng driver files with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x.h | 1 + drivers/staging/wlan-ng/hfa384x_usb.c | 1 + drivers/staging/wlan-ng/p80211conv.c | 1 + drivers/staging/wlan-ng/p80211conv.h | 1 + drivers/staging/wlan-ng/p80211hdr.h | 1 + drivers/staging/wlan-ng/p80211ioctl.h | 1 + drivers/staging/wlan-ng/p80211metadef.h | 1 + drivers/staging/wlan-ng/p80211metastruct.h | 1 + drivers/staging/wlan-ng/p80211mgmt.h | 1 + drivers/staging/wlan-ng/p80211msg.h | 1 + drivers/staging/wlan-ng/p80211netdev.c | 1 + drivers/staging/wlan-ng/p80211netdev.h | 1 + drivers/staging/wlan-ng/p80211req.c | 1 + drivers/staging/wlan-ng/p80211req.h | 1 + drivers/staging/wlan-ng/p80211types.h | 1 + drivers/staging/wlan-ng/p80211wep.c | 1 + drivers/staging/wlan-ng/prism2fw.c | 1 + drivers/staging/wlan-ng/prism2mgmt.c | 1 + drivers/staging/wlan-ng/prism2mgmt.h | 1 + drivers/staging/wlan-ng/prism2mib.c | 1 + drivers/staging/wlan-ng/prism2sta.c | 1 + 21 files changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index f5a3a1ce21ce..85c3af00abd2 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* hfa384x.h * * Defines the constants and data structures for the hfa384x diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 197f5a914e8f..84f3657e26a2 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/prism2/driver/hfa384x_usb.c * * Functions that talk to the USB variantof the Intersil hfa384x MAC diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index c1b6d426bcad..855b424f6423 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/p80211/p80211conv.c * * Ether/802.11 conversions and packet buffer routines diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h index 66332b1fb6d5..28459dcea4b1 100644 --- a/drivers/staging/wlan-ng/p80211conv.h +++ b/drivers/staging/wlan-ng/p80211conv.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211conv.h * * Ether/802.11 conversions and packet buffer routines diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h index 2c44c613a586..133d70c08ecf 100644 --- a/drivers/staging/wlan-ng/p80211hdr.h +++ b/drivers/staging/wlan-ng/p80211hdr.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211hdr.h * * Macros, types, and functions for handling 802.11 MAC headers diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h index ab6067e65050..d8cde1d8870b 100644 --- a/drivers/staging/wlan-ng/p80211ioctl.h +++ b/drivers/staging/wlan-ng/p80211ioctl.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211ioctl.h * * Declares constants and types for the p80211 ioctls diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index ea3d9ce222b9..4ac2f08a520a 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. * -------------------------------------------------------------------- * diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index 850d897fc163..15b7c08e210d 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* This file is GENERATED AUTOMATICALLY. DO NOT EDIT OR MODIFY. * -------------------------------------------------------------------- * diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h index 653950fd9843..3c12929858cb 100644 --- a/drivers/staging/wlan-ng/p80211mgmt.h +++ b/drivers/staging/wlan-ng/p80211mgmt.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211mgmt.h * * Macros, types, and functions to handle 802.11 mgmt frames diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h index 40c5cf5997c7..ae119ecd74b0 100644 --- a/drivers/staging/wlan-ng/p80211msg.h +++ b/drivers/staging/wlan-ng/p80211msg.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211msg.h * * Macros, constants, types, and funcs for req and ind messages diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 0f503652740f..0b5aecd6d233 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/p80211/p80211knetdev.c * * Linux Kernel net device interface diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 8e0d08298c8b..cebbe746a52f 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211netdev.h * * WLAN net device structure and functions diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index afe847722cf7..c36d01469afc 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/p80211/p80211req.c * * Request/Indication/MacMgmt interface handling functions diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h index 6c72f59993e0..20be2c3af4c1 100644 --- a/drivers/staging/wlan-ng/p80211req.h +++ b/drivers/staging/wlan-ng/p80211req.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* p80211req.h * * Request handling functions diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 263ef2ddb197..94420562c418 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* * p80211types.h * diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 6492ffe59085..8bd92bba0ac1 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/p80211/p80211wep.c * * WEP encode/decode for P80211. diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 344bec8cc31b..5860d0d65841 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* from src/prism2/download/prism2dl.c * * utility for downloading prism2 images moved into kernelspace diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 72070593394a..78934e435fcf 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/prism2/driver/prism2mgmt.c * * Management request handler functions. diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index c062418f1202..564c3f4a3e03 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* prism2mgmt.h * * Declares the mgmt command handler functions diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index e41207d97309..edad299ff5ad 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/prism2/driver/prism2mib.c * * Management request for mibset/mibget diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 99316b9a4e49..fed0b8ceca6f 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /* src/prism2/driver/prism2sta.c * * Implements the station functionality for prism2 -- cgit v1.2.3 From 6b4c6ce892047022fd716e2afa5fb857f1bb0ee7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:52 +0100 Subject: staging: vt6656: add SPDX identifiers to all vt6656 driver files It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the vt6656 driver files with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: Forest Bond Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/baseband.c | 1 + drivers/staging/vt6656/baseband.h | 1 + drivers/staging/vt6656/card.c | 1 + drivers/staging/vt6656/card.h | 1 + drivers/staging/vt6656/channel.c | 1 + drivers/staging/vt6656/channel.h | 1 + drivers/staging/vt6656/desc.h | 1 + drivers/staging/vt6656/device.h | 1 + drivers/staging/vt6656/dpc.c | 1 + drivers/staging/vt6656/dpc.h | 1 + drivers/staging/vt6656/firmware.c | 1 + drivers/staging/vt6656/firmware.h | 1 + drivers/staging/vt6656/int.c | 1 + drivers/staging/vt6656/int.h | 1 + drivers/staging/vt6656/key.c | 1 + drivers/staging/vt6656/key.h | 1 + drivers/staging/vt6656/mac.c | 1 + drivers/staging/vt6656/mac.h | 1 + drivers/staging/vt6656/main_usb.c | 1 + drivers/staging/vt6656/power.c | 1 + drivers/staging/vt6656/power.h | 1 + drivers/staging/vt6656/rf.c | 1 + drivers/staging/vt6656/rf.h | 1 + drivers/staging/vt6656/rxtx.c | 1 + drivers/staging/vt6656/rxtx.h | 1 + drivers/staging/vt6656/usbpipe.c | 1 + drivers/staging/vt6656/usbpipe.h | 1 + drivers/staging/vt6656/wcmd.c | 1 + drivers/staging/vt6656/wcmd.h | 1 + 29 files changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 882fe54ce41d..eefe4ed5d026 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h index fe1c25c64cca..3ec69050b9a1 100644 --- a/drivers/staging/vt6656/baseband.h +++ b/drivers/staging/vt6656/baseband.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 4fd9cd64c6e8..fe12c9505eb1 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h index 7f08cda27e2c..fa65db740e80 100644 --- a/drivers/staging/vt6656/card.h +++ b/drivers/staging/vt6656/card.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index a4299f405d7f..403bd0b86aa6 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h index 62f18a959098..43f9452c32a6 100644 --- a/drivers/staging/vt6656/channel.h +++ b/drivers/staging/vt6656/channel.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h index 59e3071021bd..8dbf005db134 100644 --- a/drivers/staging/vt6656/desc.h +++ b/drivers/staging/vt6656/desc.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 74715c854856..8d19ec3ac692 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 655f0002f880..4299a32bfeb2 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h index 5d0454f3af0e..2d2c4e7489a6 100644 --- a/drivers/staging/vt6656/dpc.h +++ b/drivers/staging/vt6656/dpc.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c index 093a6048bd22..cc30fd36606f 100644 --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/firmware.h b/drivers/staging/vt6656/firmware.h index f753019c94c9..d77b1867b5cd 100644 --- a/drivers/staging/vt6656/firmware.h +++ b/drivers/staging/vt6656/firmware.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index c6ffbe0e2728..4b5455dc7c25 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index b5f1b4b02ce4..c79ff99e4d1c 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index cc18cb141bff..2e4cac60a46e 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h index cfc6c2131536..b34f19e9d5b0 100644 --- a/drivers/staging/vt6656/key.h +++ b/drivers/staging/vt6656/key.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c index 417fdad1f9ae..8c4cbb4c681d 100644 --- a/drivers/staging/vt6656/mac.c +++ b/drivers/staging/vt6656/mac.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h index 29f37a0ff156..f18be5df18ab 100644 --- a/drivers/staging/vt6656/mac.h +++ b/drivers/staging/vt6656/mac.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index cc6d8778fe5b..251f5d0d615b 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c index c466e0614bc4..cb234cd54f81 100644 --- a/drivers/staging/vt6656/power.c +++ b/drivers/staging/vt6656/power.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h index 859e75fc77ac..b3f706c02e1a 100644 --- a/drivers/staging/vt6656/power.h +++ b/drivers/staging/vt6656/power.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index 3a9d19a0b842..eb1b4865e0c0 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h index c907a18047d2..6b65d028f4b9 100644 --- a/drivers/staging/vt6656/rf.h +++ b/drivers/staging/vt6656/rf.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index a44abcce6fb4..ca870f0925a7 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h index 1ba8647bea86..0cae295ed729 100644 --- a/drivers/staging/vt6656/rxtx.h +++ b/drivers/staging/vt6656/rxtx.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index 23eaef458556..58f7b7ca9445 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h index 9fc5ac0ef6c1..af1dd45c6233 100644 --- a/drivers/staging/vt6656/usbpipe.h +++ b/drivers/staging/vt6656/usbpipe.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index b2fc17f1381b..45f464bcf47b 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h index 727ec14380c4..c5dd8f9ea8eb 100644 --- a/drivers/staging/vt6656/wcmd.h +++ b/drivers/staging/vt6656/wcmd.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. -- cgit v1.2.3 From d7c43082fc0d178a29a7ea1dcc9729abd38c7cf8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:53 +0100 Subject: staging: vt6655: add SPDX identifiers to all vt6655 driver files It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the vt6655 driver files with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: Forest Bond Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 1 + drivers/staging/vt6655/baseband.h | 1 + drivers/staging/vt6655/card.c | 1 + drivers/staging/vt6655/card.h | 1 + drivers/staging/vt6655/channel.c | 1 + drivers/staging/vt6655/channel.h | 1 + drivers/staging/vt6655/desc.h | 1 + drivers/staging/vt6655/device.h | 1 + drivers/staging/vt6655/device_cfg.h | 1 + drivers/staging/vt6655/device_main.c | 1 + drivers/staging/vt6655/dpc.c | 1 + drivers/staging/vt6655/dpc.h | 1 + drivers/staging/vt6655/key.c | 1 + drivers/staging/vt6655/key.h | 1 + drivers/staging/vt6655/mac.c | 1 + drivers/staging/vt6655/mac.h | 1 + drivers/staging/vt6655/power.c | 1 + drivers/staging/vt6655/power.h | 1 + drivers/staging/vt6655/rf.c | 1 + drivers/staging/vt6655/rf.h | 1 + drivers/staging/vt6655/rxtx.c | 1 + drivers/staging/vt6655/rxtx.h | 1 + drivers/staging/vt6655/srom.c | 1 + drivers/staging/vt6655/srom.h | 1 + drivers/staging/vt6655/tmacro.h | 1 + drivers/staging/vt6655/upc.h | 1 + 26 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 44dfa5421374..fa7ab1969fd5 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index feaf222574ee..1416c6d726d6 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 14034e342aa6..a83218fa5aae 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 1a04dbb57d42..8bdf8ddf7486 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index ab89956511a0..f41f71d57d0d 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h index 8fe70760e548..73617ad0579d 100644 --- a/drivers/staging/vt6655/channel.h +++ b/drivers/staging/vt6655/channel.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index 2fee6e759ad8..417411b64ecf 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 3ae40d846a09..f87413195285 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h index 0298ea923f97..cc48bd9ce2a5 100644 --- a/drivers/staging/vt6655/device_cfg.h +++ b/drivers/staging/vt6655/device_cfg.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 1123b4f1e1d6..6f8f19b54562 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 9b3fa779258a..4dd164df78fa 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h index 6e75fa9c5618..14c2491c12df 100644 --- a/drivers/staging/vt6655/dpc.h +++ b/drivers/staging/vt6655/dpc.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index d891993b20cf..4898664a6111 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h index a5024611af60..54b72e1be944 100644 --- a/drivers/staging/vt6655/key.h +++ b/drivers/staging/vt6655/key.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index f7550b215f72..350e36b9a20e 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index db401e32ae23..16198dfba4e8 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 716d2a80f840..ed245cdf03e8 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h index f360c5966523..46b9195404ab 100644 --- a/drivers/staging/vt6655/power.h +++ b/drivers/staging/vt6655/power.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index edf7db9d53b3..ae884219cdfe 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h index ba222301d49d..fff4861ee283 100644 --- a/drivers/staging/vt6655/rf.h +++ b/drivers/staging/vt6655/rf.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 3efe19a1b13f..4ea720661c2e 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h index 095258923ebd..6f32d5bc6d64 100644 --- a/drivers/staging/vt6655/rxtx.h +++ b/drivers/staging/vt6655/rxtx.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c index 635f271595f6..7d6dbe55065f 100644 --- a/drivers/staging/vt6655/srom.c +++ b/drivers/staging/vt6655/srom.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h index 6e03ab6dfa9d..cde2cff5ecfc 100644 --- a/drivers/staging/vt6655/srom.h +++ b/drivers/staging/vt6655/srom.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/tmacro.h b/drivers/staging/vt6655/tmacro.h index d6a0563ad55c..e5e3ebf0184f 100644 --- a/drivers/staging/vt6655/tmacro.h +++ b/drivers/staging/vt6655/tmacro.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index 9806b5989014..4fbb21f67573 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. -- cgit v1.2.3 From bdcb7be6089b86ed42fe2a5a6344973f75c1675b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:54 +0100 Subject: staging: android: add SPDX identifiers to all android driver files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's good to have SPDX identifiers in all files to make it easier to audit the kernel tree for correct licenses. Update the android driver files with the correct SPDX license identifier based on the license text in the file itself. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. This work is based on a script and data from Thomas Gleixner, Philippe Ombredanne, and Kate Stewart. Cc: "Arve Hjønnevåg" Cc: Riley Andrews Cc: Sumit Semwal Cc: Thomas Gleixner Cc: Kate Stewart Cc: Philippe Ombredanne Acked-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ashmem.c | 1 + drivers/staging/android/ashmem.h | 1 + drivers/staging/android/ion/ion-ioctl.c | 1 + drivers/staging/android/ion/ion.c | 1 + drivers/staging/android/ion/ion.h | 1 + drivers/staging/android/ion/ion_carveout_heap.c | 1 + drivers/staging/android/ion/ion_chunk_heap.c | 1 + drivers/staging/android/ion/ion_cma_heap.c | 1 + drivers/staging/android/ion/ion_heap.c | 1 + drivers/staging/android/ion/ion_page_pool.c | 1 + drivers/staging/android/ion/ion_system_heap.c | 1 + drivers/staging/android/uapi/ashmem.h | 1 + drivers/staging/android/uapi/ion.h | 1 + 13 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 0f695df14c9d..24298077a3ba 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* mm/ashmem.c * * Anonymous Shared Memory Subsystem, ashmem diff --git a/drivers/staging/android/ashmem.h b/drivers/staging/android/ashmem.h index 5abcfd7aa706..60d7208f110a 100644 --- a/drivers/staging/android/ashmem.h +++ b/drivers/staging/android/ashmem.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR Apache-2.0) /* * include/linux/ashmem.h * diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index c78989351f9c..4eda17713d82 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * * Copyright (C) 2011 Google, Inc. diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a7d9b0e98572..eac43db27b60 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * * drivers/staging/android/ion/ion.c diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index f5f9cd63f8e9..3e9327625426 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion.h * diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index fee7650d6fbb..ff1345d81564 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_carveout_heap.c * diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 102c09398317..b23694f6bf7f 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_chunk_heap.c * diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index dd5545d9990a..6f6b1e208ec5 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_cma_heap.c * diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 91faa7f035b9..97344eba611c 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_heap.c * diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 817849df9de3..4c63e8f25b3f 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_mem_pool.c * diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 4dc5d7a589c2..9ff940095e3b 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/ion/ion_system_heap.c * diff --git a/drivers/staging/android/uapi/ashmem.h b/drivers/staging/android/uapi/ashmem.h index 13df42d200b7..5b531af6820e 100644 --- a/drivers/staging/android/uapi/ashmem.h +++ b/drivers/staging/android/uapi/ashmem.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR Apache-2.0) /* * drivers/staging/android/uapi/ashmem.h * diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index 9e21451149d0..63ae80f658dc 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/staging/android/uapi/ion.h * -- cgit v1.2.3 From dd41dab5d54f4cde127ba47ab6764731428f96ca Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:55 +0100 Subject: staging: vt6656: Remove redundant license text Now that the SPDX tag is in all vt6656 files, that identifies the license in a specific and legally-defined manner. So the extra GPL text wording can be removed as it is no longer needed at all. This is done on a quest to remove the 700+ different ways that files in the kernel describe the GPL license text. And there's unneeded stuff like the address (sometimes incorrect) for the FSF which is never needed. No copyright headers or other non-license-description text was removed. Cc: Forest Bond Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/baseband.c | 11 ----------- drivers/staging/vt6656/baseband.h | 11 ----------- drivers/staging/vt6656/card.c | 11 ----------- drivers/staging/vt6656/card.h | 11 ----------- drivers/staging/vt6656/channel.c | 11 ----------- drivers/staging/vt6656/channel.h | 11 ----------- drivers/staging/vt6656/desc.h | 11 ----------- drivers/staging/vt6656/device.h | 11 ----------- drivers/staging/vt6656/dpc.c | 11 ----------- drivers/staging/vt6656/dpc.h | 11 ----------- drivers/staging/vt6656/firmware.c | 11 ----------- drivers/staging/vt6656/firmware.h | 11 ----------- drivers/staging/vt6656/int.c | 11 ----------- drivers/staging/vt6656/int.h | 11 ----------- drivers/staging/vt6656/key.c | 11 ----------- drivers/staging/vt6656/key.h | 11 ----------- drivers/staging/vt6656/mac.c | 11 ----------- drivers/staging/vt6656/mac.h | 11 ----------- drivers/staging/vt6656/main_usb.c | 11 ----------- drivers/staging/vt6656/power.c | 11 ----------- drivers/staging/vt6656/power.h | 11 ----------- drivers/staging/vt6656/rf.c | 11 ----------- drivers/staging/vt6656/rf.h | 11 ----------- drivers/staging/vt6656/rxtx.c | 11 ----------- drivers/staging/vt6656/rxtx.h | 11 ----------- drivers/staging/vt6656/usbpipe.c | 11 ----------- drivers/staging/vt6656/usbpipe.h | 11 ----------- drivers/staging/vt6656/wcmd.c | 11 ----------- drivers/staging/vt6656/wcmd.h | 11 ----------- 29 files changed, 319 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index eefe4ed5d026..b29ba237fa29 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: baseband.c * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h index 3ec69050b9a1..a907e3026012 100644 --- a/drivers/staging/vt6656/baseband.h +++ b/drivers/staging/vt6656/baseband.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: baseband.h * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index fe12c9505eb1..501f482b41c4 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: card.c * Purpose: Provide functions to setup NIC operation mode * Functions: diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h index fa65db740e80..0a91d9ba4688 100644 --- a/drivers/staging/vt6656/card.h +++ b/drivers/staging/vt6656/card.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: card.h * * Purpose: Provide functions to setup NIC operation mode diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index 403bd0b86aa6..5d57d34577f5 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: channel.c * * Purpose: Channel number mapping diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h index 43f9452c32a6..6d0d2825d992 100644 --- a/drivers/staging/vt6656/channel.h +++ b/drivers/staging/vt6656/channel.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: channel.h * * Purpose: Country Regulation Rules header file diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h index 8dbf005db134..ac45ebb71195 100644 --- a/drivers/staging/vt6656/desc.h +++ b/drivers/staging/vt6656/desc.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: desc.h * * Purpose:The header file of descriptor diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 8d19ec3ac692..a2feeb916836 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: device.h * * Purpose: MAC Data structure diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 4299a32bfeb2..c3b5b1431048 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: dpc.c * * Purpose: handle dpc rx functions diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h index 2d2c4e7489a6..ddd0cb710512 100644 --- a/drivers/staging/vt6656/dpc.h +++ b/drivers/staging/vt6656/dpc.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: dpc.h * * Purpose: diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c index cc30fd36606f..38521c338917 100644 --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: baseband.c * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6656/firmware.h b/drivers/staging/vt6656/firmware.h index d77b1867b5cd..f30ae90cbb1f 100644 --- a/drivers/staging/vt6656/firmware.h +++ b/drivers/staging/vt6656/firmware.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: firmware.h * * Purpose: Version and Release Information diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index 4b5455dc7c25..504424b19fcf 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: int.c * * Purpose: Handle USB interrupt endpoint diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index c79ff99e4d1c..1e6ff925701a 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: int.h * * Purpose: diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index 2e4cac60a46e..91dede54cc1f 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: key.c * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h index b34f19e9d5b0..1306ff441b87 100644 --- a/drivers/staging/vt6656/key.h +++ b/drivers/staging/vt6656/key.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: key.h * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c index 8c4cbb4c681d..0b543854ea97 100644 --- a/drivers/staging/vt6656/mac.c +++ b/drivers/staging/vt6656/mac.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: mac.c * * Purpose: MAC routines diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h index f18be5df18ab..94e700fcd0b6 100644 --- a/drivers/staging/vt6656/mac.h +++ b/drivers/staging/vt6656/mac.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: mac.h * * Purpose: MAC routines diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 251f5d0d615b..1b51b835dd6f 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: main_usb.c * * Purpose: driver entry for initial, open, close, tx and rx. diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c index cb234cd54f81..7a086c72d5a8 100644 --- a/drivers/staging/vt6656/power.c +++ b/drivers/staging/vt6656/power.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: power.c * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h index b3f706c02e1a..d5a3198206da 100644 --- a/drivers/staging/vt6656/power.h +++ b/drivers/staging/vt6656/power.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: power.h * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index eb1b4865e0c0..18f75dcc65d2 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: rf.c * * Purpose: rf function code diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h index 6b65d028f4b9..f77866a9c177 100644 --- a/drivers/staging/vt6656/rf.h +++ b/drivers/staging/vt6656/rf.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: rf.h * * Purpose: diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index ca870f0925a7..26ca3fa29301 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: rxtx.c * * Purpose: handle WMAC/802.3/802.11 rx & tx functions diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h index 0cae295ed729..44698f41a234 100644 --- a/drivers/staging/vt6656/rxtx.h +++ b/drivers/staging/vt6656/rxtx.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: rxtx.h * * Purpose: diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index 58f7b7ca9445..273176386a51 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: usbpipe.c * * Purpose: Handle USB control endpoint diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h index af1dd45c6233..5d7708fcf557 100644 --- a/drivers/staging/vt6656/usbpipe.h +++ b/drivers/staging/vt6656/usbpipe.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: usbpipe.h * * Purpose: diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 45f464bcf47b..3eb2f11a5de1 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: wcmd.c * * Purpose: Handles the management command interface functions diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h index c5dd8f9ea8eb..4a96f4de980d 100644 --- a/drivers/staging/vt6656/wcmd.h +++ b/drivers/staging/vt6656/wcmd.h @@ -3,17 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * - * * File: wcmd.h * * Purpose: Handles the management command interface functions -- cgit v1.2.3 From dbc9f36cf7bc6d431c63c4785ad3c4bc0f306588 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:56 +0100 Subject: staging: vt6655: Remove redundant license text Now that the SPDX tag is in all vt6655 files, that identifies the license in a specific and legally-defined manner. So the extra GPL text wording can be removed as it is no longer needed at all. This is done on a quest to remove the 700+ different ways that files in the kernel describe the GPL license text. And there's unneeded stuff like the address (sometimes incorrect) for the FSF which is never needed. No copyright headers or other non-license-description text was removed. Cc: Forest Bond Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/baseband.c | 10 ---------- drivers/staging/vt6655/baseband.h | 10 ---------- drivers/staging/vt6655/card.c | 10 ---------- drivers/staging/vt6655/card.h | 10 ---------- drivers/staging/vt6655/channel.c | 10 ---------- drivers/staging/vt6655/channel.h | 11 ----------- drivers/staging/vt6655/desc.h | 10 ---------- drivers/staging/vt6655/device.h | 10 ---------- drivers/staging/vt6655/device_cfg.h | 10 ---------- drivers/staging/vt6655/device_main.c | 10 ---------- drivers/staging/vt6655/dpc.c | 10 ---------- drivers/staging/vt6655/dpc.h | 10 ---------- drivers/staging/vt6655/key.c | 10 ---------- drivers/staging/vt6655/key.h | 10 ---------- drivers/staging/vt6655/mac.c | 10 ---------- drivers/staging/vt6655/mac.h | 10 ---------- drivers/staging/vt6655/power.c | 10 ---------- drivers/staging/vt6655/power.h | 10 ---------- drivers/staging/vt6655/rf.c | 10 ---------- drivers/staging/vt6655/rf.h | 10 ---------- drivers/staging/vt6655/rxtx.c | 10 ---------- drivers/staging/vt6655/rxtx.h | 10 ---------- drivers/staging/vt6655/srom.c | 10 ---------- drivers/staging/vt6655/srom.h | 10 ---------- drivers/staging/vt6655/tmacro.h | 10 ---------- drivers/staging/vt6655/upc.h | 10 ---------- 26 files changed, 261 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index fa7ab1969fd5..f0b163473426 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: baseband.c * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index 1416c6d726d6..b8ee33dcb352 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: baseband.h * * Purpose: Implement functions to access baseband diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index a83218fa5aae..ea0a4b57852c 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: card.c * Purpose: Provide functions to setup NIC operation mode * Functions: diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h index 8bdf8ddf7486..487039a64587 100644 --- a/drivers/staging/vt6655/card.h +++ b/drivers/staging/vt6655/card.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: card.h * * Purpose: Provide functions to setup NIC operation mode diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index f41f71d57d0d..dec6f0f23b88 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: channel.c * */ diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h index 73617ad0579d..53f623a4af65 100644 --- a/drivers/staging/vt6655/channel.h +++ b/drivers/staging/vt6655/channel.h @@ -3,18 +3,7 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: channel.h - * */ #ifndef _CHANNEL_H_ diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index 417411b64ecf..b4a0037b40c1 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: desc.h * * Purpose:The header file of descriptor diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index f87413195285..2f9e9219e8c8 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: device.h * * Purpose: MAC Data structure diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h index cc48bd9ce2a5..73f904b51b96 100644 --- a/drivers/staging/vt6655/device_cfg.h +++ b/drivers/staging/vt6655/device_cfg.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: device_cfg.h * * Purpose: Driver configuration header diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 6f8f19b54562..676a0882cdd4 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: device_main.c * * Purpose: driver entry for initial, open, close, tx and rx. diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 4dd164df78fa..088d2d9dbc21 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: dpc.c * * Purpose: handle dpc rx functions diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h index 14c2491c12df..93af4220605f 100644 --- a/drivers/staging/vt6655/dpc.h +++ b/drivers/staging/vt6655/dpc.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: dpc.h * * Purpose: diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index 4898664a6111..4d6b48fd119d 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: key.c * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h index 54b72e1be944..0942d8703f98 100644 --- a/drivers/staging/vt6655/key.h +++ b/drivers/staging/vt6655/key.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: key.h * * Purpose: Implement functions for 802.11i Key management diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 350e36b9a20e..4750863c1bb7 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: mac.c * * Purpose: MAC routines diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 16198dfba4e8..b8ab09434773 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: mac.h * * Purpose: MAC routines diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index ed245cdf03e8..d6c581b31569 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: power.c * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h index 46b9195404ab..2ec40045fddb 100644 --- a/drivers/staging/vt6655/power.h +++ b/drivers/staging/vt6655/power.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: power.h * * Purpose: Handles 802.11 power management functions diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index ae884219cdfe..03b0d56dbe9e 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: rf.c * * Purpose: rf function code diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h index fff4861ee283..bfce5a89657d 100644 --- a/drivers/staging/vt6655/rf.h +++ b/drivers/staging/vt6655/rf.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: rf.h * * Purpose: diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 4ea720661c2e..9aa4d5262aaa 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: rxtx.c * * Purpose: handle WMAC/802.3/802.11 rx & tx functions diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h index 6f32d5bc6d64..08db848613f0 100644 --- a/drivers/staging/vt6655/rxtx.h +++ b/drivers/staging/vt6655/rxtx.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: rxtx.h * * Purpose: diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c index 7d6dbe55065f..df57d120ed30 100644 --- a/drivers/staging/vt6655/srom.c +++ b/drivers/staging/vt6655/srom.c @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: srom.c * * Purpose:Implement functions to access eeprom diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h index cde2cff5ecfc..577f20dc4308 100644 --- a/drivers/staging/vt6655/srom.h +++ b/drivers/staging/vt6655/srom.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: srom.h * * Purpose: Implement functions to access eeprom diff --git a/drivers/staging/vt6655/tmacro.h b/drivers/staging/vt6655/tmacro.h index e5e3ebf0184f..6795b5d74cfc 100644 --- a/drivers/staging/vt6655/tmacro.h +++ b/drivers/staging/vt6655/tmacro.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: tmacro.h * * Purpose: define basic common types and macros diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index 4fbb21f67573..61b3e568ff9a 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -3,16 +3,6 @@ * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * - * 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. - * * File: upc.h * * Purpose: Macros to access device -- cgit v1.2.3 From 204a68f0e845b46f9f72d2a183dfeb652a8d641a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Nov 2017 21:07:57 +0100 Subject: staging: android: Remove redundant license text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the SPDX tag is in all android files, that identifies the license in a specific and legally-defined manner. So the extra GPL text wording can be removed as it is no longer needed at all. This is done on a quest to remove the 700+ different ways that files in the kernel describe the GPL license text. And there's unneeded stuff like the address (sometimes incorrect) for the FSF which is never needed. No copyright headers or other non-license-description text was removed. Cc: "Arve Hjønnevåg" Cc: Riley Andrews Cc: Sumit Semwal Acked-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ashmem.c | 9 --------- drivers/staging/android/ion/ion-ioctl.c | 11 ----------- drivers/staging/android/ion/ion.c | 11 ----------- drivers/staging/android/ion/ion.h | 10 ---------- drivers/staging/android/ion/ion_carveout_heap.c | 10 ---------- drivers/staging/android/ion/ion_chunk_heap.c | 10 ---------- drivers/staging/android/ion/ion_cma_heap.c | 10 ---------- drivers/staging/android/ion/ion_heap.c | 10 ---------- drivers/staging/android/ion/ion_page_pool.c | 10 ---------- drivers/staging/android/ion/ion_system_heap.c | 10 ---------- drivers/staging/android/uapi/ion.h | 10 ---------- 11 files changed, 111 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 24298077a3ba..4e8947923904 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -6,15 +6,6 @@ * Copyright (C) 2008 Google, Inc. * * Robert Love - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #define pr_fmt(fmt) "ashmem: " fmt diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index 4eda17713d82..6ed2cc15c8c0 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -1,17 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index eac43db27b60..7630432a7de8 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1,19 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* - * * drivers/staging/android/ion/ion.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 3e9327625426..7409437ffdd8 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -3,16 +3,6 @@ * drivers/staging/android/ion/ion.h * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #ifndef _ION_H diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index ff1345d81564..e129237a0417 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -3,16 +3,6 @@ * drivers/staging/android/ion/ion_carveout_heap.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include #include diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index b23694f6bf7f..159d72f5bc42 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -3,16 +3,6 @@ * drivers/staging/android/ion/ion_chunk_heap.c * * Copyright (C) 2012 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include #include diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 6f6b1e208ec5..50a9736ab455 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -4,16 +4,6 @@ * * Copyright (C) Linaro 2012 * Author: for ST-Ericsson. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 97344eba611c..2af86a2d94fb 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -3,16 +3,6 @@ * drivers/staging/android/ion/ion_heap.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 4c63e8f25b3f..b3017f12835f 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -3,16 +3,6 @@ * drivers/staging/android/ion/ion_mem_pool.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 9ff940095e3b..71c4228f8238 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -3,16 +3,6 @@ * drivers/staging/android/ion/ion_system_heap.c * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index 63ae80f658dc..825d3e95ccd3 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -3,16 +3,6 @@ * drivers/staging/android/uapi/ion.h * * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #ifndef _UAPI_LINUX_ION_H -- cgit v1.2.3 From 8fc2a66b094efc3d0ac04d20f25b259e9b654bcb Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Mon, 27 Nov 2017 15:20:04 +0100 Subject: staging: most: fix Makefile This patch fixes the names of the CONFIG symbols and the subfolders make is supposed to enter in order to build the selected modules. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile index 7f6aa9c515fa..f8bcf488ecf2 100644 --- a/drivers/staging/most/Makefile +++ b/drivers/staging/most/Makefile @@ -3,10 +3,10 @@ obj-$(CONFIG_MOST) += most_core.o most_core-y := core.o ccflags-y += -Idrivers/staging/ -obj-$(CONFIG_AIM_CDEV) += aim-cdev/ -obj-$(CONFIG_AIM_NETWORK) += aim-network/ -obj-$(CONFIG_AIM_SOUND) += aim-sound/ -obj-$(CONFIG_AIM_V4L2) += aim-v4l2/ -obj-$(CONFIG_HDM_DIM2) += hdm-dim2/ -obj-$(CONFIG_HDM_I2C) += hdm-i2c/ -obj-$(CONFIG_HDM_USB) += hdm-usb/ +obj-$(CONFIG_MOST_CDEV) += cdev/ +obj-$(CONFIG_MOST_NET) += net/ +obj-$(CONFIG_MOST_SOUND) += sound/ +obj-$(CONFIG_MOST_VIDEO) += video/ +obj-$(CONFIG_MOST_DIM2) += dim2/ +obj-$(CONFIG_MOST_I2C) += i2c/ +obj-$(CONFIG_MOST_USB) += usb/ -- cgit v1.2.3 From fc10bf7e59008f401d9bd4248721f16bd6c98439 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Mon, 27 Nov 2017 15:20:05 +0100 Subject: staging: most: remove legacy folders This patch removes the legacy folders of the modules. It is needed to clean up the driver's source tree. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/Makefile | 4 ---- drivers/staging/most/aim-network/Makefile | 4 ---- drivers/staging/most/aim-sound/Makefile | 4 ---- drivers/staging/most/aim-v4l2/Makefile | 5 ----- drivers/staging/most/hdm-dim2/Makefile | 5 ----- drivers/staging/most/hdm-i2c/Makefile | 3 --- drivers/staging/most/hdm-usb/Makefile | 4 ---- 7 files changed, 29 deletions(-) delete mode 100644 drivers/staging/most/aim-cdev/Makefile delete mode 100644 drivers/staging/most/aim-network/Makefile delete mode 100644 drivers/staging/most/aim-sound/Makefile delete mode 100644 drivers/staging/most/aim-v4l2/Makefile delete mode 100644 drivers/staging/most/hdm-dim2/Makefile delete mode 100644 drivers/staging/most/hdm-i2c/Makefile delete mode 100644 drivers/staging/most/hdm-usb/Makefile (limited to 'drivers') diff --git a/drivers/staging/most/aim-cdev/Makefile b/drivers/staging/most/aim-cdev/Makefile deleted file mode 100644 index b7afcb40997d..000000000000 --- a/drivers/staging/most/aim-cdev/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_AIM_CDEV) += aim_cdev.o - -aim_cdev-objs := cdev.o -ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-network/Makefile b/drivers/staging/most/aim-network/Makefile deleted file mode 100644 index a874aac8d285..000000000000 --- a/drivers/staging/most/aim-network/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_AIM_NETWORK) += aim_network.o - -aim_network-objs := networking.o -ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-sound/Makefile b/drivers/staging/most/aim-sound/Makefile deleted file mode 100644 index d41b85baa83f..000000000000 --- a/drivers/staging/most/aim-sound/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_AIM_SOUND) += aim_sound.o - -aim_sound-objs := sound.o -ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile deleted file mode 100644 index a8e8b4930355..000000000000 --- a/drivers/staging/most/aim-v4l2/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o - -aim_v4l2-objs := video.o - -ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/hdm-dim2/Makefile b/drivers/staging/most/hdm-dim2/Makefile deleted file mode 100644 index b66492bf7674..000000000000 --- a/drivers/staging/most/hdm-dim2/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o - -hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o -ccflags-y += -Idrivers/staging/ -ccflags-y += -Idrivers/staging/most/aim-network/ diff --git a/drivers/staging/most/hdm-i2c/Makefile b/drivers/staging/most/hdm-i2c/Makefile deleted file mode 100644 index 6ddc78aae3d9..000000000000 --- a/drivers/staging/most/hdm-i2c/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_HDM_I2C) += hdm_i2c.o - -ccflags-y += -Idrivers/staging/ diff --git a/drivers/staging/most/hdm-usb/Makefile b/drivers/staging/most/hdm-usb/Makefile deleted file mode 100644 index 4fea7c2a7755..000000000000 --- a/drivers/staging/most/hdm-usb/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_HDM_USB) += hdm_usb.o - -ccflags-y += -Idrivers/staging/ -ccflags-y += -Idrivers/staging/most/aim-network/ -- cgit v1.2.3 From f15e3ad3ef22de652f5eccf34938f981af8672d3 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Mon, 27 Nov 2017 15:20:06 +0100 Subject: staging: most: make DEVICE_ATTR structures static In order to limit the scope of the DEVICE_ATTR structure this patch adds the keywork static. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/dim2/sysfs.c | 2 +- drivers/staging/most/usb/usb.c | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c index 7ead7030c6b8..c85b2cdcdca3 100644 --- a/drivers/staging/most/dim2/sysfs.c +++ b/drivers/staging/most/dim2/sysfs.c @@ -21,7 +21,7 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%s\n", state ? "locked" : ""); } -DEVICE_ATTR_RO(state); +static DEVICE_ATTR_RO(state); static struct attribute *dev_attrs[] = { &dev_attr_state.attr, diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index c72e9c3bacec..8d23075ae165 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -945,21 +945,21 @@ static ssize_t value_store(struct device *dev, struct device_attribute *attr, return count; } -DEVICE_ATTR(ni_state, 0444, value_show, NULL); -DEVICE_ATTR(packet_bandwidth, 0444, value_show, NULL); -DEVICE_ATTR(node_address, 0444, value_show, NULL); -DEVICE_ATTR(node_position, 0444, value_show, NULL); -DEVICE_ATTR(sync_ep, 0200, NULL, value_store); -DEVICE_ATTR(mep_filter, 0644, value_show, value_store); -DEVICE_ATTR(mep_hash0, 0644, value_show, value_store); -DEVICE_ATTR(mep_hash1, 0644, value_show, value_store); -DEVICE_ATTR(mep_hash2, 0644, value_show, value_store); -DEVICE_ATTR(mep_hash3, 0644, value_show, value_store); -DEVICE_ATTR(mep_eui48_hi, 0644, value_show, value_store); -DEVICE_ATTR(mep_eui48_mi, 0644, value_show, value_store); -DEVICE_ATTR(mep_eui48_lo, 0644, value_show, value_store); -DEVICE_ATTR(arb_address, 0644, value_show, value_store); -DEVICE_ATTR(arb_value, 0644, value_show, value_store); +static DEVICE_ATTR(ni_state, 0444, value_show, NULL); +static DEVICE_ATTR(packet_bandwidth, 0444, value_show, NULL); +static DEVICE_ATTR(node_address, 0444, value_show, NULL); +static DEVICE_ATTR(node_position, 0444, value_show, NULL); +static DEVICE_ATTR(sync_ep, 0200, NULL, value_store); +static DEVICE_ATTR(mep_filter, 0644, value_show, value_store); +static DEVICE_ATTR(mep_hash0, 0644, value_show, value_store); +static DEVICE_ATTR(mep_hash1, 0644, value_show, value_store); +static DEVICE_ATTR(mep_hash2, 0644, value_show, value_store); +static DEVICE_ATTR(mep_hash3, 0644, value_show, value_store); +static DEVICE_ATTR(mep_eui48_hi, 0644, value_show, value_store); +static DEVICE_ATTR(mep_eui48_mi, 0644, value_show, value_store); +static DEVICE_ATTR(mep_eui48_lo, 0644, value_show, value_store); +static DEVICE_ATTR(arb_address, 0644, value_show, value_store); +static DEVICE_ATTR(arb_value, 0644, value_show, value_store); static struct attribute *dci_attrs[] = { &dev_attr_ni_state.attr, -- cgit v1.2.3 From 6cf83f2a9e81c500819938fad3555081471212c6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Nov 2017 14:19:56 +0100 Subject: staging: bcm2835-camera use ktime_t for timestamps struct timeval is deprecated for in-kernel use, and converting this function to use ktime_t makes it simpler as well. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/bcm2835-camera/bcm2835-camera.c | 37 ++++++---------------- .../vc04_services/bcm2835-camera/bcm2835-camera.h | 2 +- 2 files changed, 10 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index be936b8fe317..d8766b166675 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -343,37 +343,18 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, if (dev->capture.frame_count) { if (dev->capture.vc_start_timestamp != -1 && pts != 0) { - struct timeval timestamp; + ktime_t timestamp; s64 runtime_us = pts - dev->capture.vc_start_timestamp; - u32 div = 0; - u32 rem = 0; - - div = - div_u64_rem(runtime_us, USEC_PER_SEC, &rem); - timestamp.tv_sec = - dev->capture.kernel_start_ts.tv_sec + div; - timestamp.tv_usec = - dev->capture.kernel_start_ts.tv_usec + rem; - - if (timestamp.tv_usec >= - USEC_PER_SEC) { - timestamp.tv_sec++; - timestamp.tv_usec -= - USEC_PER_SEC; - } + timestamp = ktime_add_us(dev->capture.kernel_start_ts, + runtime_us); v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Convert start time %d.%06d and %llu " - "with offset %llu to %d.%06d\n", - (int)dev->capture.kernel_start_ts. - tv_sec, - (int)dev->capture.kernel_start_ts. - tv_usec, + "Convert start time %llu and %llu " + "with offset %llu to %llu\n", + ktime_to_ns(dev->capture.kernel_start_ts), dev->capture.vc_start_timestamp, pts, - (int)timestamp.tv_sec, - (int)timestamp.tv_usec); - buf->vb.vb2_buf.timestamp = timestamp.tv_sec * 1000000000ULL + - timestamp.tv_usec * 1000ULL; + ktime_to_ns(timestamp)); + buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp); } else { buf->vb.vb2_buf.timestamp = ktime_get_ns(); } @@ -547,7 +528,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) "Start time %lld size %d\n", dev->capture.vc_start_timestamp, parameter_size); - v4l2_get_timestamp(&dev->capture.kernel_start_ts); + dev->capture.kernel_start_ts = ktime_get(); /* enable the camera port */ dev->capture.port->cb_ctx = dev; diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h index 404037476bc5..83920683a448 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h @@ -92,7 +92,7 @@ struct bm2835_mmal_dev { /* VC start timestamp for streaming */ s64 vc_start_timestamp; /* Kernel start timestamp for streaming */ - struct timeval kernel_start_ts; + ktime_t kernel_start_ts; struct vchiq_mmal_port *port; /* port being used for capture */ /* camera port being used for capture */ -- cgit v1.2.3 From ec8354b98b60410ec92935702fce404717be419b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Nov 2017 14:20:00 +0100 Subject: staging: imx: use ktime_t for timestamps The imx media driver passes around monotonic timestamps in the deprecated 'timespec' format. This is not a problem for the driver, as they won't overflow, but moving to either timespec64 or ktime_t is preferred. I'm picking ktime_t for simplicity here. frame_interval_monitor() is the main function that changes, as it tries to compare a time interval in microseconds. The algorithm slightly changes here, to avoid 64-bit division. The code previously assumed that the error was at most 32-bit worth of microseconds here, so I'm making the same assumption but add an explicit test for it. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/imx/imx-media-csi.c | 8 ++------ drivers/staging/media/imx/imx-media-fim.c | 30 +++++++++++++++++------------- drivers/staging/media/imx/imx-media.h | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index bb1d6dafca83..26994b429cf2 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -207,13 +207,9 @@ static irqreturn_t csi_idmac_eof_interrupt(int irq, void *dev_id) goto unlock; } - if (priv->fim) { - struct timespec cur_ts; - - ktime_get_ts(&cur_ts); + if (priv->fim) /* call frame interval monitor */ - imx_media_fim_eof_monitor(priv->fim, &cur_ts); - } + imx_media_fim_eof_monitor(priv->fim, ktime_get()); csi_vb2_buf_done(priv); diff --git a/drivers/staging/media/imx/imx-media-fim.c b/drivers/staging/media/imx/imx-media-fim.c index 47275ef803f3..6df189135db8 100644 --- a/drivers/staging/media/imx/imx-media-fim.c +++ b/drivers/staging/media/imx/imx-media-fim.c @@ -66,7 +66,7 @@ struct imx_media_fim { int icap_flags; int counter; - struct timespec last_ts; + ktime_t last_ts; unsigned long sum; /* usec */ unsigned long nominal; /* usec */ @@ -147,22 +147,26 @@ static void send_fim_event(struct imx_media_fim *fim, unsigned long error) * (presumably random) interrupt latency. */ static void frame_interval_monitor(struct imx_media_fim *fim, - struct timespec *ts) + ktime_t timestamp) { - unsigned long interval, error, error_avg; + long long interval, error; + unsigned long error_avg; bool send_event = false; - struct timespec diff; if (!fim->enabled || ++fim->counter <= 0) goto out_update_ts; - diff = timespec_sub(*ts, fim->last_ts); - interval = diff.tv_sec * 1000 * 1000 + diff.tv_nsec / 1000; - error = abs(interval - fim->nominal); + /* max error is less than l00µs, so use 32-bit division or fail */ + interval = ktime_to_ns(ktime_sub(timestamp, fim->last_ts)); + error = abs(interval - NSEC_PER_USEC * (u64)fim->nominal); + if (error > U32_MAX) + error = U32_MAX; + else + error = abs((u32)error / NSEC_PER_USEC); if (fim->tolerance_max && error >= fim->tolerance_max) { dev_dbg(fim->sd->dev, - "FIM: %lu ignored, out of tolerance bounds\n", + "FIM: %llu ignored, out of tolerance bounds\n", error); fim->counter--; goto out_update_ts; @@ -184,7 +188,7 @@ static void frame_interval_monitor(struct imx_media_fim *fim, } out_update_ts: - fim->last_ts = *ts; + fim->last_ts = timestamp; if (send_event) send_fim_event(fim, error_avg); } @@ -195,14 +199,14 @@ out_update_ts: * to interrupt latency. */ static void fim_input_capture_handler(int channel, void *dev_id, - struct timespec *ts) + ktime_t timestamp) { struct imx_media_fim *fim = dev_id; unsigned long flags; spin_lock_irqsave(&fim->lock, flags); - frame_interval_monitor(fim, ts); + frame_interval_monitor(fim, timestamp); if (!completion_done(&fim->icap_first_event)) complete(&fim->icap_first_event); @@ -405,14 +409,14 @@ err_free: * the frame_interval_monitor() is called by the input capture event * callback handler in that case. */ -void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts) +void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp) { unsigned long flags; spin_lock_irqsave(&fim->lock, flags); if (!icap_enabled(fim)) - frame_interval_monitor(fim, ts); + frame_interval_monitor(fim, timestamp); spin_unlock_irqrestore(&fim->lock, flags); } diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index d409170632bd..ac3ab115394f 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -280,7 +280,7 @@ int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd, /* imx-media-fim.c */ struct imx_media_fim; -void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts); +void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp); int imx_media_fim_set_stream(struct imx_media_fim *fim, const struct v4l2_fract *frame_interval, bool on); -- cgit v1.2.3 From da1725ca4869461890d5fd1be5202ff691c05f78 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 Nov 2017 12:47:20 +0100 Subject: staging/sm750fb: Add "port to atomic kms" to TODO fbdev is closed for new drivers, drm won't take anything but atomic drivers. Cc: Sudip Mukherjee Cc: Teddy Wang Cc: Sudip Mukherjee Cc: Bartlomiej Zolnierkiewicz Cc: dri-devel@lists.freedesktop.org Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/TODO | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/sm750fb/TODO b/drivers/staging/sm750fb/TODO index a3a877d90066..f710ab15abfe 100644 --- a/drivers/staging/sm750fb/TODO +++ b/drivers/staging/sm750fb/TODO @@ -6,8 +6,8 @@ TODO: - check on hardware effects of removal of USE_HW_I2C and USE_DVICHIP (these two are supposed to be sample code which is given here if someone wants to use those functionalities) -- move it to drivers/video/fbdev -- modify the code for drm framework +- must be ported to the atomic kms framework in the drm subsystem (which will + give you a basic fbdev driver for free) Please send any patches to Greg Kroah-Hartman -- cgit v1.2.3 From e02554e9a4338c58e75fdfb0ef908a5adc86cba5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 14 Nov 2017 08:37:14 -0800 Subject: ipx: move Novell IPX protocol support into staging The Netware IPX protocol is very old and no one should still be using it. It is time to move it into staging for a while and eventually decommision it. Signed-off-by: Stephen Hemminger Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 3 +- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/ipx/Kconfig | 60 + drivers/staging/ipx/Makefile | 8 + drivers/staging/ipx/TODO | 4 + drivers/staging/ipx/af_ipx.c | 2084 ++++++++++++++++++++++++++++++++++ drivers/staging/ipx/ipx_proc.c | 341 ++++++ drivers/staging/ipx/ipx_route.c | 293 +++++ drivers/staging/ipx/pe2.c | 36 + drivers/staging/ipx/sysctl_net_ipx.c | 40 + net/Kconfig | 1 - net/Makefile | 1 - net/ipx/Kconfig | 60 - net/ipx/Makefile | 8 - net/ipx/af_ipx.c | 2084 ---------------------------------- net/ipx/ipx_proc.c | 341 ------ net/ipx/ipx_route.c | 293 ----- net/ipx/pe2.c | 36 - net/ipx/sysctl_net_ipx.c | 40 - 20 files changed, 2870 insertions(+), 2866 deletions(-) create mode 100644 drivers/staging/ipx/Kconfig create mode 100644 drivers/staging/ipx/Makefile create mode 100644 drivers/staging/ipx/TODO create mode 100644 drivers/staging/ipx/af_ipx.c create mode 100644 drivers/staging/ipx/ipx_proc.c create mode 100644 drivers/staging/ipx/ipx_route.c create mode 100644 drivers/staging/ipx/pe2.c create mode 100644 drivers/staging/ipx/sysctl_net_ipx.c delete mode 100644 net/ipx/Kconfig delete mode 100644 net/ipx/Makefile delete mode 100644 net/ipx/af_ipx.c delete mode 100644 net/ipx/ipx_proc.c delete mode 100644 net/ipx/ipx_route.c delete mode 100644 net/ipx/pe2.c delete mode 100644 net/ipx/sysctl_net_ipx.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index aa71ab52fd76..56cc7261c7e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7311,9 +7311,8 @@ F: drivers/tty/ipwireless/ IPX NETWORK LAYER L: netdev@vger.kernel.org S: Odd fixes -F: include/net/ipx.h F: include/uapi/linux/ipx.h -F: net/ipx/ +F: drivers/staging/ipx/ IRDA SUBSYSTEM M: Samuel Ortiz diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 554683912cff..3744640bed5a 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -26,6 +26,8 @@ if STAGING source "drivers/staging/irda/net/Kconfig" +source "drivers/staging/ipx/Kconfig" + source "drivers/staging/wlan-ng/Kconfig" source "drivers/staging/comedi/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 6e536020029a..f4c0506470ff 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -3,6 +3,7 @@ obj-y += media/ obj-y += typec/ +obj-$(CONFIG_IPX) += ipx/ obj-$(CONFIG_IRDA) += irda/net/ obj-$(CONFIG_IRDA) += irda/drivers/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ diff --git a/drivers/staging/ipx/Kconfig b/drivers/staging/ipx/Kconfig new file mode 100644 index 000000000000..e9ad0062fbb6 --- /dev/null +++ b/drivers/staging/ipx/Kconfig @@ -0,0 +1,60 @@ +# +# IPX configuration +# +config IPX + tristate "The IPX protocol" + select LLC + ---help--- + This is support for the Novell networking protocol, IPX, commonly + used for local networks of Windows machines. You need it if you + want to access Novell NetWare file or print servers using the Linux + Novell client ncpfs (available from + ) or from + within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, + available from ). In order + to do the former, you'll also have to say Y to "NCP file system + support", below. + + IPX is similar in scope to IP, while SPX, which runs on top of IPX, + is similar to TCP. + + To turn your Linux box into a fully featured NetWare file server and + IPX router, say Y here and fetch either lwared from + or + mars_nwe from . For more + information, read the IPX-HOWTO available from + . + + The IPX driver would enlarge your kernel by about 16 KB. To compile + this driver as a module, choose M here: the module will be called ipx. + Unless you want to integrate your Linux box with a local Novell + network, say N. + +config IPX_INTERN + bool "IPX: Full internal IPX network" + depends on IPX + ---help--- + Every IPX network has an address that identifies it. Sometimes it is + useful to give an IPX "network" address to your Linux box as well + (for example if your box is acting as a file server for different + IPX networks: it will then be accessible from everywhere using the + same address). The way this is done is to create a virtual internal + "network" inside your box and to assign an IPX address to this + network. Say Y here if you want to do this; read the IPX-HOWTO at + for details. + + The full internal IPX network enables you to allocate sockets on + different virtual nodes of the internal network. This is done by + evaluating the field sipx_node of the socket address given to the + bind call. So applications should always initialize the node field + to 0 when binding a socket on the primary network. In this case the + socket is assigned the default node that has been given to the + kernel when the internal network was created. By enabling the full + internal IPX network the cross-forwarding of packets targeted at + 'special' sockets to sockets listening on the primary network is + disabled. This might break existing applications, especially RIP/SAP + daemons. A RIP/SAP daemon that works well with the full internal net + can be found on . + + If you don't know what you are doing, say N. + diff --git a/drivers/staging/ipx/Makefile b/drivers/staging/ipx/Makefile new file mode 100644 index 000000000000..440fafa9fd07 --- /dev/null +++ b/drivers/staging/ipx/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Linux IPX layer. +# + +obj-$(CONFIG_IPX) += ipx.o + +ipx-y := af_ipx.o ipx_route.o ipx_proc.o pe2.o +ipx-$(CONFIG_SYSCTL) += sysctl_net_ipx.o diff --git a/drivers/staging/ipx/TODO b/drivers/staging/ipx/TODO new file mode 100644 index 000000000000..80db5d968264 --- /dev/null +++ b/drivers/staging/ipx/TODO @@ -0,0 +1,4 @@ +The ipx code will be removed soon from the kernel tree as it is old and +obsolete and broken. + +Don't worry about fixing up anything here, it's not needed. diff --git a/drivers/staging/ipx/af_ipx.c b/drivers/staging/ipx/af_ipx.c new file mode 100644 index 000000000000..d21a9d128d3e --- /dev/null +++ b/drivers/staging/ipx/af_ipx.c @@ -0,0 +1,2084 @@ +/* + * Implements an IPX socket layer. + * + * This code is derived from work by + * Ross Biro : Writing the original IP stack + * Fred Van Kempen : Tidying up the TCP/IP + * + * Many thanks go to Keith Baker, Institute For Industrial Information + * Technology Ltd, Swansea University for allowing me to work on this + * in my own time even though it was in some ways related to commercial + * work I am currently employed to do there. + * + * All the material in this file is subject to the Gnu license version 2. + * Neither Alan Cox nor the Swansea University Computer Society admit + * liability nor provide warranty for any of this software. This material + * is provided as is and at no charge. + * + * Portions Copyright (c) 2000-2003 Conectiva, Inc. + * Neither Arnaldo Carvalho de Melo nor Conectiva, Inc. admit liability nor + * provide warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * Portions Copyright (c) 1995 Caldera, Inc. + * Neither Greg Page nor Caldera, Inc. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * See net/ipx/ChangeLog. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Configuration Variables */ +static unsigned char ipxcfg_max_hops = 16; +static char ipxcfg_auto_select_primary; +static char ipxcfg_auto_create_interfaces; +int sysctl_ipx_pprop_broadcasting = 1; + +/* Global Variables */ +static struct datalink_proto *p8022_datalink; +static struct datalink_proto *pEII_datalink; +static struct datalink_proto *p8023_datalink; +static struct datalink_proto *pSNAP_datalink; + +static const struct proto_ops ipx_dgram_ops; + +LIST_HEAD(ipx_interfaces); +DEFINE_SPINLOCK(ipx_interfaces_lock); + +struct ipx_interface *ipx_primary_net; +struct ipx_interface *ipx_internal_net; + +struct ipx_interface *ipx_interfaces_head(void) +{ + struct ipx_interface *rc = NULL; + + if (!list_empty(&ipx_interfaces)) + rc = list_entry(ipx_interfaces.next, + struct ipx_interface, node); + return rc; +} + +static void ipxcfg_set_auto_select(char val) +{ + ipxcfg_auto_select_primary = val; + if (val && !ipx_primary_net) + ipx_primary_net = ipx_interfaces_head(); +} + +static int ipxcfg_get_config_data(struct ipx_config_data __user *arg) +{ + struct ipx_config_data vals; + + vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces; + vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary; + + return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0; +} + +/* + * Note: Sockets may not be removed _during_ an interrupt or inet_bh + * handler using this technique. They can be added although we do not + * use this facility. + */ + +static void ipx_remove_socket(struct sock *sk) +{ + /* Determine interface with which socket is associated */ + struct ipx_interface *intrfc = ipx_sk(sk)->intrfc; + + if (!intrfc) + goto out; + + ipxitf_hold(intrfc); + spin_lock_bh(&intrfc->if_sklist_lock); + sk_del_node_init(sk); + spin_unlock_bh(&intrfc->if_sklist_lock); + ipxitf_put(intrfc); +out: + return; +} + +static void ipx_destroy_socket(struct sock *sk) +{ + ipx_remove_socket(sk); + skb_queue_purge(&sk->sk_receive_queue); + sk_refcnt_debug_dec(sk); +} + +/* + * The following code is used to support IPX Interfaces (IPXITF). An + * IPX interface is defined by a physical device and a frame type. + */ + +/* ipxitf_clear_primary_net has to be called with ipx_interfaces_lock held */ + +static void ipxitf_clear_primary_net(void) +{ + ipx_primary_net = NULL; + if (ipxcfg_auto_select_primary) + ipx_primary_net = ipx_interfaces_head(); +} + +static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev, + __be16 datalink) +{ + struct ipx_interface *i; + + list_for_each_entry(i, &ipx_interfaces, node) + if (i->if_dev == dev && i->if_dlink_type == datalink) + goto out; + i = NULL; +out: + return i; +} + +static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev, + __be16 datalink) +{ + struct ipx_interface *i; + + spin_lock_bh(&ipx_interfaces_lock); + i = __ipxitf_find_using_phys(dev, datalink); + if (i) + ipxitf_hold(i); + spin_unlock_bh(&ipx_interfaces_lock); + return i; +} + +struct ipx_interface *ipxitf_find_using_net(__be32 net) +{ + struct ipx_interface *i; + + spin_lock_bh(&ipx_interfaces_lock); + if (net) { + list_for_each_entry(i, &ipx_interfaces, node) + if (i->if_netnum == net) + goto hold; + i = NULL; + goto unlock; + } + + i = ipx_primary_net; + if (i) +hold: + ipxitf_hold(i); +unlock: + spin_unlock_bh(&ipx_interfaces_lock); + return i; +} + +/* Sockets are bound to a particular IPX interface. */ +static void ipxitf_insert_socket(struct ipx_interface *intrfc, struct sock *sk) +{ + ipxitf_hold(intrfc); + spin_lock_bh(&intrfc->if_sklist_lock); + ipx_sk(sk)->intrfc = intrfc; + sk_add_node(sk, &intrfc->if_sklist); + spin_unlock_bh(&intrfc->if_sklist_lock); + ipxitf_put(intrfc); +} + +/* caller must hold intrfc->if_sklist_lock */ +static struct sock *__ipxitf_find_socket(struct ipx_interface *intrfc, + __be16 port) +{ + struct sock *s; + + sk_for_each(s, &intrfc->if_sklist) + if (ipx_sk(s)->port == port) + goto found; + s = NULL; +found: + return s; +} + +/* caller must hold a reference to intrfc */ +static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc, + __be16 port) +{ + struct sock *s; + + spin_lock_bh(&intrfc->if_sklist_lock); + s = __ipxitf_find_socket(intrfc, port); + if (s) + sock_hold(s); + spin_unlock_bh(&intrfc->if_sklist_lock); + + return s; +} + +#ifdef CONFIG_IPX_INTERN +static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc, + unsigned char *ipx_node, + __be16 port) +{ + struct sock *s; + + ipxitf_hold(intrfc); + spin_lock_bh(&intrfc->if_sklist_lock); + + sk_for_each(s, &intrfc->if_sklist) { + struct ipx_sock *ipxs = ipx_sk(s); + + if (ipxs->port == port && + !memcmp(ipx_node, ipxs->node, IPX_NODE_LEN)) + goto found; + } + s = NULL; +found: + spin_unlock_bh(&intrfc->if_sklist_lock); + ipxitf_put(intrfc); + return s; +} +#endif + +static void __ipxitf_down(struct ipx_interface *intrfc) +{ + struct sock *s; + struct hlist_node *t; + + /* Delete all routes associated with this interface */ + ipxrtr_del_routes(intrfc); + + spin_lock_bh(&intrfc->if_sklist_lock); + /* error sockets */ + sk_for_each_safe(s, t, &intrfc->if_sklist) { + struct ipx_sock *ipxs = ipx_sk(s); + + s->sk_err = ENOLINK; + s->sk_error_report(s); + ipxs->intrfc = NULL; + ipxs->port = 0; + sock_set_flag(s, SOCK_ZAPPED); /* Indicates it is no longer bound */ + sk_del_node_init(s); + } + INIT_HLIST_HEAD(&intrfc->if_sklist); + spin_unlock_bh(&intrfc->if_sklist_lock); + + /* remove this interface from list */ + list_del(&intrfc->node); + + /* remove this interface from *special* networks */ + if (intrfc == ipx_primary_net) + ipxitf_clear_primary_net(); + if (intrfc == ipx_internal_net) + ipx_internal_net = NULL; + + if (intrfc->if_dev) + dev_put(intrfc->if_dev); + kfree(intrfc); +} + +void ipxitf_down(struct ipx_interface *intrfc) +{ + spin_lock_bh(&ipx_interfaces_lock); + __ipxitf_down(intrfc); + spin_unlock_bh(&ipx_interfaces_lock); +} + +static void __ipxitf_put(struct ipx_interface *intrfc) +{ + if (refcount_dec_and_test(&intrfc->refcnt)) + __ipxitf_down(intrfc); +} + +static int ipxitf_device_event(struct notifier_block *notifier, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct ipx_interface *i, *tmp; + + if (!net_eq(dev_net(dev), &init_net)) + return NOTIFY_DONE; + + if (event != NETDEV_DOWN && event != NETDEV_UP) + goto out; + + spin_lock_bh(&ipx_interfaces_lock); + list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) + if (i->if_dev == dev) { + if (event == NETDEV_UP) + ipxitf_hold(i); + else + __ipxitf_put(i); + } + spin_unlock_bh(&ipx_interfaces_lock); +out: + return NOTIFY_DONE; +} + + +static __exit void ipxitf_cleanup(void) +{ + struct ipx_interface *i, *tmp; + + spin_lock_bh(&ipx_interfaces_lock); + list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) + __ipxitf_put(i); + spin_unlock_bh(&ipx_interfaces_lock); +} + +static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb) +{ + if (sock_queue_rcv_skb(sock, skb) < 0) + kfree_skb(skb); +} + +/* + * On input skb->sk is NULL. Nobody is charged for the memory. + */ + +/* caller must hold a reference to intrfc */ + +#ifdef CONFIG_IPX_INTERN +static int ipxitf_demux_socket(struct ipx_interface *intrfc, + struct sk_buff *skb, int copy) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + int is_broadcast = !memcmp(ipx->ipx_dest.node, ipx_broadcast_node, + IPX_NODE_LEN); + struct sock *s; + int rc; + + spin_lock_bh(&intrfc->if_sklist_lock); + + sk_for_each(s, &intrfc->if_sklist) { + struct ipx_sock *ipxs = ipx_sk(s); + + if (ipxs->port == ipx->ipx_dest.sock && + (is_broadcast || !memcmp(ipx->ipx_dest.node, + ipxs->node, IPX_NODE_LEN))) { + /* We found a socket to which to send */ + struct sk_buff *skb1; + + if (copy) { + skb1 = skb_clone(skb, GFP_ATOMIC); + rc = -ENOMEM; + if (!skb1) + goto out; + } else { + skb1 = skb; + copy = 1; /* skb may only be used once */ + } + ipxitf_def_skb_handler(s, skb1); + + /* On an external interface, one socket can listen */ + if (intrfc != ipx_internal_net) + break; + } + } + + /* skb was solely for us, and we did not make a copy, so free it. */ + if (!copy) + kfree_skb(skb); + + rc = 0; +out: + spin_unlock_bh(&intrfc->if_sklist_lock); + return rc; +} +#else +static struct sock *ncp_connection_hack(struct ipx_interface *intrfc, + struct ipxhdr *ipx) +{ + /* The packet's target is a NCP connection handler. We want to hand it + * to the correct socket directly within the kernel, so that the + * mars_nwe packet distribution process does not have to do it. Here we + * only care about NCP and BURST packets. + * + * You might call this a hack, but believe me, you do not want a + * complete NCP layer in the kernel, and this is VERY fast as well. */ + struct sock *sk = NULL; + int connection = 0; + u8 *ncphdr = (u8 *)(ipx + 1); + + if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */ + connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3); + else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */ + connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8); + + if (connection) { + /* Now we have to look for a special NCP connection handling + * socket. Only these sockets have ipx_ncp_conn != 0, set by + * SIOCIPXNCPCONN. */ + spin_lock_bh(&intrfc->if_sklist_lock); + sk_for_each(sk, &intrfc->if_sklist) + if (ipx_sk(sk)->ipx_ncp_conn == connection) { + sock_hold(sk); + goto found; + } + sk = NULL; + found: + spin_unlock_bh(&intrfc->if_sklist_lock); + } + return sk; +} + +static int ipxitf_demux_socket(struct ipx_interface *intrfc, + struct sk_buff *skb, int copy) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + struct sock *sock1 = NULL, *sock2 = NULL; + struct sk_buff *skb1 = NULL, *skb2 = NULL; + int rc; + + if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) + sock1 = ncp_connection_hack(intrfc, ipx); + if (!sock1) + /* No special socket found, forward the packet the normal way */ + sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock); + + /* + * We need to check if there is a primary net and if + * this is addressed to one of the *SPECIAL* sockets because + * these need to be propagated to the primary net. + * The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and + * 0x456(Diagnostic). + */ + + if (ipx_primary_net && intrfc != ipx_primary_net) { + const int dsock = ntohs(ipx->ipx_dest.sock); + + if (dsock == 0x452 || dsock == 0x453 || dsock == 0x456) + /* The appropriate thing to do here is to dup the + * packet and route to the primary net interface via + * ipxitf_send; however, we'll cheat and just demux it + * here. */ + sock2 = ipxitf_find_socket(ipx_primary_net, + ipx->ipx_dest.sock); + } + + /* + * If there is nothing to do return. The kfree will cancel any charging. + */ + rc = 0; + if (!sock1 && !sock2) { + if (!copy) + kfree_skb(skb); + goto out; + } + + /* + * This next segment of code is a little awkward, but it sets it up + * so that the appropriate number of copies of the SKB are made and + * that skb1 and skb2 point to it (them) so that it (they) can be + * demuxed to sock1 and/or sock2. If we are unable to make enough + * copies, we do as much as is possible. + */ + + if (copy) + skb1 = skb_clone(skb, GFP_ATOMIC); + else + skb1 = skb; + + rc = -ENOMEM; + if (!skb1) + goto out_put; + + /* Do we need 2 SKBs? */ + if (sock1 && sock2) + skb2 = skb_clone(skb1, GFP_ATOMIC); + else + skb2 = skb1; + + if (sock1) + ipxitf_def_skb_handler(sock1, skb1); + + if (!skb2) + goto out_put; + + if (sock2) + ipxitf_def_skb_handler(sock2, skb2); + + rc = 0; +out_put: + if (sock1) + sock_put(sock1); + if (sock2) + sock_put(sock2); +out: + return rc; +} +#endif /* CONFIG_IPX_INTERN */ + +static struct sk_buff *ipxitf_adjust_skbuff(struct ipx_interface *intrfc, + struct sk_buff *skb) +{ + struct sk_buff *skb2; + int in_offset = (unsigned char *)ipx_hdr(skb) - skb->head; + int out_offset = intrfc->if_ipx_offset; + int len; + + /* Hopefully, most cases */ + if (in_offset >= out_offset) + return skb; + + /* Need new SKB */ + len = skb->len + out_offset; + skb2 = alloc_skb(len, GFP_ATOMIC); + if (skb2) { + skb_reserve(skb2, out_offset); + skb_reset_network_header(skb2); + skb_reset_transport_header(skb2); + skb_put(skb2, skb->len); + memcpy(ipx_hdr(skb2), ipx_hdr(skb), skb->len); + memcpy(skb2->cb, skb->cb, sizeof(skb->cb)); + } + kfree_skb(skb); + return skb2; +} + +/* caller must hold a reference to intrfc and the skb has to be unshared */ +int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + struct net_device *dev = intrfc->if_dev; + struct datalink_proto *dl = intrfc->if_dlink; + char dest_node[IPX_NODE_LEN]; + int send_to_wire = 1; + int addr_len; + + ipx->ipx_tctrl = IPX_SKB_CB(skb)->ipx_tctrl; + ipx->ipx_dest.net = IPX_SKB_CB(skb)->ipx_dest_net; + ipx->ipx_source.net = IPX_SKB_CB(skb)->ipx_source_net; + + /* see if we need to include the netnum in the route list */ + if (IPX_SKB_CB(skb)->last_hop.index >= 0) { + __be32 *last_hop = (__be32 *)(((u8 *) skb->data) + + sizeof(struct ipxhdr) + + IPX_SKB_CB(skb)->last_hop.index * + sizeof(__be32)); + *last_hop = IPX_SKB_CB(skb)->last_hop.netnum; + IPX_SKB_CB(skb)->last_hop.index = -1; + } + + /* + * We need to know how many skbuffs it will take to send out this + * packet to avoid unnecessary copies. + */ + + if (!dl || !dev || dev->flags & IFF_LOOPBACK) + send_to_wire = 0; /* No non looped */ + + /* + * See if this should be demuxed to sockets on this interface + * + * We want to ensure the original was eaten or that we only use + * up clones. + */ + + if (ipx->ipx_dest.net == intrfc->if_netnum) { + /* + * To our own node, loop and free the original. + * The internal net will receive on all node address. + */ + if (intrfc == ipx_internal_net || + !memcmp(intrfc->if_node, node, IPX_NODE_LEN)) { + /* Don't charge sender */ + skb_orphan(skb); + + /* Will charge receiver */ + return ipxitf_demux_socket(intrfc, skb, 0); + } + + /* Broadcast, loop and possibly keep to send on. */ + if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) { + if (!send_to_wire) + skb_orphan(skb); + ipxitf_demux_socket(intrfc, skb, send_to_wire); + if (!send_to_wire) + goto out; + } + } + + /* + * If the originating net is not equal to our net; this is routed + * We are still charging the sender. Which is right - the driver + * free will handle this fairly. + */ + if (ipx->ipx_source.net != intrfc->if_netnum) { + /* + * Unshare the buffer before modifying the count in + * case it's a flood or tcpdump + */ + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) + goto out; + if (++ipx->ipx_tctrl > ipxcfg_max_hops) + send_to_wire = 0; + } + + if (!send_to_wire) { + kfree_skb(skb); + goto out; + } + + /* Determine the appropriate hardware address */ + addr_len = dev->addr_len; + if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) + memcpy(dest_node, dev->broadcast, addr_len); + else + memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len); + + /* Make any compensation for differing physical/data link size */ + skb = ipxitf_adjust_skbuff(intrfc, skb); + if (!skb) + goto out; + + /* set up data link and physical headers */ + skb->dev = dev; + skb->protocol = htons(ETH_P_IPX); + + /* Send it out */ + dl->request(dl, skb, dest_node); +out: + return 0; +} + +static int ipxitf_add_local_route(struct ipx_interface *intrfc) +{ + return ipxrtr_add_route(intrfc->if_netnum, intrfc, NULL); +} + +static void ipxitf_discover_netnum(struct ipx_interface *intrfc, + struct sk_buff *skb); +static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb); + +static int ipxitf_rcv(struct ipx_interface *intrfc, struct sk_buff *skb) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + int rc = 0; + + ipxitf_hold(intrfc); + + /* See if we should update our network number */ + if (!intrfc->if_netnum) /* net number of intrfc not known yet */ + ipxitf_discover_netnum(intrfc, skb); + + IPX_SKB_CB(skb)->last_hop.index = -1; + if (ipx->ipx_type == IPX_TYPE_PPROP) { + rc = ipxitf_pprop(intrfc, skb); + if (rc) + goto out_free_skb; + } + + /* local processing follows */ + if (!IPX_SKB_CB(skb)->ipx_dest_net) + IPX_SKB_CB(skb)->ipx_dest_net = intrfc->if_netnum; + if (!IPX_SKB_CB(skb)->ipx_source_net) + IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum; + + /* it doesn't make sense to route a pprop packet, there's no meaning + * in the ipx_dest_net for such packets */ + if (ipx->ipx_type != IPX_TYPE_PPROP && + intrfc->if_netnum != IPX_SKB_CB(skb)->ipx_dest_net) { + /* We only route point-to-point packets. */ + if (skb->pkt_type == PACKET_HOST) { + skb = skb_unshare(skb, GFP_ATOMIC); + if (skb) + rc = ipxrtr_route_skb(skb); + goto out_intrfc; + } + + goto out_free_skb; + } + + /* see if we should keep it */ + if (!memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) || + !memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN)) { + rc = ipxitf_demux_socket(intrfc, skb, 0); + goto out_intrfc; + } + + /* we couldn't pawn it off so unload it */ +out_free_skb: + kfree_skb(skb); +out_intrfc: + ipxitf_put(intrfc); + return rc; +} + +static void ipxitf_discover_netnum(struct ipx_interface *intrfc, + struct sk_buff *skb) +{ + const struct ipx_cb *cb = IPX_SKB_CB(skb); + + /* see if this is an intra packet: source_net == dest_net */ + if (cb->ipx_source_net == cb->ipx_dest_net && cb->ipx_source_net) { + struct ipx_interface *i = + ipxitf_find_using_net(cb->ipx_source_net); + /* NB: NetWare servers lie about their hop count so we + * dropped the test based on it. This is the best way + * to determine this is a 0 hop count packet. */ + if (!i) { + intrfc->if_netnum = cb->ipx_source_net; + ipxitf_add_local_route(intrfc); + } else { + printk(KERN_WARNING "IPX: Network number collision " + "%lx\n %s %s and %s %s\n", + (unsigned long) ntohl(cb->ipx_source_net), + ipx_device_name(i), + ipx_frame_name(i->if_dlink_type), + ipx_device_name(intrfc), + ipx_frame_name(intrfc->if_dlink_type)); + ipxitf_put(i); + } + } +} + +/** + * ipxitf_pprop - Process packet propagation IPX packet type 0x14, used for + * NetBIOS broadcasts + * @intrfc: IPX interface receiving this packet + * @skb: Received packet + * + * Checks if packet is valid: if its more than %IPX_MAX_PPROP_HOPS hops or if it + * is smaller than a IPX header + the room for %IPX_MAX_PPROP_HOPS hops we drop + * it, not even processing it locally, if it has exact %IPX_MAX_PPROP_HOPS we + * don't broadcast it, but process it locally. See chapter 5 of Novell's "IPX + * RIP and SAP Router Specification", Part Number 107-000029-001. + * + * If it is valid, check if we have pprop broadcasting enabled by the user, + * if not, just return zero for local processing. + * + * If it is enabled check the packet and don't broadcast it if we have already + * seen this packet. + * + * Broadcast: send it to the interfaces that aren't on the packet visited nets + * array, just after the IPX header. + * + * Returns -EINVAL for invalid packets, so that the calling function drops + * the packet without local processing. 0 if packet is to be locally processed. + */ +static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + int i, rc = -EINVAL; + struct ipx_interface *ifcs; + char *c; + __be32 *l; + + /* Illegal packet - too many hops or too short */ + /* We decide to throw it away: no broadcasting, no local processing. + * NetBIOS unaware implementations route them as normal packets - + * tctrl <= 15, any data payload... */ + if (IPX_SKB_CB(skb)->ipx_tctrl > IPX_MAX_PPROP_HOPS || + ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr) + + IPX_MAX_PPROP_HOPS * sizeof(u32)) + goto out; + /* are we broadcasting this damn thing? */ + rc = 0; + if (!sysctl_ipx_pprop_broadcasting) + goto out; + /* We do broadcast packet on the IPX_MAX_PPROP_HOPS hop, but we + * process it locally. All previous hops broadcasted it, and process it + * locally. */ + if (IPX_SKB_CB(skb)->ipx_tctrl == IPX_MAX_PPROP_HOPS) + goto out; + + c = ((u8 *) ipx) + sizeof(struct ipxhdr); + l = (__be32 *) c; + + /* Don't broadcast packet if already seen this net */ + for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++) + if (*l++ == intrfc->if_netnum) + goto out; + + /* < IPX_MAX_PPROP_HOPS hops && input interface not in list. Save the + * position where we will insert recvd netnum into list, later on, + * in ipxitf_send */ + IPX_SKB_CB(skb)->last_hop.index = i; + IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum; + /* xmit on all other interfaces... */ + spin_lock_bh(&ipx_interfaces_lock); + list_for_each_entry(ifcs, &ipx_interfaces, node) { + /* Except unconfigured interfaces */ + if (!ifcs->if_netnum) + continue; + + /* That aren't in the list */ + if (ifcs == intrfc) + continue; + l = (__be32 *) c; + /* don't consider the last entry in the packet list, + * it is our netnum, and it is not there yet */ + for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++) + if (ifcs->if_netnum == *l++) + break; + if (i == IPX_SKB_CB(skb)->ipx_tctrl) { + struct sk_buff *s = skb_copy(skb, GFP_ATOMIC); + + if (s) { + IPX_SKB_CB(s)->ipx_dest_net = ifcs->if_netnum; + ipxrtr_route_skb(s); + } + } + } + spin_unlock_bh(&ipx_interfaces_lock); +out: + return rc; +} + +static void ipxitf_insert(struct ipx_interface *intrfc) +{ + spin_lock_bh(&ipx_interfaces_lock); + list_add_tail(&intrfc->node, &ipx_interfaces); + spin_unlock_bh(&ipx_interfaces_lock); + + if (ipxcfg_auto_select_primary && !ipx_primary_net) + ipx_primary_net = intrfc; +} + +static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum, + __be16 dlink_type, + struct datalink_proto *dlink, + unsigned char internal, + int ipx_offset) +{ + struct ipx_interface *intrfc = kmalloc(sizeof(*intrfc), GFP_ATOMIC); + + if (intrfc) { + intrfc->if_dev = dev; + intrfc->if_netnum = netnum; + intrfc->if_dlink_type = dlink_type; + intrfc->if_dlink = dlink; + intrfc->if_internal = internal; + intrfc->if_ipx_offset = ipx_offset; + intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET; + INIT_HLIST_HEAD(&intrfc->if_sklist); + refcount_set(&intrfc->refcnt, 1); + spin_lock_init(&intrfc->if_sklist_lock); + } + + return intrfc; +} + +static int ipxitf_create_internal(struct ipx_interface_definition *idef) +{ + struct ipx_interface *intrfc; + int rc = -EEXIST; + + /* Only one primary network allowed */ + if (ipx_primary_net) + goto out; + + /* Must have a valid network number */ + rc = -EADDRNOTAVAIL; + if (!idef->ipx_network) + goto out; + intrfc = ipxitf_find_using_net(idef->ipx_network); + rc = -EADDRINUSE; + if (intrfc) { + ipxitf_put(intrfc); + goto out; + } + intrfc = ipxitf_alloc(NULL, idef->ipx_network, 0, NULL, 1, 0); + rc = -EAGAIN; + if (!intrfc) + goto out; + memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN); + ipx_internal_net = ipx_primary_net = intrfc; + ipxitf_hold(intrfc); + ipxitf_insert(intrfc); + + rc = ipxitf_add_local_route(intrfc); + ipxitf_put(intrfc); +out: + return rc; +} + +static __be16 ipx_map_frame_type(unsigned char type) +{ + __be16 rc = 0; + + switch (type) { + case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX); break; + case IPX_FRAME_8022: rc = htons(ETH_P_802_2); break; + case IPX_FRAME_SNAP: rc = htons(ETH_P_SNAP); break; + case IPX_FRAME_8023: rc = htons(ETH_P_802_3); break; + } + + return rc; +} + +static int ipxitf_create(struct ipx_interface_definition *idef) +{ + struct net_device *dev; + __be16 dlink_type = 0; + struct datalink_proto *datalink = NULL; + struct ipx_interface *intrfc; + int rc; + + if (idef->ipx_special == IPX_INTERNAL) { + rc = ipxitf_create_internal(idef); + goto out; + } + + rc = -EEXIST; + if (idef->ipx_special == IPX_PRIMARY && ipx_primary_net) + goto out; + + intrfc = ipxitf_find_using_net(idef->ipx_network); + rc = -EADDRINUSE; + if (idef->ipx_network && intrfc) { + ipxitf_put(intrfc); + goto out; + } + + if (intrfc) + ipxitf_put(intrfc); + + dev = dev_get_by_name(&init_net, idef->ipx_device); + rc = -ENODEV; + if (!dev) + goto out; + + switch (idef->ipx_dlink_type) { + case IPX_FRAME_8022: + dlink_type = htons(ETH_P_802_2); + datalink = p8022_datalink; + break; + case IPX_FRAME_ETHERII: + if (dev->type != ARPHRD_IEEE802) { + dlink_type = htons(ETH_P_IPX); + datalink = pEII_datalink; + break; + } + /* fall through */ + case IPX_FRAME_SNAP: + dlink_type = htons(ETH_P_SNAP); + datalink = pSNAP_datalink; + break; + case IPX_FRAME_8023: + dlink_type = htons(ETH_P_802_3); + datalink = p8023_datalink; + break; + case IPX_FRAME_NONE: + default: + rc = -EPROTONOSUPPORT; + goto out_dev; + } + + rc = -ENETDOWN; + if (!(dev->flags & IFF_UP)) + goto out_dev; + + /* Check addresses are suitable */ + rc = -EINVAL; + if (dev->addr_len > IPX_NODE_LEN) + goto out_dev; + + intrfc = ipxitf_find_using_phys(dev, dlink_type); + if (!intrfc) { + /* Ok now create */ + intrfc = ipxitf_alloc(dev, idef->ipx_network, dlink_type, + datalink, 0, dev->hard_header_len + + datalink->header_length); + rc = -EAGAIN; + if (!intrfc) + goto out_dev; + /* Setup primary if necessary */ + if (idef->ipx_special == IPX_PRIMARY) + ipx_primary_net = intrfc; + if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000", + IPX_NODE_LEN)) { + memset(intrfc->if_node, 0, IPX_NODE_LEN); + memcpy(intrfc->if_node + IPX_NODE_LEN - dev->addr_len, + dev->dev_addr, dev->addr_len); + } else + memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN); + ipxitf_hold(intrfc); + ipxitf_insert(intrfc); + } + + + /* If the network number is known, add a route */ + rc = 0; + if (!intrfc->if_netnum) + goto out_intrfc; + + rc = ipxitf_add_local_route(intrfc); +out_intrfc: + ipxitf_put(intrfc); + goto out; +out_dev: + dev_put(dev); +out: + return rc; +} + +static int ipxitf_delete(struct ipx_interface_definition *idef) +{ + struct net_device *dev = NULL; + __be16 dlink_type = 0; + struct ipx_interface *intrfc; + int rc = 0; + + spin_lock_bh(&ipx_interfaces_lock); + if (idef->ipx_special == IPX_INTERNAL) { + if (ipx_internal_net) { + __ipxitf_put(ipx_internal_net); + goto out; + } + rc = -ENOENT; + goto out; + } + + dlink_type = ipx_map_frame_type(idef->ipx_dlink_type); + rc = -EPROTONOSUPPORT; + if (!dlink_type) + goto out; + + dev = __dev_get_by_name(&init_net, idef->ipx_device); + rc = -ENODEV; + if (!dev) + goto out; + + intrfc = __ipxitf_find_using_phys(dev, dlink_type); + rc = -EINVAL; + if (!intrfc) + goto out; + __ipxitf_put(intrfc); + + rc = 0; +out: + spin_unlock_bh(&ipx_interfaces_lock); + return rc; +} + +static struct ipx_interface *ipxitf_auto_create(struct net_device *dev, + __be16 dlink_type) +{ + struct ipx_interface *intrfc = NULL; + struct datalink_proto *datalink; + + if (!dev) + goto out; + + /* Check addresses are suitable */ + if (dev->addr_len > IPX_NODE_LEN) + goto out; + + switch (ntohs(dlink_type)) { + case ETH_P_IPX: datalink = pEII_datalink; break; + case ETH_P_802_2: datalink = p8022_datalink; break; + case ETH_P_SNAP: datalink = pSNAP_datalink; break; + case ETH_P_802_3: datalink = p8023_datalink; break; + default: goto out; + } + + intrfc = ipxitf_alloc(dev, 0, dlink_type, datalink, 0, + dev->hard_header_len + datalink->header_length); + + if (intrfc) { + memset(intrfc->if_node, 0, IPX_NODE_LEN); + memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]), + dev->dev_addr, dev->addr_len); + spin_lock_init(&intrfc->if_sklist_lock); + refcount_set(&intrfc->refcnt, 1); + ipxitf_insert(intrfc); + dev_hold(dev); + } + +out: + return intrfc; +} + +static int ipxitf_ioctl(unsigned int cmd, void __user *arg) +{ + int rc = -EINVAL; + struct ifreq ifr; + int val; + + switch (cmd) { + case SIOCSIFADDR: { + struct sockaddr_ipx *sipx; + struct ipx_interface_definition f; + + rc = -EFAULT; + if (copy_from_user(&ifr, arg, sizeof(ifr))) + break; + sipx = (struct sockaddr_ipx *)&ifr.ifr_addr; + rc = -EINVAL; + if (sipx->sipx_family != AF_IPX) + break; + f.ipx_network = sipx->sipx_network; + memcpy(f.ipx_device, ifr.ifr_name, + sizeof(f.ipx_device)); + memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN); + f.ipx_dlink_type = sipx->sipx_type; + f.ipx_special = sipx->sipx_special; + + if (sipx->sipx_action == IPX_DLTITF) + rc = ipxitf_delete(&f); + else + rc = ipxitf_create(&f); + break; + } + case SIOCGIFADDR: { + struct sockaddr_ipx *sipx; + struct ipx_interface *ipxif; + struct net_device *dev; + + rc = -EFAULT; + if (copy_from_user(&ifr, arg, sizeof(ifr))) + break; + sipx = (struct sockaddr_ipx *)&ifr.ifr_addr; + dev = __dev_get_by_name(&init_net, ifr.ifr_name); + rc = -ENODEV; + if (!dev) + break; + ipxif = ipxitf_find_using_phys(dev, + ipx_map_frame_type(sipx->sipx_type)); + rc = -EADDRNOTAVAIL; + if (!ipxif) + break; + + sipx->sipx_family = AF_IPX; + sipx->sipx_network = ipxif->if_netnum; + memcpy(sipx->sipx_node, ipxif->if_node, + sizeof(sipx->sipx_node)); + rc = 0; + if (copy_to_user(arg, &ifr, sizeof(ifr))) + rc = -EFAULT; + ipxitf_put(ipxif); + break; + } + case SIOCAIPXITFCRT: + rc = -EFAULT; + if (get_user(val, (unsigned char __user *) arg)) + break; + rc = 0; + ipxcfg_auto_create_interfaces = val; + break; + case SIOCAIPXPRISLT: + rc = -EFAULT; + if (get_user(val, (unsigned char __user *) arg)) + break; + rc = 0; + ipxcfg_set_auto_select(val); + break; + } + + return rc; +} + +/* + * Checksum routine for IPX + */ + +/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */ +/* This functions should *not* mess with packet contents */ + +__be16 ipx_cksum(struct ipxhdr *packet, int length) +{ + /* + * NOTE: sum is a net byte order quantity, which optimizes the + * loop. This only works on big and little endian machines. (I + * don't know of a machine that isn't.) + */ + /* handle the first 3 words separately; checksum should be skipped + * and ipx_tctrl masked out */ + __u16 *p = (__u16 *)packet; + __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff)); + __u32 i = (length >> 1) - 3; /* Number of remaining complete words */ + + /* Loop through them */ + p += 3; + while (i--) + sum += *p++; + + /* Add on the last part word if it exists */ + if (packet->ipx_pktsize & htons(1)) + sum += (__force u16)htons(0xff00) & *p; + + /* Do final fixup */ + sum = (sum & 0xffff) + (sum >> 16); + + /* It's a pity there's no concept of carry in C */ + if (sum >= 0x10000) + sum++; + + /* + * Leave 0 alone; we don't want 0xffff here. Note that we can't get + * here with 0x10000, so this check is the same as ((__u16)sum) + */ + if (sum) + sum = ~sum; + + return (__force __be16)sum; +} + +const char *ipx_frame_name(__be16 frame) +{ + char* rc = "None"; + + switch (ntohs(frame)) { + case ETH_P_IPX: rc = "EtherII"; break; + case ETH_P_802_2: rc = "802.2"; break; + case ETH_P_SNAP: rc = "SNAP"; break; + case ETH_P_802_3: rc = "802.3"; break; + } + + return rc; +} + +const char *ipx_device_name(struct ipx_interface *intrfc) +{ + return intrfc->if_internal ? "Internal" : + intrfc->if_dev ? intrfc->if_dev->name : "Unknown"; +} + +/* Handling for system calls applied via the various interfaces to an IPX + * socket object. */ + +static int ipx_setsockopt(struct socket *sock, int level, int optname, + char __user *optval, unsigned int optlen) +{ + struct sock *sk = sock->sk; + int opt; + int rc = -EINVAL; + + lock_sock(sk); + if (optlen != sizeof(int)) + goto out; + + rc = -EFAULT; + if (get_user(opt, (unsigned int __user *)optval)) + goto out; + + rc = -ENOPROTOOPT; + if (!(level == SOL_IPX && optname == IPX_TYPE)) + goto out; + + ipx_sk(sk)->type = opt; + rc = 0; +out: + release_sock(sk); + return rc; +} + +static int ipx_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) +{ + struct sock *sk = sock->sk; + int val = 0; + int len; + int rc = -ENOPROTOOPT; + + lock_sock(sk); + if (!(level == SOL_IPX && optname == IPX_TYPE)) + goto out; + + val = ipx_sk(sk)->type; + + rc = -EFAULT; + if (get_user(len, optlen)) + goto out; + + len = min_t(unsigned int, len, sizeof(int)); + rc = -EINVAL; + if(len < 0) + goto out; + + rc = -EFAULT; + if (put_user(len, optlen) || copy_to_user(optval, &val, len)) + goto out; + + rc = 0; +out: + release_sock(sk); + return rc; +} + +static struct proto ipx_proto = { + .name = "IPX", + .owner = THIS_MODULE, + .obj_size = sizeof(struct ipx_sock), +}; + +static int ipx_create(struct net *net, struct socket *sock, int protocol, + int kern) +{ + int rc = -ESOCKTNOSUPPORT; + struct sock *sk; + + if (!net_eq(net, &init_net)) + return -EAFNOSUPPORT; + + /* + * SPX support is not anymore in the kernel sources. If you want to + * ressurrect it, completing it and making it understand shared skbs, + * be fully multithreaded, etc, grab the sources in an early 2.5 kernel + * tree. + */ + if (sock->type != SOCK_DGRAM) + goto out; + + rc = -ENOMEM; + sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, kern); + if (!sk) + goto out; + + sk_refcnt_debug_inc(sk); + sock_init_data(sock, sk); + sk->sk_no_check_tx = 1; /* Checksum off by default */ + sock->ops = &ipx_dgram_ops; + rc = 0; +out: + return rc; +} + +static int ipx_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + + if (!sk) + goto out; + + lock_sock(sk); + sk->sk_shutdown = SHUTDOWN_MASK; + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_state_change(sk); + + sock_set_flag(sk, SOCK_DEAD); + sock->sk = NULL; + sk_refcnt_debug_release(sk); + ipx_destroy_socket(sk); + release_sock(sk); + sock_put(sk); +out: + return 0; +} + +/* caller must hold a reference to intrfc */ + +static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc) +{ + unsigned short socketNum = intrfc->if_sknum; + + spin_lock_bh(&intrfc->if_sklist_lock); + + if (socketNum < IPX_MIN_EPHEMERAL_SOCKET) + socketNum = IPX_MIN_EPHEMERAL_SOCKET; + + while (__ipxitf_find_socket(intrfc, htons(socketNum))) + if (socketNum > IPX_MAX_EPHEMERAL_SOCKET) + socketNum = IPX_MIN_EPHEMERAL_SOCKET; + else + socketNum++; + + spin_unlock_bh(&intrfc->if_sklist_lock); + intrfc->if_sknum = socketNum; + + return htons(socketNum); +} + +static int __ipx_bind(struct socket *sock, + struct sockaddr *uaddr, int addr_len) +{ + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + struct ipx_interface *intrfc; + struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr; + int rc = -EINVAL; + + if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_ipx)) + goto out; + + intrfc = ipxitf_find_using_net(addr->sipx_network); + rc = -EADDRNOTAVAIL; + if (!intrfc) + goto out; + + if (!addr->sipx_port) { + addr->sipx_port = ipx_first_free_socketnum(intrfc); + rc = -EINVAL; + if (!addr->sipx_port) + goto out_put; + } + + /* protect IPX system stuff like routing/sap */ + rc = -EACCES; + if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET && + !capable(CAP_NET_ADMIN)) + goto out_put; + + ipxs->port = addr->sipx_port; + +#ifdef CONFIG_IPX_INTERN + if (intrfc == ipx_internal_net) { + /* The source address is to be set explicitly if the + * socket is to be bound on the internal network. If a + * node number 0 was specified, the default is used. + */ + + rc = -EINVAL; + if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN)) + goto out_put; + if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN)) + memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN); + else + memcpy(ipxs->node, addr->sipx_node, IPX_NODE_LEN); + + rc = -EADDRINUSE; + if (ipxitf_find_internal_socket(intrfc, ipxs->node, + ipxs->port)) { + SOCK_DEBUG(sk, + "IPX: bind failed because port %X in use.\n", + ntohs(addr->sipx_port)); + goto out_put; + } + } else { + /* Source addresses are easy. It must be our + * network:node pair for an interface routed to IPX + * with the ipx routing ioctl() + */ + + memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN); + + rc = -EADDRINUSE; + if (ipxitf_find_socket(intrfc, addr->sipx_port)) { + SOCK_DEBUG(sk, + "IPX: bind failed because port %X in use.\n", + ntohs(addr->sipx_port)); + goto out_put; + } + } + +#else /* !def CONFIG_IPX_INTERN */ + + /* Source addresses are easy. It must be our network:node pair for + an interface routed to IPX with the ipx routing ioctl() */ + + rc = -EADDRINUSE; + if (ipxitf_find_socket(intrfc, addr->sipx_port)) { + SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", + ntohs((int)addr->sipx_port)); + goto out_put; + } + +#endif /* CONFIG_IPX_INTERN */ + + ipxitf_insert_socket(intrfc, sk); + sock_reset_flag(sk, SOCK_ZAPPED); + + rc = 0; +out_put: + ipxitf_put(intrfc); +out: + return rc; +} + +static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) +{ + struct sock *sk = sock->sk; + int rc; + + lock_sock(sk); + rc = __ipx_bind(sock, uaddr, addr_len); + release_sock(sk); + + return rc; +} + +static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) +{ + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + struct sockaddr_ipx *addr; + int rc = -EINVAL; + struct ipx_route *rt; + + sk->sk_state = TCP_CLOSE; + sock->state = SS_UNCONNECTED; + + lock_sock(sk); + if (addr_len != sizeof(*addr)) + goto out; + addr = (struct sockaddr_ipx *)uaddr; + + /* put the autobinding in */ + if (!ipxs->port) { + struct sockaddr_ipx uaddr; + + uaddr.sipx_port = 0; + uaddr.sipx_network = 0; + +#ifdef CONFIG_IPX_INTERN + rc = -ENETDOWN; + if (!ipxs->intrfc) + goto out; /* Someone zonked the iface */ + memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, + IPX_NODE_LEN); +#endif /* CONFIG_IPX_INTERN */ + + rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + sizeof(struct sockaddr_ipx)); + if (rc) + goto out; + } + + /* We can either connect to primary network or somewhere + * we can route to */ + rt = ipxrtr_lookup(addr->sipx_network); + rc = -ENETUNREACH; + if (!rt && !(!addr->sipx_network && ipx_primary_net)) + goto out; + + ipxs->dest_addr.net = addr->sipx_network; + ipxs->dest_addr.sock = addr->sipx_port; + memcpy(ipxs->dest_addr.node, addr->sipx_node, IPX_NODE_LEN); + ipxs->type = addr->sipx_type; + + if (sock->type == SOCK_DGRAM) { + sock->state = SS_CONNECTED; + sk->sk_state = TCP_ESTABLISHED; + } + + if (rt) + ipxrtr_put(rt); + rc = 0; +out: + release_sock(sk); + return rc; +} + + +static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) +{ + struct ipx_address *addr; + struct sockaddr_ipx sipx; + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + int rc; + + *uaddr_len = sizeof(struct sockaddr_ipx); + + lock_sock(sk); + if (peer) { + rc = -ENOTCONN; + if (sk->sk_state != TCP_ESTABLISHED) + goto out; + + addr = &ipxs->dest_addr; + sipx.sipx_network = addr->net; + sipx.sipx_port = addr->sock; + memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN); + } else { + if (ipxs->intrfc) { + sipx.sipx_network = ipxs->intrfc->if_netnum; +#ifdef CONFIG_IPX_INTERN + memcpy(sipx.sipx_node, ipxs->node, IPX_NODE_LEN); +#else + memcpy(sipx.sipx_node, ipxs->intrfc->if_node, + IPX_NODE_LEN); +#endif /* CONFIG_IPX_INTERN */ + + } else { + sipx.sipx_network = 0; + memset(sipx.sipx_node, '\0', IPX_NODE_LEN); + } + + sipx.sipx_port = ipxs->port; + } + + sipx.sipx_family = AF_IPX; + sipx.sipx_type = ipxs->type; + sipx.sipx_zero = 0; + memcpy(uaddr, &sipx, sizeof(sipx)); + + rc = 0; +out: + release_sock(sk); + return rc; +} + +static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) +{ + /* NULL here for pt means the packet was looped back */ + struct ipx_interface *intrfc; + struct ipxhdr *ipx; + u16 ipx_pktsize; + int rc = 0; + + if (!net_eq(dev_net(dev), &init_net)) + goto drop; + + /* Not ours */ + if (skb->pkt_type == PACKET_OTHERHOST) + goto drop; + + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) + goto out; + + if (!pskb_may_pull(skb, sizeof(struct ipxhdr))) + goto drop; + + ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); + + /* Too small or invalid header? */ + if (ipx_pktsize < sizeof(struct ipxhdr) || + !pskb_may_pull(skb, ipx_pktsize)) + goto drop; + + ipx = ipx_hdr(skb); + if (ipx->ipx_checksum != IPX_NO_CHECKSUM && + ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) + goto drop; + + IPX_SKB_CB(skb)->ipx_tctrl = ipx->ipx_tctrl; + IPX_SKB_CB(skb)->ipx_dest_net = ipx->ipx_dest.net; + IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net; + + /* Determine what local ipx endpoint this is */ + intrfc = ipxitf_find_using_phys(dev, pt->type); + if (!intrfc) { + if (ipxcfg_auto_create_interfaces && + IPX_SKB_CB(skb)->ipx_dest_net) { + intrfc = ipxitf_auto_create(dev, pt->type); + if (intrfc) + ipxitf_hold(intrfc); + } + + if (!intrfc) /* Not one of ours */ + /* or invalid packet for auto creation */ + goto drop; + } + + rc = ipxitf_rcv(intrfc, skb); + ipxitf_put(intrfc); + goto out; +drop: + kfree_skb(skb); +out: + return rc; +} + +static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) +{ + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + DECLARE_SOCKADDR(struct sockaddr_ipx *, usipx, msg->msg_name); + struct sockaddr_ipx local_sipx; + int rc = -EINVAL; + int flags = msg->msg_flags; + + lock_sock(sk); + /* Socket gets bound below anyway */ +/* if (sk->sk_zapped) + return -EIO; */ /* Socket not bound */ + if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) + goto out; + + /* Max possible packet size limited by 16 bit pktsize in header */ + if (len >= 65535 - sizeof(struct ipxhdr)) + goto out; + + if (usipx) { + if (!ipxs->port) { + struct sockaddr_ipx uaddr; + + uaddr.sipx_port = 0; + uaddr.sipx_network = 0; +#ifdef CONFIG_IPX_INTERN + rc = -ENETDOWN; + if (!ipxs->intrfc) + goto out; /* Someone zonked the iface */ + memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, + IPX_NODE_LEN); +#endif + rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + sizeof(struct sockaddr_ipx)); + if (rc) + goto out; + } + + rc = -EINVAL; + if (msg->msg_namelen < sizeof(*usipx) || + usipx->sipx_family != AF_IPX) + goto out; + } else { + rc = -ENOTCONN; + if (sk->sk_state != TCP_ESTABLISHED) + goto out; + + usipx = &local_sipx; + usipx->sipx_family = AF_IPX; + usipx->sipx_type = ipxs->type; + usipx->sipx_port = ipxs->dest_addr.sock; + usipx->sipx_network = ipxs->dest_addr.net; + memcpy(usipx->sipx_node, ipxs->dest_addr.node, IPX_NODE_LEN); + } + + rc = ipxrtr_route_packet(sk, usipx, msg, len, flags & MSG_DONTWAIT); + if (rc >= 0) + rc = len; +out: + release_sock(sk); + return rc; +} + + +static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, + int flags) +{ + struct sock *sk = sock->sk; + struct ipx_sock *ipxs = ipx_sk(sk); + DECLARE_SOCKADDR(struct sockaddr_ipx *, sipx, msg->msg_name); + struct ipxhdr *ipx = NULL; + struct sk_buff *skb; + int copied, rc; + bool locked = true; + + lock_sock(sk); + /* put the autobinding in */ + if (!ipxs->port) { + struct sockaddr_ipx uaddr; + + uaddr.sipx_port = 0; + uaddr.sipx_network = 0; + +#ifdef CONFIG_IPX_INTERN + rc = -ENETDOWN; + if (!ipxs->intrfc) + goto out; /* Someone zonked the iface */ + memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN); +#endif /* CONFIG_IPX_INTERN */ + + rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + sizeof(struct sockaddr_ipx)); + if (rc) + goto out; + } + + rc = -ENOTCONN; + if (sock_flag(sk, SOCK_ZAPPED)) + goto out; + + release_sock(sk); + locked = false; + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &rc); + if (!skb) { + if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN)) + rc = 0; + goto out; + } + + ipx = ipx_hdr(skb); + copied = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr); + if (copied > size) { + copied = size; + msg->msg_flags |= MSG_TRUNC; + } + + rc = skb_copy_datagram_msg(skb, sizeof(struct ipxhdr), msg, copied); + if (rc) + goto out_free; + if (skb->tstamp) + sk->sk_stamp = skb->tstamp; + + if (sipx) { + sipx->sipx_family = AF_IPX; + sipx->sipx_port = ipx->ipx_source.sock; + memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN); + sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net; + sipx->sipx_type = ipx->ipx_type; + sipx->sipx_zero = 0; + msg->msg_namelen = sizeof(*sipx); + } + rc = copied; + +out_free: + skb_free_datagram(sk, skb); +out: + if (locked) + release_sock(sk); + return rc; +} + + +static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + long amount = 0; + struct sock *sk = sock->sk; + void __user *argp = (void __user *)arg; + + lock_sock(sk); + switch (cmd) { + case TIOCOUTQ: + amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); + if (amount < 0) + amount = 0; + rc = put_user(amount, (int __user *)argp); + break; + case TIOCINQ: { + struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); + /* These two are safe on a single CPU system as only + * user tasks fiddle here */ + if (skb) + amount = skb->len - sizeof(struct ipxhdr); + rc = put_user(amount, (int __user *)argp); + break; + } + case SIOCADDRT: + case SIOCDELRT: + rc = -EPERM; + if (capable(CAP_NET_ADMIN)) + rc = ipxrtr_ioctl(cmd, argp); + break; + case SIOCSIFADDR: + case SIOCAIPXITFCRT: + case SIOCAIPXPRISLT: + rc = -EPERM; + if (!capable(CAP_NET_ADMIN)) + break; + /* fall through */ + case SIOCGIFADDR: + rc = ipxitf_ioctl(cmd, argp); + break; + case SIOCIPXCFGDATA: + rc = ipxcfg_get_config_data(argp); + break; + case SIOCIPXNCPCONN: + /* + * This socket wants to take care of the NCP connection + * handed to us in arg. + */ + rc = -EPERM; + if (!capable(CAP_NET_ADMIN)) + break; + rc = get_user(ipx_sk(sk)->ipx_ncp_conn, + (const unsigned short __user *)argp); + break; + case SIOCGSTAMP: + rc = sock_get_timestamp(sk, argp); + break; + case SIOCGIFDSTADDR: + case SIOCSIFDSTADDR: + case SIOCGIFBRDADDR: + case SIOCSIFBRDADDR: + case SIOCGIFNETMASK: + case SIOCSIFNETMASK: + rc = -EINVAL; + break; + default: + rc = -ENOIOCTLCMD; + break; + } + release_sock(sk); + + return rc; +} + + +#ifdef CONFIG_COMPAT +static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + /* + * These 4 commands use same structure on 32bit and 64bit. Rest of IPX + * commands is handled by generic ioctl code. As these commands are + * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic + * code. + */ + switch (cmd) { + case SIOCAIPXITFCRT: + case SIOCAIPXPRISLT: + case SIOCIPXCFGDATA: + case SIOCIPXNCPCONN: + return ipx_ioctl(sock, cmd, arg); + default: + return -ENOIOCTLCMD; + } +} +#endif + +static int ipx_shutdown(struct socket *sock, int mode) +{ + struct sock *sk = sock->sk; + + if (mode < SHUT_RD || mode > SHUT_RDWR) + return -EINVAL; + /* This maps: + * SHUT_RD (0) -> RCV_SHUTDOWN (1) + * SHUT_WR (1) -> SEND_SHUTDOWN (2) + * SHUT_RDWR (2) -> SHUTDOWN_MASK (3) + */ + ++mode; + + lock_sock(sk); + sk->sk_shutdown |= mode; + release_sock(sk); + sk->sk_state_change(sk); + + return 0; +} + +/* + * Socket family declarations + */ + +static const struct net_proto_family ipx_family_ops = { + .family = PF_IPX, + .create = ipx_create, + .owner = THIS_MODULE, +}; + +static const struct proto_ops ipx_dgram_ops = { + .family = PF_IPX, + .owner = THIS_MODULE, + .release = ipx_release, + .bind = ipx_bind, + .connect = ipx_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = ipx_getname, + .poll = datagram_poll, + .ioctl = ipx_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ipx_compat_ioctl, +#endif + .listen = sock_no_listen, + .shutdown = ipx_shutdown, + .setsockopt = ipx_setsockopt, + .getsockopt = ipx_getsockopt, + .sendmsg = ipx_sendmsg, + .recvmsg = ipx_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; + +static struct packet_type ipx_8023_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_802_3), + .func = ipx_rcv, +}; + +static struct packet_type ipx_dix_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_IPX), + .func = ipx_rcv, +}; + +static struct notifier_block ipx_dev_notifier = { + .notifier_call = ipxitf_device_event, +}; + +static const unsigned char ipx_8022_type = 0xE0; +static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; +static const char ipx_EII_err_msg[] __initconst = + KERN_CRIT "IPX: Unable to register with Ethernet II\n"; +static const char ipx_8023_err_msg[] __initconst = + KERN_CRIT "IPX: Unable to register with 802.3\n"; +static const char ipx_llc_err_msg[] __initconst = + KERN_CRIT "IPX: Unable to register with 802.2\n"; +static const char ipx_snap_err_msg[] __initconst = + KERN_CRIT "IPX: Unable to register with SNAP\n"; + +static int __init ipx_init(void) +{ + int rc = proto_register(&ipx_proto, 1); + + if (rc != 0) + goto out; + + sock_register(&ipx_family_ops); + + pEII_datalink = make_EII_client(); + if (pEII_datalink) + dev_add_pack(&ipx_dix_packet_type); + else + printk(ipx_EII_err_msg); + + p8023_datalink = make_8023_client(); + if (p8023_datalink) + dev_add_pack(&ipx_8023_packet_type); + else + printk(ipx_8023_err_msg); + + p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv); + if (!p8022_datalink) + printk(ipx_llc_err_msg); + + pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv); + if (!pSNAP_datalink) + printk(ipx_snap_err_msg); + + register_netdevice_notifier(&ipx_dev_notifier); + ipx_register_sysctl(); + ipx_proc_init(); +out: + return rc; +} + +static void __exit ipx_proto_finito(void) +{ + ipx_proc_exit(); + ipx_unregister_sysctl(); + + unregister_netdevice_notifier(&ipx_dev_notifier); + + ipxitf_cleanup(); + + if (pSNAP_datalink) { + unregister_snap_client(pSNAP_datalink); + pSNAP_datalink = NULL; + } + + if (p8022_datalink) { + unregister_8022_client(p8022_datalink); + p8022_datalink = NULL; + } + + dev_remove_pack(&ipx_8023_packet_type); + if (p8023_datalink) { + destroy_8023_client(p8023_datalink); + p8023_datalink = NULL; + } + + dev_remove_pack(&ipx_dix_packet_type); + if (pEII_datalink) { + destroy_EII_client(pEII_datalink); + pEII_datalink = NULL; + } + + proto_unregister(&ipx_proto); + sock_unregister(ipx_family_ops.family); +} + +module_init(ipx_init); +module_exit(ipx_proto_finito); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_NETPROTO(PF_IPX); diff --git a/drivers/staging/ipx/ipx_proc.c b/drivers/staging/ipx/ipx_proc.c new file mode 100644 index 000000000000..38a3d51d9ead --- /dev/null +++ b/drivers/staging/ipx/ipx_proc.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * IPX proc routines + * + * Copyright(C) Arnaldo Carvalho de Melo , 2002 + */ + +#include +#ifdef CONFIG_PROC_FS +#include +#include +#include +#include +#include +#include +#include + +static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) +{ + spin_lock_bh(&ipx_interfaces_lock); + return seq_list_start_head(&ipx_interfaces, *pos); +} + +static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) +{ + return seq_list_next(v, &ipx_interfaces, pos); +} + +static void ipx_seq_interface_stop(struct seq_file *seq, void *v) +{ + spin_unlock_bh(&ipx_interfaces_lock); +} + +static int ipx_seq_interface_show(struct seq_file *seq, void *v) +{ + struct ipx_interface *i; + + if (v == &ipx_interfaces) { + seq_puts(seq, "Network Node_Address Primary Device " + "Frame_Type"); +#ifdef IPX_REFCNT_DEBUG + seq_puts(seq, " refcnt"); +#endif + seq_puts(seq, "\n"); + goto out; + } + + i = list_entry(v, struct ipx_interface, node); + seq_printf(seq, "%08X ", ntohl(i->if_netnum)); + seq_printf(seq, "%02X%02X%02X%02X%02X%02X ", + i->if_node[0], i->if_node[1], i->if_node[2], + i->if_node[3], i->if_node[4], i->if_node[5]); + seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No"); + seq_printf(seq, "%-11s", ipx_device_name(i)); + seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type)); +#ifdef IPX_REFCNT_DEBUG + seq_printf(seq, "%6d", refcount_read(&i->refcnt)); +#endif + seq_puts(seq, "\n"); +out: + return 0; +} + +static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos) +{ + read_lock_bh(&ipx_routes_lock); + return seq_list_start_head(&ipx_routes, *pos); +} + +static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) +{ + return seq_list_next(v, &ipx_routes, pos); +} + +static void ipx_seq_route_stop(struct seq_file *seq, void *v) +{ + read_unlock_bh(&ipx_routes_lock); +} + +static int ipx_seq_route_show(struct seq_file *seq, void *v) +{ + struct ipx_route *rt; + + if (v == &ipx_routes) { + seq_puts(seq, "Network Router_Net Router_Node\n"); + goto out; + } + + rt = list_entry(v, struct ipx_route, node); + + seq_printf(seq, "%08X ", ntohl(rt->ir_net)); + if (rt->ir_routed) + seq_printf(seq, "%08X %02X%02X%02X%02X%02X%02X\n", + ntohl(rt->ir_intrfc->if_netnum), + rt->ir_router_node[0], rt->ir_router_node[1], + rt->ir_router_node[2], rt->ir_router_node[3], + rt->ir_router_node[4], rt->ir_router_node[5]); + else + seq_puts(seq, "Directly Connected\n"); +out: + return 0; +} + +static __inline__ struct sock *ipx_get_socket_idx(loff_t pos) +{ + struct sock *s = NULL; + struct ipx_interface *i; + + list_for_each_entry(i, &ipx_interfaces, node) { + spin_lock_bh(&i->if_sklist_lock); + sk_for_each(s, &i->if_sklist) { + if (!pos) + break; + --pos; + } + spin_unlock_bh(&i->if_sklist_lock); + if (!pos) { + if (s) + goto found; + break; + } + } + s = NULL; +found: + return s; +} + +static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos) +{ + loff_t l = *pos; + + spin_lock_bh(&ipx_interfaces_lock); + return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN; +} + +static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct sock* sk, *next; + struct ipx_interface *i; + struct ipx_sock *ipxs; + + ++*pos; + if (v == SEQ_START_TOKEN) { + sk = NULL; + i = ipx_interfaces_head(); + if (!i) + goto out; + sk = sk_head(&i->if_sklist); + if (sk) + spin_lock_bh(&i->if_sklist_lock); + goto out; + } + sk = v; + next = sk_next(sk); + if (next) { + sk = next; + goto out; + } + ipxs = ipx_sk(sk); + i = ipxs->intrfc; + spin_unlock_bh(&i->if_sklist_lock); + sk = NULL; + for (;;) { + if (i->node.next == &ipx_interfaces) + break; + i = list_entry(i->node.next, struct ipx_interface, node); + spin_lock_bh(&i->if_sklist_lock); + if (!hlist_empty(&i->if_sklist)) { + sk = sk_head(&i->if_sklist); + break; + } + spin_unlock_bh(&i->if_sklist_lock); + } +out: + return sk; +} + +static int ipx_seq_socket_show(struct seq_file *seq, void *v) +{ + struct sock *s; + struct ipx_sock *ipxs; + + if (v == SEQ_START_TOKEN) { +#ifdef CONFIG_IPX_INTERN + seq_puts(seq, "Local_Address " + "Remote_Address Tx_Queue " + "Rx_Queue State Uid\n"); +#else + seq_puts(seq, "Local_Address Remote_Address " + "Tx_Queue Rx_Queue State Uid\n"); +#endif + goto out; + } + + s = v; + ipxs = ipx_sk(s); +#ifdef CONFIG_IPX_INTERN + seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X ", + ntohl(ipxs->intrfc->if_netnum), + ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3], + ipxs->node[4], ipxs->node[5], ntohs(ipxs->port)); +#else + seq_printf(seq, "%08X:%04X ", ntohl(ipxs->intrfc->if_netnum), + ntohs(ipxs->port)); +#endif /* CONFIG_IPX_INTERN */ + if (s->sk_state != TCP_ESTABLISHED) + seq_printf(seq, "%-28s", "Not_Connected"); + else { + seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X ", + ntohl(ipxs->dest_addr.net), + ipxs->dest_addr.node[0], ipxs->dest_addr.node[1], + ipxs->dest_addr.node[2], ipxs->dest_addr.node[3], + ipxs->dest_addr.node[4], ipxs->dest_addr.node[5], + ntohs(ipxs->dest_addr.sock)); + } + + seq_printf(seq, "%08X %08X %02X %03u\n", + sk_wmem_alloc_get(s), + sk_rmem_alloc_get(s), + s->sk_state, + from_kuid_munged(seq_user_ns(seq), sock_i_uid(s))); +out: + return 0; +} + +static const struct seq_operations ipx_seq_interface_ops = { + .start = ipx_seq_interface_start, + .next = ipx_seq_interface_next, + .stop = ipx_seq_interface_stop, + .show = ipx_seq_interface_show, +}; + +static const struct seq_operations ipx_seq_route_ops = { + .start = ipx_seq_route_start, + .next = ipx_seq_route_next, + .stop = ipx_seq_route_stop, + .show = ipx_seq_route_show, +}; + +static const struct seq_operations ipx_seq_socket_ops = { + .start = ipx_seq_socket_start, + .next = ipx_seq_socket_next, + .stop = ipx_seq_interface_stop, + .show = ipx_seq_socket_show, +}; + +static int ipx_seq_route_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ipx_seq_route_ops); +} + +static int ipx_seq_interface_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ipx_seq_interface_ops); +} + +static int ipx_seq_socket_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ipx_seq_socket_ops); +} + +static const struct file_operations ipx_seq_interface_fops = { + .owner = THIS_MODULE, + .open = ipx_seq_interface_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations ipx_seq_route_fops = { + .owner = THIS_MODULE, + .open = ipx_seq_route_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations ipx_seq_socket_fops = { + .owner = THIS_MODULE, + .open = ipx_seq_socket_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static struct proc_dir_entry *ipx_proc_dir; + +int __init ipx_proc_init(void) +{ + struct proc_dir_entry *p; + int rc = -ENOMEM; + + ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net); + + if (!ipx_proc_dir) + goto out; + p = proc_create("interface", S_IRUGO, + ipx_proc_dir, &ipx_seq_interface_fops); + if (!p) + goto out_interface; + + p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops); + if (!p) + goto out_route; + + p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops); + if (!p) + goto out_socket; + + rc = 0; +out: + return rc; +out_socket: + remove_proc_entry("route", ipx_proc_dir); +out_route: + remove_proc_entry("interface", ipx_proc_dir); +out_interface: + remove_proc_entry("ipx", init_net.proc_net); + goto out; +} + +void __exit ipx_proc_exit(void) +{ + remove_proc_entry("interface", ipx_proc_dir); + remove_proc_entry("route", ipx_proc_dir); + remove_proc_entry("socket", ipx_proc_dir); + remove_proc_entry("ipx", init_net.proc_net); +} + +#else /* CONFIG_PROC_FS */ + +int __init ipx_proc_init(void) +{ + return 0; +} + +void __exit ipx_proc_exit(void) +{ +} + +#endif /* CONFIG_PROC_FS */ diff --git a/drivers/staging/ipx/ipx_route.c b/drivers/staging/ipx/ipx_route.c new file mode 100644 index 000000000000..3cf93aa9f284 --- /dev/null +++ b/drivers/staging/ipx/ipx_route.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implements the IPX routing routines. + * Code moved from af_ipx.c. + * + * Arnaldo Carvalho de Melo , 2003 + * + * See net/ipx/ChangeLog. + */ + +#include +#include +#include +#include + +#include +#include + +LIST_HEAD(ipx_routes); +DEFINE_RWLOCK(ipx_routes_lock); + +extern struct ipx_interface *ipx_internal_net; + +extern struct ipx_interface *ipxitf_find_using_net(__be32 net); +extern int ipxitf_demux_socket(struct ipx_interface *intrfc, + struct sk_buff *skb, int copy); +extern int ipxitf_demux_socket(struct ipx_interface *intrfc, + struct sk_buff *skb, int copy); + +struct ipx_route *ipxrtr_lookup(__be32 net) +{ + struct ipx_route *r; + + read_lock_bh(&ipx_routes_lock); + list_for_each_entry(r, &ipx_routes, node) + if (r->ir_net == net) { + ipxrtr_hold(r); + goto unlock; + } + r = NULL; +unlock: + read_unlock_bh(&ipx_routes_lock); + return r; +} + +/* + * Caller must hold a reference to intrfc + */ +int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, + unsigned char *node) +{ + struct ipx_route *rt; + int rc; + + /* Get a route structure; either existing or create */ + rt = ipxrtr_lookup(network); + if (!rt) { + rt = kmalloc(sizeof(*rt), GFP_ATOMIC); + rc = -EAGAIN; + if (!rt) + goto out; + + refcount_set(&rt->refcnt, 1); + ipxrtr_hold(rt); + write_lock_bh(&ipx_routes_lock); + list_add(&rt->node, &ipx_routes); + write_unlock_bh(&ipx_routes_lock); + } else { + rc = -EEXIST; + if (intrfc == ipx_internal_net) + goto out_put; + } + + rt->ir_net = network; + rt->ir_intrfc = intrfc; + if (!node) { + memset(rt->ir_router_node, '\0', IPX_NODE_LEN); + rt->ir_routed = 0; + } else { + memcpy(rt->ir_router_node, node, IPX_NODE_LEN); + rt->ir_routed = 1; + } + + rc = 0; +out_put: + ipxrtr_put(rt); +out: + return rc; +} + +void ipxrtr_del_routes(struct ipx_interface *intrfc) +{ + struct ipx_route *r, *tmp; + + write_lock_bh(&ipx_routes_lock); + list_for_each_entry_safe(r, tmp, &ipx_routes, node) + if (r->ir_intrfc == intrfc) { + list_del(&r->node); + ipxrtr_put(r); + } + write_unlock_bh(&ipx_routes_lock); +} + +static int ipxrtr_create(struct ipx_route_definition *rd) +{ + struct ipx_interface *intrfc; + int rc = -ENETUNREACH; + + /* Find the appropriate interface */ + intrfc = ipxitf_find_using_net(rd->ipx_router_network); + if (!intrfc) + goto out; + rc = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node); + ipxitf_put(intrfc); +out: + return rc; +} + +static int ipxrtr_delete(__be32 net) +{ + struct ipx_route *r, *tmp; + int rc; + + write_lock_bh(&ipx_routes_lock); + list_for_each_entry_safe(r, tmp, &ipx_routes, node) + if (r->ir_net == net) { + /* Directly connected; can't lose route */ + rc = -EPERM; + if (!r->ir_routed) + goto out; + list_del(&r->node); + ipxrtr_put(r); + rc = 0; + goto out; + } + rc = -ENOENT; +out: + write_unlock_bh(&ipx_routes_lock); + return rc; +} + +/* + * The skb has to be unshared, we'll end up calling ipxitf_send, that'll + * modify the packet + */ +int ipxrtr_route_skb(struct sk_buff *skb) +{ + struct ipxhdr *ipx = ipx_hdr(skb); + struct ipx_route *r = ipxrtr_lookup(IPX_SKB_CB(skb)->ipx_dest_net); + + if (!r) { /* no known route */ + kfree_skb(skb); + return 0; + } + + ipxitf_hold(r->ir_intrfc); + ipxitf_send(r->ir_intrfc, skb, r->ir_routed ? + r->ir_router_node : ipx->ipx_dest.node); + ipxitf_put(r->ir_intrfc); + ipxrtr_put(r); + + return 0; +} + +/* + * Route an outgoing frame from a socket. + */ +int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, + struct msghdr *msg, size_t len, int noblock) +{ + struct sk_buff *skb; + struct ipx_sock *ipxs = ipx_sk(sk); + struct ipx_interface *intrfc; + struct ipxhdr *ipx; + size_t size; + int ipx_offset; + struct ipx_route *rt = NULL; + int rc; + + /* Find the appropriate interface on which to send packet */ + if (!usipx->sipx_network && ipx_primary_net) { + usipx->sipx_network = ipx_primary_net->if_netnum; + intrfc = ipx_primary_net; + } else { + rt = ipxrtr_lookup(usipx->sipx_network); + rc = -ENETUNREACH; + if (!rt) + goto out; + intrfc = rt->ir_intrfc; + } + + ipxitf_hold(intrfc); + ipx_offset = intrfc->if_ipx_offset; + size = sizeof(struct ipxhdr) + len + ipx_offset; + + skb = sock_alloc_send_skb(sk, size, noblock, &rc); + if (!skb) + goto out_put; + + skb_reserve(skb, ipx_offset); + skb->sk = sk; + + /* Fill in IPX header */ + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + skb_put(skb, sizeof(struct ipxhdr)); + ipx = ipx_hdr(skb); + ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr)); + IPX_SKB_CB(skb)->ipx_tctrl = 0; + ipx->ipx_type = usipx->sipx_type; + + IPX_SKB_CB(skb)->last_hop.index = -1; +#ifdef CONFIG_IPX_INTERN + IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum; + memcpy(ipx->ipx_source.node, ipxs->node, IPX_NODE_LEN); +#else + rc = ntohs(ipxs->port); + if (rc == 0x453 || rc == 0x452) { + /* RIP/SAP special handling for mars_nwe */ + IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum; + memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN); + } else { + IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum; + memcpy(ipx->ipx_source.node, ipxs->intrfc->if_node, + IPX_NODE_LEN); + } +#endif /* CONFIG_IPX_INTERN */ + ipx->ipx_source.sock = ipxs->port; + IPX_SKB_CB(skb)->ipx_dest_net = usipx->sipx_network; + memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN); + ipx->ipx_dest.sock = usipx->sipx_port; + + rc = memcpy_from_msg(skb_put(skb, len), msg, len); + if (rc) { + kfree_skb(skb); + goto out_put; + } + + /* Apply checksum. Not allowed on 802.3 links. */ + if (sk->sk_no_check_tx || + intrfc->if_dlink_type == htons(IPX_FRAME_8023)) + ipx->ipx_checksum = htons(0xFFFF); + else + ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr)); + + rc = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ? + rt->ir_router_node : ipx->ipx_dest.node); +out_put: + ipxitf_put(intrfc); + if (rt) + ipxrtr_put(rt); +out: + return rc; +} + +/* + * We use a normal struct rtentry for route handling + */ +int ipxrtr_ioctl(unsigned int cmd, void __user *arg) +{ + struct rtentry rt; /* Use these to behave like 'other' stacks */ + struct sockaddr_ipx *sg, *st; + int rc = -EFAULT; + + if (copy_from_user(&rt, arg, sizeof(rt))) + goto out; + + sg = (struct sockaddr_ipx *)&rt.rt_gateway; + st = (struct sockaddr_ipx *)&rt.rt_dst; + + rc = -EINVAL; + if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */ + sg->sipx_family != AF_IPX || + st->sipx_family != AF_IPX) + goto out; + + switch (cmd) { + case SIOCDELRT: + rc = ipxrtr_delete(st->sipx_network); + break; + case SIOCADDRT: { + struct ipx_route_definition f; + f.ipx_network = st->sipx_network; + f.ipx_router_network = sg->sipx_network; + memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN); + rc = ipxrtr_create(&f); + break; + } + } + +out: + return rc; +} diff --git a/drivers/staging/ipx/pe2.c b/drivers/staging/ipx/pe2.c new file mode 100644 index 000000000000..ba7d4214bbff --- /dev/null +++ b/drivers/staging/ipx/pe2.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +#include + +static int pEII_request(struct datalink_proto *dl, + struct sk_buff *skb, unsigned char *dest_node) +{ + struct net_device *dev = skb->dev; + + skb->protocol = htons(ETH_P_IPX); + dev_hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len); + return dev_queue_xmit(skb); +} + +struct datalink_proto *make_EII_client(void) +{ + struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC); + + if (proto) { + proto->header_length = 0; + proto->request = pEII_request; + } + + return proto; +} + +void destroy_EII_client(struct datalink_proto *dl) +{ + kfree(dl); +} diff --git a/drivers/staging/ipx/sysctl_net_ipx.c b/drivers/staging/ipx/sysctl_net_ipx.c new file mode 100644 index 000000000000..c3eef457db88 --- /dev/null +++ b/drivers/staging/ipx/sysctl_net_ipx.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -*- linux-c -*- + * sysctl_net_ipx.c: sysctl interface to net IPX subsystem. + * + * Begun April 1, 1996, Mike Shaver. + * Added /proc/sys/net/ipx directory entry (empty =) ). [MS] + * Added /proc/sys/net/ipx/ipx_pprop_broadcasting - acme March 4, 2001 + */ + +#include +#include +#include +#include + +#ifndef CONFIG_SYSCTL +#error This file should not be compiled without CONFIG_SYSCTL defined +#endif + +static struct ctl_table ipx_table[] = { + { + .procname = "ipx_pprop_broadcasting", + .data = &sysctl_ipx_pprop_broadcasting, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { }, +}; + +static struct ctl_table_header *ipx_table_header; + +void ipx_register_sysctl(void) +{ + ipx_table_header = register_net_sysctl(&init_net, "net/ipx", ipx_table); +} + +void ipx_unregister_sysctl(void) +{ + unregister_net_sysctl_table(ipx_table_header); +} diff --git a/net/Kconfig b/net/Kconfig index 9dba2715919d..ff71ba0f6c27 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -212,7 +212,6 @@ source "net/dsa/Kconfig" source "net/8021q/Kconfig" source "net/decnet/Kconfig" source "net/llc/Kconfig" -source "net/ipx/Kconfig" source "drivers/net/appletalk/Kconfig" source "net/x25/Kconfig" source "net/lapb/Kconfig" diff --git a/net/Makefile b/net/Makefile index 14fede520840..a6147c61b174 100644 --- a/net/Makefile +++ b/net/Makefile @@ -24,7 +24,6 @@ obj-$(CONFIG_PACKET) += packet/ obj-$(CONFIG_NET_KEY) += key/ obj-$(CONFIG_BRIDGE) += bridge/ obj-$(CONFIG_NET_DSA) += dsa/ -obj-$(CONFIG_IPX) += ipx/ obj-$(CONFIG_ATALK) += appletalk/ obj-$(CONFIG_X25) += x25/ obj-$(CONFIG_LAPB) += lapb/ diff --git a/net/ipx/Kconfig b/net/ipx/Kconfig deleted file mode 100644 index e9ad0062fbb6..000000000000 --- a/net/ipx/Kconfig +++ /dev/null @@ -1,60 +0,0 @@ -# -# IPX configuration -# -config IPX - tristate "The IPX protocol" - select LLC - ---help--- - This is support for the Novell networking protocol, IPX, commonly - used for local networks of Windows machines. You need it if you - want to access Novell NetWare file or print servers using the Linux - Novell client ncpfs (available from - ) or from - within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, - available from ). In order - to do the former, you'll also have to say Y to "NCP file system - support", below. - - IPX is similar in scope to IP, while SPX, which runs on top of IPX, - is similar to TCP. - - To turn your Linux box into a fully featured NetWare file server and - IPX router, say Y here and fetch either lwared from - or - mars_nwe from . For more - information, read the IPX-HOWTO available from - . - - The IPX driver would enlarge your kernel by about 16 KB. To compile - this driver as a module, choose M here: the module will be called ipx. - Unless you want to integrate your Linux box with a local Novell - network, say N. - -config IPX_INTERN - bool "IPX: Full internal IPX network" - depends on IPX - ---help--- - Every IPX network has an address that identifies it. Sometimes it is - useful to give an IPX "network" address to your Linux box as well - (for example if your box is acting as a file server for different - IPX networks: it will then be accessible from everywhere using the - same address). The way this is done is to create a virtual internal - "network" inside your box and to assign an IPX address to this - network. Say Y here if you want to do this; read the IPX-HOWTO at - for details. - - The full internal IPX network enables you to allocate sockets on - different virtual nodes of the internal network. This is done by - evaluating the field sipx_node of the socket address given to the - bind call. So applications should always initialize the node field - to 0 when binding a socket on the primary network. In this case the - socket is assigned the default node that has been given to the - kernel when the internal network was created. By enabling the full - internal IPX network the cross-forwarding of packets targeted at - 'special' sockets to sockets listening on the primary network is - disabled. This might break existing applications, especially RIP/SAP - daemons. A RIP/SAP daemon that works well with the full internal net - can be found on . - - If you don't know what you are doing, say N. - diff --git a/net/ipx/Makefile b/net/ipx/Makefile deleted file mode 100644 index 440fafa9fd07..000000000000 --- a/net/ipx/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the Linux IPX layer. -# - -obj-$(CONFIG_IPX) += ipx.o - -ipx-y := af_ipx.o ipx_route.o ipx_proc.o pe2.o -ipx-$(CONFIG_SYSCTL) += sysctl_net_ipx.o diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c deleted file mode 100644 index d21a9d128d3e..000000000000 --- a/net/ipx/af_ipx.c +++ /dev/null @@ -1,2084 +0,0 @@ -/* - * Implements an IPX socket layer. - * - * This code is derived from work by - * Ross Biro : Writing the original IP stack - * Fred Van Kempen : Tidying up the TCP/IP - * - * Many thanks go to Keith Baker, Institute For Industrial Information - * Technology Ltd, Swansea University for allowing me to work on this - * in my own time even though it was in some ways related to commercial - * work I am currently employed to do there. - * - * All the material in this file is subject to the Gnu license version 2. - * Neither Alan Cox nor the Swansea University Computer Society admit - * liability nor provide warranty for any of this software. This material - * is provided as is and at no charge. - * - * Portions Copyright (c) 2000-2003 Conectiva, Inc. - * Neither Arnaldo Carvalho de Melo nor Conectiva, Inc. admit liability nor - * provide warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * Portions Copyright (c) 1995 Caldera, Inc. - * Neither Greg Page nor Caldera, Inc. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * See net/ipx/ChangeLog. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Configuration Variables */ -static unsigned char ipxcfg_max_hops = 16; -static char ipxcfg_auto_select_primary; -static char ipxcfg_auto_create_interfaces; -int sysctl_ipx_pprop_broadcasting = 1; - -/* Global Variables */ -static struct datalink_proto *p8022_datalink; -static struct datalink_proto *pEII_datalink; -static struct datalink_proto *p8023_datalink; -static struct datalink_proto *pSNAP_datalink; - -static const struct proto_ops ipx_dgram_ops; - -LIST_HEAD(ipx_interfaces); -DEFINE_SPINLOCK(ipx_interfaces_lock); - -struct ipx_interface *ipx_primary_net; -struct ipx_interface *ipx_internal_net; - -struct ipx_interface *ipx_interfaces_head(void) -{ - struct ipx_interface *rc = NULL; - - if (!list_empty(&ipx_interfaces)) - rc = list_entry(ipx_interfaces.next, - struct ipx_interface, node); - return rc; -} - -static void ipxcfg_set_auto_select(char val) -{ - ipxcfg_auto_select_primary = val; - if (val && !ipx_primary_net) - ipx_primary_net = ipx_interfaces_head(); -} - -static int ipxcfg_get_config_data(struct ipx_config_data __user *arg) -{ - struct ipx_config_data vals; - - vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces; - vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary; - - return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0; -} - -/* - * Note: Sockets may not be removed _during_ an interrupt or inet_bh - * handler using this technique. They can be added although we do not - * use this facility. - */ - -static void ipx_remove_socket(struct sock *sk) -{ - /* Determine interface with which socket is associated */ - struct ipx_interface *intrfc = ipx_sk(sk)->intrfc; - - if (!intrfc) - goto out; - - ipxitf_hold(intrfc); - spin_lock_bh(&intrfc->if_sklist_lock); - sk_del_node_init(sk); - spin_unlock_bh(&intrfc->if_sklist_lock); - ipxitf_put(intrfc); -out: - return; -} - -static void ipx_destroy_socket(struct sock *sk) -{ - ipx_remove_socket(sk); - skb_queue_purge(&sk->sk_receive_queue); - sk_refcnt_debug_dec(sk); -} - -/* - * The following code is used to support IPX Interfaces (IPXITF). An - * IPX interface is defined by a physical device and a frame type. - */ - -/* ipxitf_clear_primary_net has to be called with ipx_interfaces_lock held */ - -static void ipxitf_clear_primary_net(void) -{ - ipx_primary_net = NULL; - if (ipxcfg_auto_select_primary) - ipx_primary_net = ipx_interfaces_head(); -} - -static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev, - __be16 datalink) -{ - struct ipx_interface *i; - - list_for_each_entry(i, &ipx_interfaces, node) - if (i->if_dev == dev && i->if_dlink_type == datalink) - goto out; - i = NULL; -out: - return i; -} - -static struct ipx_interface *ipxitf_find_using_phys(struct net_device *dev, - __be16 datalink) -{ - struct ipx_interface *i; - - spin_lock_bh(&ipx_interfaces_lock); - i = __ipxitf_find_using_phys(dev, datalink); - if (i) - ipxitf_hold(i); - spin_unlock_bh(&ipx_interfaces_lock); - return i; -} - -struct ipx_interface *ipxitf_find_using_net(__be32 net) -{ - struct ipx_interface *i; - - spin_lock_bh(&ipx_interfaces_lock); - if (net) { - list_for_each_entry(i, &ipx_interfaces, node) - if (i->if_netnum == net) - goto hold; - i = NULL; - goto unlock; - } - - i = ipx_primary_net; - if (i) -hold: - ipxitf_hold(i); -unlock: - spin_unlock_bh(&ipx_interfaces_lock); - return i; -} - -/* Sockets are bound to a particular IPX interface. */ -static void ipxitf_insert_socket(struct ipx_interface *intrfc, struct sock *sk) -{ - ipxitf_hold(intrfc); - spin_lock_bh(&intrfc->if_sklist_lock); - ipx_sk(sk)->intrfc = intrfc; - sk_add_node(sk, &intrfc->if_sklist); - spin_unlock_bh(&intrfc->if_sklist_lock); - ipxitf_put(intrfc); -} - -/* caller must hold intrfc->if_sklist_lock */ -static struct sock *__ipxitf_find_socket(struct ipx_interface *intrfc, - __be16 port) -{ - struct sock *s; - - sk_for_each(s, &intrfc->if_sklist) - if (ipx_sk(s)->port == port) - goto found; - s = NULL; -found: - return s; -} - -/* caller must hold a reference to intrfc */ -static struct sock *ipxitf_find_socket(struct ipx_interface *intrfc, - __be16 port) -{ - struct sock *s; - - spin_lock_bh(&intrfc->if_sklist_lock); - s = __ipxitf_find_socket(intrfc, port); - if (s) - sock_hold(s); - spin_unlock_bh(&intrfc->if_sklist_lock); - - return s; -} - -#ifdef CONFIG_IPX_INTERN -static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc, - unsigned char *ipx_node, - __be16 port) -{ - struct sock *s; - - ipxitf_hold(intrfc); - spin_lock_bh(&intrfc->if_sklist_lock); - - sk_for_each(s, &intrfc->if_sklist) { - struct ipx_sock *ipxs = ipx_sk(s); - - if (ipxs->port == port && - !memcmp(ipx_node, ipxs->node, IPX_NODE_LEN)) - goto found; - } - s = NULL; -found: - spin_unlock_bh(&intrfc->if_sklist_lock); - ipxitf_put(intrfc); - return s; -} -#endif - -static void __ipxitf_down(struct ipx_interface *intrfc) -{ - struct sock *s; - struct hlist_node *t; - - /* Delete all routes associated with this interface */ - ipxrtr_del_routes(intrfc); - - spin_lock_bh(&intrfc->if_sklist_lock); - /* error sockets */ - sk_for_each_safe(s, t, &intrfc->if_sklist) { - struct ipx_sock *ipxs = ipx_sk(s); - - s->sk_err = ENOLINK; - s->sk_error_report(s); - ipxs->intrfc = NULL; - ipxs->port = 0; - sock_set_flag(s, SOCK_ZAPPED); /* Indicates it is no longer bound */ - sk_del_node_init(s); - } - INIT_HLIST_HEAD(&intrfc->if_sklist); - spin_unlock_bh(&intrfc->if_sklist_lock); - - /* remove this interface from list */ - list_del(&intrfc->node); - - /* remove this interface from *special* networks */ - if (intrfc == ipx_primary_net) - ipxitf_clear_primary_net(); - if (intrfc == ipx_internal_net) - ipx_internal_net = NULL; - - if (intrfc->if_dev) - dev_put(intrfc->if_dev); - kfree(intrfc); -} - -void ipxitf_down(struct ipx_interface *intrfc) -{ - spin_lock_bh(&ipx_interfaces_lock); - __ipxitf_down(intrfc); - spin_unlock_bh(&ipx_interfaces_lock); -} - -static void __ipxitf_put(struct ipx_interface *intrfc) -{ - if (refcount_dec_and_test(&intrfc->refcnt)) - __ipxitf_down(intrfc); -} - -static int ipxitf_device_event(struct notifier_block *notifier, - unsigned long event, void *ptr) -{ - struct net_device *dev = netdev_notifier_info_to_dev(ptr); - struct ipx_interface *i, *tmp; - - if (!net_eq(dev_net(dev), &init_net)) - return NOTIFY_DONE; - - if (event != NETDEV_DOWN && event != NETDEV_UP) - goto out; - - spin_lock_bh(&ipx_interfaces_lock); - list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) - if (i->if_dev == dev) { - if (event == NETDEV_UP) - ipxitf_hold(i); - else - __ipxitf_put(i); - } - spin_unlock_bh(&ipx_interfaces_lock); -out: - return NOTIFY_DONE; -} - - -static __exit void ipxitf_cleanup(void) -{ - struct ipx_interface *i, *tmp; - - spin_lock_bh(&ipx_interfaces_lock); - list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) - __ipxitf_put(i); - spin_unlock_bh(&ipx_interfaces_lock); -} - -static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb) -{ - if (sock_queue_rcv_skb(sock, skb) < 0) - kfree_skb(skb); -} - -/* - * On input skb->sk is NULL. Nobody is charged for the memory. - */ - -/* caller must hold a reference to intrfc */ - -#ifdef CONFIG_IPX_INTERN -static int ipxitf_demux_socket(struct ipx_interface *intrfc, - struct sk_buff *skb, int copy) -{ - struct ipxhdr *ipx = ipx_hdr(skb); - int is_broadcast = !memcmp(ipx->ipx_dest.node, ipx_broadcast_node, - IPX_NODE_LEN); - struct sock *s; - int rc; - - spin_lock_bh(&intrfc->if_sklist_lock); - - sk_for_each(s, &intrfc->if_sklist) { - struct ipx_sock *ipxs = ipx_sk(s); - - if (ipxs->port == ipx->ipx_dest.sock && - (is_broadcast || !memcmp(ipx->ipx_dest.node, - ipxs->node, IPX_NODE_LEN))) { - /* We found a socket to which to send */ - struct sk_buff *skb1; - - if (copy) { - skb1 = skb_clone(skb, GFP_ATOMIC); - rc = -ENOMEM; - if (!skb1) - goto out; - } else { - skb1 = skb; - copy = 1; /* skb may only be used once */ - } - ipxitf_def_skb_handler(s, skb1); - - /* On an external interface, one socket can listen */ - if (intrfc != ipx_internal_net) - break; - } - } - - /* skb was solely for us, and we did not make a copy, so free it. */ - if (!copy) - kfree_skb(skb); - - rc = 0; -out: - spin_unlock_bh(&intrfc->if_sklist_lock); - return rc; -} -#else -static struct sock *ncp_connection_hack(struct ipx_interface *intrfc, - struct ipxhdr *ipx) -{ - /* The packet's target is a NCP connection handler. We want to hand it - * to the correct socket directly within the kernel, so that the - * mars_nwe packet distribution process does not have to do it. Here we - * only care about NCP and BURST packets. - * - * You might call this a hack, but believe me, you do not want a - * complete NCP layer in the kernel, and this is VERY fast as well. */ - struct sock *sk = NULL; - int connection = 0; - u8 *ncphdr = (u8 *)(ipx + 1); - - if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */ - connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3); - else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */ - connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8); - - if (connection) { - /* Now we have to look for a special NCP connection handling - * socket. Only these sockets have ipx_ncp_conn != 0, set by - * SIOCIPXNCPCONN. */ - spin_lock_bh(&intrfc->if_sklist_lock); - sk_for_each(sk, &intrfc->if_sklist) - if (ipx_sk(sk)->ipx_ncp_conn == connection) { - sock_hold(sk); - goto found; - } - sk = NULL; - found: - spin_unlock_bh(&intrfc->if_sklist_lock); - } - return sk; -} - -static int ipxitf_demux_socket(struct ipx_interface *intrfc, - struct sk_buff *skb, int copy) -{ - struct ipxhdr *ipx = ipx_hdr(skb); - struct sock *sock1 = NULL, *sock2 = NULL; - struct sk_buff *skb1 = NULL, *skb2 = NULL; - int rc; - - if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) - sock1 = ncp_connection_hack(intrfc, ipx); - if (!sock1) - /* No special socket found, forward the packet the normal way */ - sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock); - - /* - * We need to check if there is a primary net and if - * this is addressed to one of the *SPECIAL* sockets because - * these need to be propagated to the primary net. - * The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and - * 0x456(Diagnostic). - */ - - if (ipx_primary_net && intrfc != ipx_primary_net) { - const int dsock = ntohs(ipx->ipx_dest.sock); - - if (dsock == 0x452 || dsock == 0x453 || dsock == 0x456) - /* The appropriate thing to do here is to dup the - * packet and route to the primary net interface via - * ipxitf_send; however, we'll cheat and just demux it - * here. */ - sock2 = ipxitf_find_socket(ipx_primary_net, - ipx->ipx_dest.sock); - } - - /* - * If there is nothing to do return. The kfree will cancel any charging. - */ - rc = 0; - if (!sock1 && !sock2) { - if (!copy) - kfree_skb(skb); - goto out; - } - - /* - * This next segment of code is a little awkward, but it sets it up - * so that the appropriate number of copies of the SKB are made and - * that skb1 and skb2 point to it (them) so that it (they) can be - * demuxed to sock1 and/or sock2. If we are unable to make enough - * copies, we do as much as is possible. - */ - - if (copy) - skb1 = skb_clone(skb, GFP_ATOMIC); - else - skb1 = skb; - - rc = -ENOMEM; - if (!skb1) - goto out_put; - - /* Do we need 2 SKBs? */ - if (sock1 && sock2) - skb2 = skb_clone(skb1, GFP_ATOMIC); - else - skb2 = skb1; - - if (sock1) - ipxitf_def_skb_handler(sock1, skb1); - - if (!skb2) - goto out_put; - - if (sock2) - ipxitf_def_skb_handler(sock2, skb2); - - rc = 0; -out_put: - if (sock1) - sock_put(sock1); - if (sock2) - sock_put(sock2); -out: - return rc; -} -#endif /* CONFIG_IPX_INTERN */ - -static struct sk_buff *ipxitf_adjust_skbuff(struct ipx_interface *intrfc, - struct sk_buff *skb) -{ - struct sk_buff *skb2; - int in_offset = (unsigned char *)ipx_hdr(skb) - skb->head; - int out_offset = intrfc->if_ipx_offset; - int len; - - /* Hopefully, most cases */ - if (in_offset >= out_offset) - return skb; - - /* Need new SKB */ - len = skb->len + out_offset; - skb2 = alloc_skb(len, GFP_ATOMIC); - if (skb2) { - skb_reserve(skb2, out_offset); - skb_reset_network_header(skb2); - skb_reset_transport_header(skb2); - skb_put(skb2, skb->len); - memcpy(ipx_hdr(skb2), ipx_hdr(skb), skb->len); - memcpy(skb2->cb, skb->cb, sizeof(skb->cb)); - } - kfree_skb(skb); - return skb2; -} - -/* caller must hold a reference to intrfc and the skb has to be unshared */ -int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node) -{ - struct ipxhdr *ipx = ipx_hdr(skb); - struct net_device *dev = intrfc->if_dev; - struct datalink_proto *dl = intrfc->if_dlink; - char dest_node[IPX_NODE_LEN]; - int send_to_wire = 1; - int addr_len; - - ipx->ipx_tctrl = IPX_SKB_CB(skb)->ipx_tctrl; - ipx->ipx_dest.net = IPX_SKB_CB(skb)->ipx_dest_net; - ipx->ipx_source.net = IPX_SKB_CB(skb)->ipx_source_net; - - /* see if we need to include the netnum in the route list */ - if (IPX_SKB_CB(skb)->last_hop.index >= 0) { - __be32 *last_hop = (__be32 *)(((u8 *) skb->data) + - sizeof(struct ipxhdr) + - IPX_SKB_CB(skb)->last_hop.index * - sizeof(__be32)); - *last_hop = IPX_SKB_CB(skb)->last_hop.netnum; - IPX_SKB_CB(skb)->last_hop.index = -1; - } - - /* - * We need to know how many skbuffs it will take to send out this - * packet to avoid unnecessary copies. - */ - - if (!dl || !dev || dev->flags & IFF_LOOPBACK) - send_to_wire = 0; /* No non looped */ - - /* - * See if this should be demuxed to sockets on this interface - * - * We want to ensure the original was eaten or that we only use - * up clones. - */ - - if (ipx->ipx_dest.net == intrfc->if_netnum) { - /* - * To our own node, loop and free the original. - * The internal net will receive on all node address. - */ - if (intrfc == ipx_internal_net || - !memcmp(intrfc->if_node, node, IPX_NODE_LEN)) { - /* Don't charge sender */ - skb_orphan(skb); - - /* Will charge receiver */ - return ipxitf_demux_socket(intrfc, skb, 0); - } - - /* Broadcast, loop and possibly keep to send on. */ - if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) { - if (!send_to_wire) - skb_orphan(skb); - ipxitf_demux_socket(intrfc, skb, send_to_wire); - if (!send_to_wire) - goto out; - } - } - - /* - * If the originating net is not equal to our net; this is routed - * We are still charging the sender. Which is right - the driver - * free will handle this fairly. - */ - if (ipx->ipx_source.net != intrfc->if_netnum) { - /* - * Unshare the buffer before modifying the count in - * case it's a flood or tcpdump - */ - skb = skb_unshare(skb, GFP_ATOMIC); - if (!skb) - goto out; - if (++ipx->ipx_tctrl > ipxcfg_max_hops) - send_to_wire = 0; - } - - if (!send_to_wire) { - kfree_skb(skb); - goto out; - } - - /* Determine the appropriate hardware address */ - addr_len = dev->addr_len; - if (!memcmp(ipx_broadcast_node, node, IPX_NODE_LEN)) - memcpy(dest_node, dev->broadcast, addr_len); - else - memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len); - - /* Make any compensation for differing physical/data link size */ - skb = ipxitf_adjust_skbuff(intrfc, skb); - if (!skb) - goto out; - - /* set up data link and physical headers */ - skb->dev = dev; - skb->protocol = htons(ETH_P_IPX); - - /* Send it out */ - dl->request(dl, skb, dest_node); -out: - return 0; -} - -static int ipxitf_add_local_route(struct ipx_interface *intrfc) -{ - return ipxrtr_add_route(intrfc->if_netnum, intrfc, NULL); -} - -static void ipxitf_discover_netnum(struct ipx_interface *intrfc, - struct sk_buff *skb); -static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb); - -static int ipxitf_rcv(struct ipx_interface *intrfc, struct sk_buff *skb) -{ - struct ipxhdr *ipx = ipx_hdr(skb); - int rc = 0; - - ipxitf_hold(intrfc); - - /* See if we should update our network number */ - if (!intrfc->if_netnum) /* net number of intrfc not known yet */ - ipxitf_discover_netnum(intrfc, skb); - - IPX_SKB_CB(skb)->last_hop.index = -1; - if (ipx->ipx_type == IPX_TYPE_PPROP) { - rc = ipxitf_pprop(intrfc, skb); - if (rc) - goto out_free_skb; - } - - /* local processing follows */ - if (!IPX_SKB_CB(skb)->ipx_dest_net) - IPX_SKB_CB(skb)->ipx_dest_net = intrfc->if_netnum; - if (!IPX_SKB_CB(skb)->ipx_source_net) - IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum; - - /* it doesn't make sense to route a pprop packet, there's no meaning - * in the ipx_dest_net for such packets */ - if (ipx->ipx_type != IPX_TYPE_PPROP && - intrfc->if_netnum != IPX_SKB_CB(skb)->ipx_dest_net) { - /* We only route point-to-point packets. */ - if (skb->pkt_type == PACKET_HOST) { - skb = skb_unshare(skb, GFP_ATOMIC); - if (skb) - rc = ipxrtr_route_skb(skb); - goto out_intrfc; - } - - goto out_free_skb; - } - - /* see if we should keep it */ - if (!memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) || - !memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN)) { - rc = ipxitf_demux_socket(intrfc, skb, 0); - goto out_intrfc; - } - - /* we couldn't pawn it off so unload it */ -out_free_skb: - kfree_skb(skb); -out_intrfc: - ipxitf_put(intrfc); - return rc; -} - -static void ipxitf_discover_netnum(struct ipx_interface *intrfc, - struct sk_buff *skb) -{ - const struct ipx_cb *cb = IPX_SKB_CB(skb); - - /* see if this is an intra packet: source_net == dest_net */ - if (cb->ipx_source_net == cb->ipx_dest_net && cb->ipx_source_net) { - struct ipx_interface *i = - ipxitf_find_using_net(cb->ipx_source_net); - /* NB: NetWare servers lie about their hop count so we - * dropped the test based on it. This is the best way - * to determine this is a 0 hop count packet. */ - if (!i) { - intrfc->if_netnum = cb->ipx_source_net; - ipxitf_add_local_route(intrfc); - } else { - printk(KERN_WARNING "IPX: Network number collision " - "%lx\n %s %s and %s %s\n", - (unsigned long) ntohl(cb->ipx_source_net), - ipx_device_name(i), - ipx_frame_name(i->if_dlink_type), - ipx_device_name(intrfc), - ipx_frame_name(intrfc->if_dlink_type)); - ipxitf_put(i); - } - } -} - -/** - * ipxitf_pprop - Process packet propagation IPX packet type 0x14, used for - * NetBIOS broadcasts - * @intrfc: IPX interface receiving this packet - * @skb: Received packet - * - * Checks if packet is valid: if its more than %IPX_MAX_PPROP_HOPS hops or if it - * is smaller than a IPX header + the room for %IPX_MAX_PPROP_HOPS hops we drop - * it, not even processing it locally, if it has exact %IPX_MAX_PPROP_HOPS we - * don't broadcast it, but process it locally. See chapter 5 of Novell's "IPX - * RIP and SAP Router Specification", Part Number 107-000029-001. - * - * If it is valid, check if we have pprop broadcasting enabled by the user, - * if not, just return zero for local processing. - * - * If it is enabled check the packet and don't broadcast it if we have already - * seen this packet. - * - * Broadcast: send it to the interfaces that aren't on the packet visited nets - * array, just after the IPX header. - * - * Returns -EINVAL for invalid packets, so that the calling function drops - * the packet without local processing. 0 if packet is to be locally processed. - */ -static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) -{ - struct ipxhdr *ipx = ipx_hdr(skb); - int i, rc = -EINVAL; - struct ipx_interface *ifcs; - char *c; - __be32 *l; - - /* Illegal packet - too many hops or too short */ - /* We decide to throw it away: no broadcasting, no local processing. - * NetBIOS unaware implementations route them as normal packets - - * tctrl <= 15, any data payload... */ - if (IPX_SKB_CB(skb)->ipx_tctrl > IPX_MAX_PPROP_HOPS || - ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr) + - IPX_MAX_PPROP_HOPS * sizeof(u32)) - goto out; - /* are we broadcasting this damn thing? */ - rc = 0; - if (!sysctl_ipx_pprop_broadcasting) - goto out; - /* We do broadcast packet on the IPX_MAX_PPROP_HOPS hop, but we - * process it locally. All previous hops broadcasted it, and process it - * locally. */ - if (IPX_SKB_CB(skb)->ipx_tctrl == IPX_MAX_PPROP_HOPS) - goto out; - - c = ((u8 *) ipx) + sizeof(struct ipxhdr); - l = (__be32 *) c; - - /* Don't broadcast packet if already seen this net */ - for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++) - if (*l++ == intrfc->if_netnum) - goto out; - - /* < IPX_MAX_PPROP_HOPS hops && input interface not in list. Save the - * position where we will insert recvd netnum into list, later on, - * in ipxitf_send */ - IPX_SKB_CB(skb)->last_hop.index = i; - IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum; - /* xmit on all other interfaces... */ - spin_lock_bh(&ipx_interfaces_lock); - list_for_each_entry(ifcs, &ipx_interfaces, node) { - /* Except unconfigured interfaces */ - if (!ifcs->if_netnum) - continue; - - /* That aren't in the list */ - if (ifcs == intrfc) - continue; - l = (__be32 *) c; - /* don't consider the last entry in the packet list, - * it is our netnum, and it is not there yet */ - for (i = 0; i < IPX_SKB_CB(skb)->ipx_tctrl; i++) - if (ifcs->if_netnum == *l++) - break; - if (i == IPX_SKB_CB(skb)->ipx_tctrl) { - struct sk_buff *s = skb_copy(skb, GFP_ATOMIC); - - if (s) { - IPX_SKB_CB(s)->ipx_dest_net = ifcs->if_netnum; - ipxrtr_route_skb(s); - } - } - } - spin_unlock_bh(&ipx_interfaces_lock); -out: - return rc; -} - -static void ipxitf_insert(struct ipx_interface *intrfc) -{ - spin_lock_bh(&ipx_interfaces_lock); - list_add_tail(&intrfc->node, &ipx_interfaces); - spin_unlock_bh(&ipx_interfaces_lock); - - if (ipxcfg_auto_select_primary && !ipx_primary_net) - ipx_primary_net = intrfc; -} - -static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum, - __be16 dlink_type, - struct datalink_proto *dlink, - unsigned char internal, - int ipx_offset) -{ - struct ipx_interface *intrfc = kmalloc(sizeof(*intrfc), GFP_ATOMIC); - - if (intrfc) { - intrfc->if_dev = dev; - intrfc->if_netnum = netnum; - intrfc->if_dlink_type = dlink_type; - intrfc->if_dlink = dlink; - intrfc->if_internal = internal; - intrfc->if_ipx_offset = ipx_offset; - intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET; - INIT_HLIST_HEAD(&intrfc->if_sklist); - refcount_set(&intrfc->refcnt, 1); - spin_lock_init(&intrfc->if_sklist_lock); - } - - return intrfc; -} - -static int ipxitf_create_internal(struct ipx_interface_definition *idef) -{ - struct ipx_interface *intrfc; - int rc = -EEXIST; - - /* Only one primary network allowed */ - if (ipx_primary_net) - goto out; - - /* Must have a valid network number */ - rc = -EADDRNOTAVAIL; - if (!idef->ipx_network) - goto out; - intrfc = ipxitf_find_using_net(idef->ipx_network); - rc = -EADDRINUSE; - if (intrfc) { - ipxitf_put(intrfc); - goto out; - } - intrfc = ipxitf_alloc(NULL, idef->ipx_network, 0, NULL, 1, 0); - rc = -EAGAIN; - if (!intrfc) - goto out; - memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN); - ipx_internal_net = ipx_primary_net = intrfc; - ipxitf_hold(intrfc); - ipxitf_insert(intrfc); - - rc = ipxitf_add_local_route(intrfc); - ipxitf_put(intrfc); -out: - return rc; -} - -static __be16 ipx_map_frame_type(unsigned char type) -{ - __be16 rc = 0; - - switch (type) { - case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX); break; - case IPX_FRAME_8022: rc = htons(ETH_P_802_2); break; - case IPX_FRAME_SNAP: rc = htons(ETH_P_SNAP); break; - case IPX_FRAME_8023: rc = htons(ETH_P_802_3); break; - } - - return rc; -} - -static int ipxitf_create(struct ipx_interface_definition *idef) -{ - struct net_device *dev; - __be16 dlink_type = 0; - struct datalink_proto *datalink = NULL; - struct ipx_interface *intrfc; - int rc; - - if (idef->ipx_special == IPX_INTERNAL) { - rc = ipxitf_create_internal(idef); - goto out; - } - - rc = -EEXIST; - if (idef->ipx_special == IPX_PRIMARY && ipx_primary_net) - goto out; - - intrfc = ipxitf_find_using_net(idef->ipx_network); - rc = -EADDRINUSE; - if (idef->ipx_network && intrfc) { - ipxitf_put(intrfc); - goto out; - } - - if (intrfc) - ipxitf_put(intrfc); - - dev = dev_get_by_name(&init_net, idef->ipx_device); - rc = -ENODEV; - if (!dev) - goto out; - - switch (idef->ipx_dlink_type) { - case IPX_FRAME_8022: - dlink_type = htons(ETH_P_802_2); - datalink = p8022_datalink; - break; - case IPX_FRAME_ETHERII: - if (dev->type != ARPHRD_IEEE802) { - dlink_type = htons(ETH_P_IPX); - datalink = pEII_datalink; - break; - } - /* fall through */ - case IPX_FRAME_SNAP: - dlink_type = htons(ETH_P_SNAP); - datalink = pSNAP_datalink; - break; - case IPX_FRAME_8023: - dlink_type = htons(ETH_P_802_3); - datalink = p8023_datalink; - break; - case IPX_FRAME_NONE: - default: - rc = -EPROTONOSUPPORT; - goto out_dev; - } - - rc = -ENETDOWN; - if (!(dev->flags & IFF_UP)) - goto out_dev; - - /* Check addresses are suitable */ - rc = -EINVAL; - if (dev->addr_len > IPX_NODE_LEN) - goto out_dev; - - intrfc = ipxitf_find_using_phys(dev, dlink_type); - if (!intrfc) { - /* Ok now create */ - intrfc = ipxitf_alloc(dev, idef->ipx_network, dlink_type, - datalink, 0, dev->hard_header_len + - datalink->header_length); - rc = -EAGAIN; - if (!intrfc) - goto out_dev; - /* Setup primary if necessary */ - if (idef->ipx_special == IPX_PRIMARY) - ipx_primary_net = intrfc; - if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000", - IPX_NODE_LEN)) { - memset(intrfc->if_node, 0, IPX_NODE_LEN); - memcpy(intrfc->if_node + IPX_NODE_LEN - dev->addr_len, - dev->dev_addr, dev->addr_len); - } else - memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN); - ipxitf_hold(intrfc); - ipxitf_insert(intrfc); - } - - - /* If the network number is known, add a route */ - rc = 0; - if (!intrfc->if_netnum) - goto out_intrfc; - - rc = ipxitf_add_local_route(intrfc); -out_intrfc: - ipxitf_put(intrfc); - goto out; -out_dev: - dev_put(dev); -out: - return rc; -} - -static int ipxitf_delete(struct ipx_interface_definition *idef) -{ - struct net_device *dev = NULL; - __be16 dlink_type = 0; - struct ipx_interface *intrfc; - int rc = 0; - - spin_lock_bh(&ipx_interfaces_lock); - if (idef->ipx_special == IPX_INTERNAL) { - if (ipx_internal_net) { - __ipxitf_put(ipx_internal_net); - goto out; - } - rc = -ENOENT; - goto out; - } - - dlink_type = ipx_map_frame_type(idef->ipx_dlink_type); - rc = -EPROTONOSUPPORT; - if (!dlink_type) - goto out; - - dev = __dev_get_by_name(&init_net, idef->ipx_device); - rc = -ENODEV; - if (!dev) - goto out; - - intrfc = __ipxitf_find_using_phys(dev, dlink_type); - rc = -EINVAL; - if (!intrfc) - goto out; - __ipxitf_put(intrfc); - - rc = 0; -out: - spin_unlock_bh(&ipx_interfaces_lock); - return rc; -} - -static struct ipx_interface *ipxitf_auto_create(struct net_device *dev, - __be16 dlink_type) -{ - struct ipx_interface *intrfc = NULL; - struct datalink_proto *datalink; - - if (!dev) - goto out; - - /* Check addresses are suitable */ - if (dev->addr_len > IPX_NODE_LEN) - goto out; - - switch (ntohs(dlink_type)) { - case ETH_P_IPX: datalink = pEII_datalink; break; - case ETH_P_802_2: datalink = p8022_datalink; break; - case ETH_P_SNAP: datalink = pSNAP_datalink; break; - case ETH_P_802_3: datalink = p8023_datalink; break; - default: goto out; - } - - intrfc = ipxitf_alloc(dev, 0, dlink_type, datalink, 0, - dev->hard_header_len + datalink->header_length); - - if (intrfc) { - memset(intrfc->if_node, 0, IPX_NODE_LEN); - memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]), - dev->dev_addr, dev->addr_len); - spin_lock_init(&intrfc->if_sklist_lock); - refcount_set(&intrfc->refcnt, 1); - ipxitf_insert(intrfc); - dev_hold(dev); - } - -out: - return intrfc; -} - -static int ipxitf_ioctl(unsigned int cmd, void __user *arg) -{ - int rc = -EINVAL; - struct ifreq ifr; - int val; - - switch (cmd) { - case SIOCSIFADDR: { - struct sockaddr_ipx *sipx; - struct ipx_interface_definition f; - - rc = -EFAULT; - if (copy_from_user(&ifr, arg, sizeof(ifr))) - break; - sipx = (struct sockaddr_ipx *)&ifr.ifr_addr; - rc = -EINVAL; - if (sipx->sipx_family != AF_IPX) - break; - f.ipx_network = sipx->sipx_network; - memcpy(f.ipx_device, ifr.ifr_name, - sizeof(f.ipx_device)); - memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN); - f.ipx_dlink_type = sipx->sipx_type; - f.ipx_special = sipx->sipx_special; - - if (sipx->sipx_action == IPX_DLTITF) - rc = ipxitf_delete(&f); - else - rc = ipxitf_create(&f); - break; - } - case SIOCGIFADDR: { - struct sockaddr_ipx *sipx; - struct ipx_interface *ipxif; - struct net_device *dev; - - rc = -EFAULT; - if (copy_from_user(&ifr, arg, sizeof(ifr))) - break; - sipx = (struct sockaddr_ipx *)&ifr.ifr_addr; - dev = __dev_get_by_name(&init_net, ifr.ifr_name); - rc = -ENODEV; - if (!dev) - break; - ipxif = ipxitf_find_using_phys(dev, - ipx_map_frame_type(sipx->sipx_type)); - rc = -EADDRNOTAVAIL; - if (!ipxif) - break; - - sipx->sipx_family = AF_IPX; - sipx->sipx_network = ipxif->if_netnum; - memcpy(sipx->sipx_node, ipxif->if_node, - sizeof(sipx->sipx_node)); - rc = 0; - if (copy_to_user(arg, &ifr, sizeof(ifr))) - rc = -EFAULT; - ipxitf_put(ipxif); - break; - } - case SIOCAIPXITFCRT: - rc = -EFAULT; - if (get_user(val, (unsigned char __user *) arg)) - break; - rc = 0; - ipxcfg_auto_create_interfaces = val; - break; - case SIOCAIPXPRISLT: - rc = -EFAULT; - if (get_user(val, (unsigned char __user *) arg)) - break; - rc = 0; - ipxcfg_set_auto_select(val); - break; - } - - return rc; -} - -/* - * Checksum routine for IPX - */ - -/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */ -/* This functions should *not* mess with packet contents */ - -__be16 ipx_cksum(struct ipxhdr *packet, int length) -{ - /* - * NOTE: sum is a net byte order quantity, which optimizes the - * loop. This only works on big and little endian machines. (I - * don't know of a machine that isn't.) - */ - /* handle the first 3 words separately; checksum should be skipped - * and ipx_tctrl masked out */ - __u16 *p = (__u16 *)packet; - __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff)); - __u32 i = (length >> 1) - 3; /* Number of remaining complete words */ - - /* Loop through them */ - p += 3; - while (i--) - sum += *p++; - - /* Add on the last part word if it exists */ - if (packet->ipx_pktsize & htons(1)) - sum += (__force u16)htons(0xff00) & *p; - - /* Do final fixup */ - sum = (sum & 0xffff) + (sum >> 16); - - /* It's a pity there's no concept of carry in C */ - if (sum >= 0x10000) - sum++; - - /* - * Leave 0 alone; we don't want 0xffff here. Note that we can't get - * here with 0x10000, so this check is the same as ((__u16)sum) - */ - if (sum) - sum = ~sum; - - return (__force __be16)sum; -} - -const char *ipx_frame_name(__be16 frame) -{ - char* rc = "None"; - - switch (ntohs(frame)) { - case ETH_P_IPX: rc = "EtherII"; break; - case ETH_P_802_2: rc = "802.2"; break; - case ETH_P_SNAP: rc = "SNAP"; break; - case ETH_P_802_3: rc = "802.3"; break; - } - - return rc; -} - -const char *ipx_device_name(struct ipx_interface *intrfc) -{ - return intrfc->if_internal ? "Internal" : - intrfc->if_dev ? intrfc->if_dev->name : "Unknown"; -} - -/* Handling for system calls applied via the various interfaces to an IPX - * socket object. */ - -static int ipx_setsockopt(struct socket *sock, int level, int optname, - char __user *optval, unsigned int optlen) -{ - struct sock *sk = sock->sk; - int opt; - int rc = -EINVAL; - - lock_sock(sk); - if (optlen != sizeof(int)) - goto out; - - rc = -EFAULT; - if (get_user(opt, (unsigned int __user *)optval)) - goto out; - - rc = -ENOPROTOOPT; - if (!(level == SOL_IPX && optname == IPX_TYPE)) - goto out; - - ipx_sk(sk)->type = opt; - rc = 0; -out: - release_sock(sk); - return rc; -} - -static int ipx_getsockopt(struct socket *sock, int level, int optname, - char __user *optval, int __user *optlen) -{ - struct sock *sk = sock->sk; - int val = 0; - int len; - int rc = -ENOPROTOOPT; - - lock_sock(sk); - if (!(level == SOL_IPX && optname == IPX_TYPE)) - goto out; - - val = ipx_sk(sk)->type; - - rc = -EFAULT; - if (get_user(len, optlen)) - goto out; - - len = min_t(unsigned int, len, sizeof(int)); - rc = -EINVAL; - if(len < 0) - goto out; - - rc = -EFAULT; - if (put_user(len, optlen) || copy_to_user(optval, &val, len)) - goto out; - - rc = 0; -out: - release_sock(sk); - return rc; -} - -static struct proto ipx_proto = { - .name = "IPX", - .owner = THIS_MODULE, - .obj_size = sizeof(struct ipx_sock), -}; - -static int ipx_create(struct net *net, struct socket *sock, int protocol, - int kern) -{ - int rc = -ESOCKTNOSUPPORT; - struct sock *sk; - - if (!net_eq(net, &init_net)) - return -EAFNOSUPPORT; - - /* - * SPX support is not anymore in the kernel sources. If you want to - * ressurrect it, completing it and making it understand shared skbs, - * be fully multithreaded, etc, grab the sources in an early 2.5 kernel - * tree. - */ - if (sock->type != SOCK_DGRAM) - goto out; - - rc = -ENOMEM; - sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, kern); - if (!sk) - goto out; - - sk_refcnt_debug_inc(sk); - sock_init_data(sock, sk); - sk->sk_no_check_tx = 1; /* Checksum off by default */ - sock->ops = &ipx_dgram_ops; - rc = 0; -out: - return rc; -} - -static int ipx_release(struct socket *sock) -{ - struct sock *sk = sock->sk; - - if (!sk) - goto out; - - lock_sock(sk); - sk->sk_shutdown = SHUTDOWN_MASK; - if (!sock_flag(sk, SOCK_DEAD)) - sk->sk_state_change(sk); - - sock_set_flag(sk, SOCK_DEAD); - sock->sk = NULL; - sk_refcnt_debug_release(sk); - ipx_destroy_socket(sk); - release_sock(sk); - sock_put(sk); -out: - return 0; -} - -/* caller must hold a reference to intrfc */ - -static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc) -{ - unsigned short socketNum = intrfc->if_sknum; - - spin_lock_bh(&intrfc->if_sklist_lock); - - if (socketNum < IPX_MIN_EPHEMERAL_SOCKET) - socketNum = IPX_MIN_EPHEMERAL_SOCKET; - - while (__ipxitf_find_socket(intrfc, htons(socketNum))) - if (socketNum > IPX_MAX_EPHEMERAL_SOCKET) - socketNum = IPX_MIN_EPHEMERAL_SOCKET; - else - socketNum++; - - spin_unlock_bh(&intrfc->if_sklist_lock); - intrfc->if_sknum = socketNum; - - return htons(socketNum); -} - -static int __ipx_bind(struct socket *sock, - struct sockaddr *uaddr, int addr_len) -{ - struct sock *sk = sock->sk; - struct ipx_sock *ipxs = ipx_sk(sk); - struct ipx_interface *intrfc; - struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr; - int rc = -EINVAL; - - if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_ipx)) - goto out; - - intrfc = ipxitf_find_using_net(addr->sipx_network); - rc = -EADDRNOTAVAIL; - if (!intrfc) - goto out; - - if (!addr->sipx_port) { - addr->sipx_port = ipx_first_free_socketnum(intrfc); - rc = -EINVAL; - if (!addr->sipx_port) - goto out_put; - } - - /* protect IPX system stuff like routing/sap */ - rc = -EACCES; - if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET && - !capable(CAP_NET_ADMIN)) - goto out_put; - - ipxs->port = addr->sipx_port; - -#ifdef CONFIG_IPX_INTERN - if (intrfc == ipx_internal_net) { - /* The source address is to be set explicitly if the - * socket is to be bound on the internal network. If a - * node number 0 was specified, the default is used. - */ - - rc = -EINVAL; - if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN)) - goto out_put; - if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN)) - memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN); - else - memcpy(ipxs->node, addr->sipx_node, IPX_NODE_LEN); - - rc = -EADDRINUSE; - if (ipxitf_find_internal_socket(intrfc, ipxs->node, - ipxs->port)) { - SOCK_DEBUG(sk, - "IPX: bind failed because port %X in use.\n", - ntohs(addr->sipx_port)); - goto out_put; - } - } else { - /* Source addresses are easy. It must be our - * network:node pair for an interface routed to IPX - * with the ipx routing ioctl() - */ - - memcpy(ipxs->node, intrfc->if_node, IPX_NODE_LEN); - - rc = -EADDRINUSE; - if (ipxitf_find_socket(intrfc, addr->sipx_port)) { - SOCK_DEBUG(sk, - "IPX: bind failed because port %X in use.\n", - ntohs(addr->sipx_port)); - goto out_put; - } - } - -#else /* !def CONFIG_IPX_INTERN */ - - /* Source addresses are easy. It must be our network:node pair for - an interface routed to IPX with the ipx routing ioctl() */ - - rc = -EADDRINUSE; - if (ipxitf_find_socket(intrfc, addr->sipx_port)) { - SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", - ntohs((int)addr->sipx_port)); - goto out_put; - } - -#endif /* CONFIG_IPX_INTERN */ - - ipxitf_insert_socket(intrfc, sk); - sock_reset_flag(sk, SOCK_ZAPPED); - - rc = 0; -out_put: - ipxitf_put(intrfc); -out: - return rc; -} - -static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) -{ - struct sock *sk = sock->sk; - int rc; - - lock_sock(sk); - rc = __ipx_bind(sock, uaddr, addr_len); - release_sock(sk); - - return rc; -} - -static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, - int addr_len, int flags) -{ - struct sock *sk = sock->sk; - struct ipx_sock *ipxs = ipx_sk(sk); - struct sockaddr_ipx *addr; - int rc = -EINVAL; - struct ipx_route *rt; - - sk->sk_state = TCP_CLOSE; - sock->state = SS_UNCONNECTED; - - lock_sock(sk); - if (addr_len != sizeof(*addr)) - goto out; - addr = (struct sockaddr_ipx *)uaddr; - - /* put the autobinding in */ - if (!ipxs->port) { - struct sockaddr_ipx uaddr; - - uaddr.sipx_port = 0; - uaddr.sipx_network = 0; - -#ifdef CONFIG_IPX_INTERN - rc = -ENETDOWN; - if (!ipxs->intrfc) - goto out; /* Someone zonked the iface */ - memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, - IPX_NODE_LEN); -#endif /* CONFIG_IPX_INTERN */ - - rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, - sizeof(struct sockaddr_ipx)); - if (rc) - goto out; - } - - /* We can either connect to primary network or somewhere - * we can route to */ - rt = ipxrtr_lookup(addr->sipx_network); - rc = -ENETUNREACH; - if (!rt && !(!addr->sipx_network && ipx_primary_net)) - goto out; - - ipxs->dest_addr.net = addr->sipx_network; - ipxs->dest_addr.sock = addr->sipx_port; - memcpy(ipxs->dest_addr.node, addr->sipx_node, IPX_NODE_LEN); - ipxs->type = addr->sipx_type; - - if (sock->type == SOCK_DGRAM) { - sock->state = SS_CONNECTED; - sk->sk_state = TCP_ESTABLISHED; - } - - if (rt) - ipxrtr_put(rt); - rc = 0; -out: - release_sock(sk); - return rc; -} - - -static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, - int *uaddr_len, int peer) -{ - struct ipx_address *addr; - struct sockaddr_ipx sipx; - struct sock *sk = sock->sk; - struct ipx_sock *ipxs = ipx_sk(sk); - int rc; - - *uaddr_len = sizeof(struct sockaddr_ipx); - - lock_sock(sk); - if (peer) { - rc = -ENOTCONN; - if (sk->sk_state != TCP_ESTABLISHED) - goto out; - - addr = &ipxs->dest_addr; - sipx.sipx_network = addr->net; - sipx.sipx_port = addr->sock; - memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN); - } else { - if (ipxs->intrfc) { - sipx.sipx_network = ipxs->intrfc->if_netnum; -#ifdef CONFIG_IPX_INTERN - memcpy(sipx.sipx_node, ipxs->node, IPX_NODE_LEN); -#else - memcpy(sipx.sipx_node, ipxs->intrfc->if_node, - IPX_NODE_LEN); -#endif /* CONFIG_IPX_INTERN */ - - } else { - sipx.sipx_network = 0; - memset(sipx.sipx_node, '\0', IPX_NODE_LEN); - } - - sipx.sipx_port = ipxs->port; - } - - sipx.sipx_family = AF_IPX; - sipx.sipx_type = ipxs->type; - sipx.sipx_zero = 0; - memcpy(uaddr, &sipx, sizeof(sipx)); - - rc = 0; -out: - release_sock(sk); - return rc; -} - -static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) -{ - /* NULL here for pt means the packet was looped back */ - struct ipx_interface *intrfc; - struct ipxhdr *ipx; - u16 ipx_pktsize; - int rc = 0; - - if (!net_eq(dev_net(dev), &init_net)) - goto drop; - - /* Not ours */ - if (skb->pkt_type == PACKET_OTHERHOST) - goto drop; - - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) - goto out; - - if (!pskb_may_pull(skb, sizeof(struct ipxhdr))) - goto drop; - - ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); - - /* Too small or invalid header? */ - if (ipx_pktsize < sizeof(struct ipxhdr) || - !pskb_may_pull(skb, ipx_pktsize)) - goto drop; - - ipx = ipx_hdr(skb); - if (ipx->ipx_checksum != IPX_NO_CHECKSUM && - ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) - goto drop; - - IPX_SKB_CB(skb)->ipx_tctrl = ipx->ipx_tctrl; - IPX_SKB_CB(skb)->ipx_dest_net = ipx->ipx_dest.net; - IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net; - - /* Determine what local ipx endpoint this is */ - intrfc = ipxitf_find_using_phys(dev, pt->type); - if (!intrfc) { - if (ipxcfg_auto_create_interfaces && - IPX_SKB_CB(skb)->ipx_dest_net) { - intrfc = ipxitf_auto_create(dev, pt->type); - if (intrfc) - ipxitf_hold(intrfc); - } - - if (!intrfc) /* Not one of ours */ - /* or invalid packet for auto creation */ - goto drop; - } - - rc = ipxitf_rcv(intrfc, skb); - ipxitf_put(intrfc); - goto out; -drop: - kfree_skb(skb); -out: - return rc; -} - -static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) -{ - struct sock *sk = sock->sk; - struct ipx_sock *ipxs = ipx_sk(sk); - DECLARE_SOCKADDR(struct sockaddr_ipx *, usipx, msg->msg_name); - struct sockaddr_ipx local_sipx; - int rc = -EINVAL; - int flags = msg->msg_flags; - - lock_sock(sk); - /* Socket gets bound below anyway */ -/* if (sk->sk_zapped) - return -EIO; */ /* Socket not bound */ - if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) - goto out; - - /* Max possible packet size limited by 16 bit pktsize in header */ - if (len >= 65535 - sizeof(struct ipxhdr)) - goto out; - - if (usipx) { - if (!ipxs->port) { - struct sockaddr_ipx uaddr; - - uaddr.sipx_port = 0; - uaddr.sipx_network = 0; -#ifdef CONFIG_IPX_INTERN - rc = -ENETDOWN; - if (!ipxs->intrfc) - goto out; /* Someone zonked the iface */ - memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, - IPX_NODE_LEN); -#endif - rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, - sizeof(struct sockaddr_ipx)); - if (rc) - goto out; - } - - rc = -EINVAL; - if (msg->msg_namelen < sizeof(*usipx) || - usipx->sipx_family != AF_IPX) - goto out; - } else { - rc = -ENOTCONN; - if (sk->sk_state != TCP_ESTABLISHED) - goto out; - - usipx = &local_sipx; - usipx->sipx_family = AF_IPX; - usipx->sipx_type = ipxs->type; - usipx->sipx_port = ipxs->dest_addr.sock; - usipx->sipx_network = ipxs->dest_addr.net; - memcpy(usipx->sipx_node, ipxs->dest_addr.node, IPX_NODE_LEN); - } - - rc = ipxrtr_route_packet(sk, usipx, msg, len, flags & MSG_DONTWAIT); - if (rc >= 0) - rc = len; -out: - release_sock(sk); - return rc; -} - - -static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, - int flags) -{ - struct sock *sk = sock->sk; - struct ipx_sock *ipxs = ipx_sk(sk); - DECLARE_SOCKADDR(struct sockaddr_ipx *, sipx, msg->msg_name); - struct ipxhdr *ipx = NULL; - struct sk_buff *skb; - int copied, rc; - bool locked = true; - - lock_sock(sk); - /* put the autobinding in */ - if (!ipxs->port) { - struct sockaddr_ipx uaddr; - - uaddr.sipx_port = 0; - uaddr.sipx_network = 0; - -#ifdef CONFIG_IPX_INTERN - rc = -ENETDOWN; - if (!ipxs->intrfc) - goto out; /* Someone zonked the iface */ - memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN); -#endif /* CONFIG_IPX_INTERN */ - - rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, - sizeof(struct sockaddr_ipx)); - if (rc) - goto out; - } - - rc = -ENOTCONN; - if (sock_flag(sk, SOCK_ZAPPED)) - goto out; - - release_sock(sk); - locked = false; - skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, - flags & MSG_DONTWAIT, &rc); - if (!skb) { - if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN)) - rc = 0; - goto out; - } - - ipx = ipx_hdr(skb); - copied = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr); - if (copied > size) { - copied = size; - msg->msg_flags |= MSG_TRUNC; - } - - rc = skb_copy_datagram_msg(skb, sizeof(struct ipxhdr), msg, copied); - if (rc) - goto out_free; - if (skb->tstamp) - sk->sk_stamp = skb->tstamp; - - if (sipx) { - sipx->sipx_family = AF_IPX; - sipx->sipx_port = ipx->ipx_source.sock; - memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN); - sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net; - sipx->sipx_type = ipx->ipx_type; - sipx->sipx_zero = 0; - msg->msg_namelen = sizeof(*sipx); - } - rc = copied; - -out_free: - skb_free_datagram(sk, skb); -out: - if (locked) - release_sock(sk); - return rc; -} - - -static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - int rc = 0; - long amount = 0; - struct sock *sk = sock->sk; - void __user *argp = (void __user *)arg; - - lock_sock(sk); - switch (cmd) { - case TIOCOUTQ: - amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); - if (amount < 0) - amount = 0; - rc = put_user(amount, (int __user *)argp); - break; - case TIOCINQ: { - struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); - /* These two are safe on a single CPU system as only - * user tasks fiddle here */ - if (skb) - amount = skb->len - sizeof(struct ipxhdr); - rc = put_user(amount, (int __user *)argp); - break; - } - case SIOCADDRT: - case SIOCDELRT: - rc = -EPERM; - if (capable(CAP_NET_ADMIN)) - rc = ipxrtr_ioctl(cmd, argp); - break; - case SIOCSIFADDR: - case SIOCAIPXITFCRT: - case SIOCAIPXPRISLT: - rc = -EPERM; - if (!capable(CAP_NET_ADMIN)) - break; - /* fall through */ - case SIOCGIFADDR: - rc = ipxitf_ioctl(cmd, argp); - break; - case SIOCIPXCFGDATA: - rc = ipxcfg_get_config_data(argp); - break; - case SIOCIPXNCPCONN: - /* - * This socket wants to take care of the NCP connection - * handed to us in arg. - */ - rc = -EPERM; - if (!capable(CAP_NET_ADMIN)) - break; - rc = get_user(ipx_sk(sk)->ipx_ncp_conn, - (const unsigned short __user *)argp); - break; - case SIOCGSTAMP: - rc = sock_get_timestamp(sk, argp); - break; - case SIOCGIFDSTADDR: - case SIOCSIFDSTADDR: - case SIOCGIFBRDADDR: - case SIOCSIFBRDADDR: - case SIOCGIFNETMASK: - case SIOCSIFNETMASK: - rc = -EINVAL; - break; - default: - rc = -ENOIOCTLCMD; - break; - } - release_sock(sk); - - return rc; -} - - -#ifdef CONFIG_COMPAT -static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - /* - * These 4 commands use same structure on 32bit and 64bit. Rest of IPX - * commands is handled by generic ioctl code. As these commands are - * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic - * code. - */ - switch (cmd) { - case SIOCAIPXITFCRT: - case SIOCAIPXPRISLT: - case SIOCIPXCFGDATA: - case SIOCIPXNCPCONN: - return ipx_ioctl(sock, cmd, arg); - default: - return -ENOIOCTLCMD; - } -} -#endif - -static int ipx_shutdown(struct socket *sock, int mode) -{ - struct sock *sk = sock->sk; - - if (mode < SHUT_RD || mode > SHUT_RDWR) - return -EINVAL; - /* This maps: - * SHUT_RD (0) -> RCV_SHUTDOWN (1) - * SHUT_WR (1) -> SEND_SHUTDOWN (2) - * SHUT_RDWR (2) -> SHUTDOWN_MASK (3) - */ - ++mode; - - lock_sock(sk); - sk->sk_shutdown |= mode; - release_sock(sk); - sk->sk_state_change(sk); - - return 0; -} - -/* - * Socket family declarations - */ - -static const struct net_proto_family ipx_family_ops = { - .family = PF_IPX, - .create = ipx_create, - .owner = THIS_MODULE, -}; - -static const struct proto_ops ipx_dgram_ops = { - .family = PF_IPX, - .owner = THIS_MODULE, - .release = ipx_release, - .bind = ipx_bind, - .connect = ipx_connect, - .socketpair = sock_no_socketpair, - .accept = sock_no_accept, - .getname = ipx_getname, - .poll = datagram_poll, - .ioctl = ipx_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ipx_compat_ioctl, -#endif - .listen = sock_no_listen, - .shutdown = ipx_shutdown, - .setsockopt = ipx_setsockopt, - .getsockopt = ipx_getsockopt, - .sendmsg = ipx_sendmsg, - .recvmsg = ipx_recvmsg, - .mmap = sock_no_mmap, - .sendpage = sock_no_sendpage, -}; - -static struct packet_type ipx_8023_packet_type __read_mostly = { - .type = cpu_to_be16(ETH_P_802_3), - .func = ipx_rcv, -}; - -static struct packet_type ipx_dix_packet_type __read_mostly = { - .type = cpu_to_be16(ETH_P_IPX), - .func = ipx_rcv, -}; - -static struct notifier_block ipx_dev_notifier = { - .notifier_call = ipxitf_device_event, -}; - -static const unsigned char ipx_8022_type = 0xE0; -static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; -static const char ipx_EII_err_msg[] __initconst = - KERN_CRIT "IPX: Unable to register with Ethernet II\n"; -static const char ipx_8023_err_msg[] __initconst = - KERN_CRIT "IPX: Unable to register with 802.3\n"; -static const char ipx_llc_err_msg[] __initconst = - KERN_CRIT "IPX: Unable to register with 802.2\n"; -static const char ipx_snap_err_msg[] __initconst = - KERN_CRIT "IPX: Unable to register with SNAP\n"; - -static int __init ipx_init(void) -{ - int rc = proto_register(&ipx_proto, 1); - - if (rc != 0) - goto out; - - sock_register(&ipx_family_ops); - - pEII_datalink = make_EII_client(); - if (pEII_datalink) - dev_add_pack(&ipx_dix_packet_type); - else - printk(ipx_EII_err_msg); - - p8023_datalink = make_8023_client(); - if (p8023_datalink) - dev_add_pack(&ipx_8023_packet_type); - else - printk(ipx_8023_err_msg); - - p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv); - if (!p8022_datalink) - printk(ipx_llc_err_msg); - - pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv); - if (!pSNAP_datalink) - printk(ipx_snap_err_msg); - - register_netdevice_notifier(&ipx_dev_notifier); - ipx_register_sysctl(); - ipx_proc_init(); -out: - return rc; -} - -static void __exit ipx_proto_finito(void) -{ - ipx_proc_exit(); - ipx_unregister_sysctl(); - - unregister_netdevice_notifier(&ipx_dev_notifier); - - ipxitf_cleanup(); - - if (pSNAP_datalink) { - unregister_snap_client(pSNAP_datalink); - pSNAP_datalink = NULL; - } - - if (p8022_datalink) { - unregister_8022_client(p8022_datalink); - p8022_datalink = NULL; - } - - dev_remove_pack(&ipx_8023_packet_type); - if (p8023_datalink) { - destroy_8023_client(p8023_datalink); - p8023_datalink = NULL; - } - - dev_remove_pack(&ipx_dix_packet_type); - if (pEII_datalink) { - destroy_EII_client(pEII_datalink); - pEII_datalink = NULL; - } - - proto_unregister(&ipx_proto); - sock_unregister(ipx_family_ops.family); -} - -module_init(ipx_init); -module_exit(ipx_proto_finito); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_NETPROTO(PF_IPX); diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c deleted file mode 100644 index 38a3d51d9ead..000000000000 --- a/net/ipx/ipx_proc.c +++ /dev/null @@ -1,341 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * IPX proc routines - * - * Copyright(C) Arnaldo Carvalho de Melo , 2002 - */ - -#include -#ifdef CONFIG_PROC_FS -#include -#include -#include -#include -#include -#include -#include - -static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) -{ - spin_lock_bh(&ipx_interfaces_lock); - return seq_list_start_head(&ipx_interfaces, *pos); -} - -static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) -{ - return seq_list_next(v, &ipx_interfaces, pos); -} - -static void ipx_seq_interface_stop(struct seq_file *seq, void *v) -{ - spin_unlock_bh(&ipx_interfaces_lock); -} - -static int ipx_seq_interface_show(struct seq_file *seq, void *v) -{ - struct ipx_interface *i; - - if (v == &ipx_interfaces) { - seq_puts(seq, "Network Node_Address Primary Device " - "Frame_Type"); -#ifdef IPX_REFCNT_DEBUG - seq_puts(seq, " refcnt"); -#endif - seq_puts(seq, "\n"); - goto out; - } - - i = list_entry(v, struct ipx_interface, node); - seq_printf(seq, "%08X ", ntohl(i->if_netnum)); - seq_printf(seq, "%02X%02X%02X%02X%02X%02X ", - i->if_node[0], i->if_node[1], i->if_node[2], - i->if_node[3], i->if_node[4], i->if_node[5]); - seq_printf(seq, "%-9s", i == ipx_primary_net ? "Yes" : "No"); - seq_printf(seq, "%-11s", ipx_device_name(i)); - seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type)); -#ifdef IPX_REFCNT_DEBUG - seq_printf(seq, "%6d", refcount_read(&i->refcnt)); -#endif - seq_puts(seq, "\n"); -out: - return 0; -} - -static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos) -{ - read_lock_bh(&ipx_routes_lock); - return seq_list_start_head(&ipx_routes, *pos); -} - -static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) -{ - return seq_list_next(v, &ipx_routes, pos); -} - -static void ipx_seq_route_stop(struct seq_file *seq, void *v) -{ - read_unlock_bh(&ipx_routes_lock); -} - -static int ipx_seq_route_show(struct seq_file *seq, void *v) -{ - struct ipx_route *rt; - - if (v == &ipx_routes) { - seq_puts(seq, "Network Router_Net Router_Node\n"); - goto out; - } - - rt = list_entry(v, struct ipx_route, node); - - seq_printf(seq, "%08X ", ntohl(rt->ir_net)); - if (rt->ir_routed) - seq_printf(seq, "%08X %02X%02X%02X%02X%02X%02X\n", - ntohl(rt->ir_intrfc->if_netnum), - rt->ir_router_node[0], rt->ir_router_node[1], - rt->ir_router_node[2], rt->ir_router_node[3], - rt->ir_router_node[4], rt->ir_router_node[5]); - else - seq_puts(seq, "Directly Connected\n"); -out: - return 0; -} - -static __inline__ struct sock *ipx_get_socket_idx(loff_t pos) -{ - struct sock *s = NULL; - struct ipx_interface *i; - - list_for_each_entry(i, &ipx_interfaces, node) { - spin_lock_bh(&i->if_sklist_lock); - sk_for_each(s, &i->if_sklist) { - if (!pos) - break; - --pos; - } - spin_unlock_bh(&i->if_sklist_lock); - if (!pos) { - if (s) - goto found; - break; - } - } - s = NULL; -found: - return s; -} - -static void *ipx_seq_socket_start(struct seq_file *seq, loff_t *pos) -{ - loff_t l = *pos; - - spin_lock_bh(&ipx_interfaces_lock); - return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN; -} - -static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) -{ - struct sock* sk, *next; - struct ipx_interface *i; - struct ipx_sock *ipxs; - - ++*pos; - if (v == SEQ_START_TOKEN) { - sk = NULL; - i = ipx_interfaces_head(); - if (!i) - goto out; - sk = sk_head(&i->if_sklist); - if (sk) - spin_lock_bh(&i->if_sklist_lock); - goto out; - } - sk = v; - next = sk_next(sk); - if (next) { - sk = next; - goto out; - } - ipxs = ipx_sk(sk); - i = ipxs->intrfc; - spin_unlock_bh(&i->if_sklist_lock); - sk = NULL; - for (;;) { - if (i->node.next == &ipx_interfaces) - break; - i = list_entry(i->node.next, struct ipx_interface, node); - spin_lock_bh(&i->if_sklist_lock); - if (!hlist_empty(&i->if_sklist)) { - sk = sk_head(&i->if_sklist); - break; - } - spin_unlock_bh(&i->if_sklist_lock); - } -out: - return sk; -} - -static int ipx_seq_socket_show(struct seq_file *seq, void *v) -{ - struct sock *s; - struct ipx_sock *ipxs; - - if (v == SEQ_START_TOKEN) { -#ifdef CONFIG_IPX_INTERN - seq_puts(seq, "Local_Address " - "Remote_Address Tx_Queue " - "Rx_Queue State Uid\n"); -#else - seq_puts(seq, "Local_Address Remote_Address " - "Tx_Queue Rx_Queue State Uid\n"); -#endif - goto out; - } - - s = v; - ipxs = ipx_sk(s); -#ifdef CONFIG_IPX_INTERN - seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X ", - ntohl(ipxs->intrfc->if_netnum), - ipxs->node[0], ipxs->node[1], ipxs->node[2], ipxs->node[3], - ipxs->node[4], ipxs->node[5], ntohs(ipxs->port)); -#else - seq_printf(seq, "%08X:%04X ", ntohl(ipxs->intrfc->if_netnum), - ntohs(ipxs->port)); -#endif /* CONFIG_IPX_INTERN */ - if (s->sk_state != TCP_ESTABLISHED) - seq_printf(seq, "%-28s", "Not_Connected"); - else { - seq_printf(seq, "%08X:%02X%02X%02X%02X%02X%02X:%04X ", - ntohl(ipxs->dest_addr.net), - ipxs->dest_addr.node[0], ipxs->dest_addr.node[1], - ipxs->dest_addr.node[2], ipxs->dest_addr.node[3], - ipxs->dest_addr.node[4], ipxs->dest_addr.node[5], - ntohs(ipxs->dest_addr.sock)); - } - - seq_printf(seq, "%08X %08X %02X %03u\n", - sk_wmem_alloc_get(s), - sk_rmem_alloc_get(s), - s->sk_state, - from_kuid_munged(seq_user_ns(seq), sock_i_uid(s))); -out: - return 0; -} - -static const struct seq_operations ipx_seq_interface_ops = { - .start = ipx_seq_interface_start, - .next = ipx_seq_interface_next, - .stop = ipx_seq_interface_stop, - .show = ipx_seq_interface_show, -}; - -static const struct seq_operations ipx_seq_route_ops = { - .start = ipx_seq_route_start, - .next = ipx_seq_route_next, - .stop = ipx_seq_route_stop, - .show = ipx_seq_route_show, -}; - -static const struct seq_operations ipx_seq_socket_ops = { - .start = ipx_seq_socket_start, - .next = ipx_seq_socket_next, - .stop = ipx_seq_interface_stop, - .show = ipx_seq_socket_show, -}; - -static int ipx_seq_route_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &ipx_seq_route_ops); -} - -static int ipx_seq_interface_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &ipx_seq_interface_ops); -} - -static int ipx_seq_socket_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &ipx_seq_socket_ops); -} - -static const struct file_operations ipx_seq_interface_fops = { - .owner = THIS_MODULE, - .open = ipx_seq_interface_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct file_operations ipx_seq_route_fops = { - .owner = THIS_MODULE, - .open = ipx_seq_route_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct file_operations ipx_seq_socket_fops = { - .owner = THIS_MODULE, - .open = ipx_seq_socket_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static struct proc_dir_entry *ipx_proc_dir; - -int __init ipx_proc_init(void) -{ - struct proc_dir_entry *p; - int rc = -ENOMEM; - - ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net); - - if (!ipx_proc_dir) - goto out; - p = proc_create("interface", S_IRUGO, - ipx_proc_dir, &ipx_seq_interface_fops); - if (!p) - goto out_interface; - - p = proc_create("route", S_IRUGO, ipx_proc_dir, &ipx_seq_route_fops); - if (!p) - goto out_route; - - p = proc_create("socket", S_IRUGO, ipx_proc_dir, &ipx_seq_socket_fops); - if (!p) - goto out_socket; - - rc = 0; -out: - return rc; -out_socket: - remove_proc_entry("route", ipx_proc_dir); -out_route: - remove_proc_entry("interface", ipx_proc_dir); -out_interface: - remove_proc_entry("ipx", init_net.proc_net); - goto out; -} - -void __exit ipx_proc_exit(void) -{ - remove_proc_entry("interface", ipx_proc_dir); - remove_proc_entry("route", ipx_proc_dir); - remove_proc_entry("socket", ipx_proc_dir); - remove_proc_entry("ipx", init_net.proc_net); -} - -#else /* CONFIG_PROC_FS */ - -int __init ipx_proc_init(void) -{ - return 0; -} - -void __exit ipx_proc_exit(void) -{ -} - -#endif /* CONFIG_PROC_FS */ diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c deleted file mode 100644 index 3cf93aa9f284..000000000000 --- a/net/ipx/ipx_route.c +++ /dev/null @@ -1,293 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Implements the IPX routing routines. - * Code moved from af_ipx.c. - * - * Arnaldo Carvalho de Melo , 2003 - * - * See net/ipx/ChangeLog. - */ - -#include -#include -#include -#include - -#include -#include - -LIST_HEAD(ipx_routes); -DEFINE_RWLOCK(ipx_routes_lock); - -extern struct ipx_interface *ipx_internal_net; - -extern struct ipx_interface *ipxitf_find_using_net(__be32 net); -extern int ipxitf_demux_socket(struct ipx_interface *intrfc, - struct sk_buff *skb, int copy); -extern int ipxitf_demux_socket(struct ipx_interface *intrfc, - struct sk_buff *skb, int copy); - -struct ipx_route *ipxrtr_lookup(__be32 net) -{ - struct ipx_route *r; - - read_lock_bh(&ipx_routes_lock); - list_for_each_entry(r, &ipx_routes, node) - if (r->ir_net == net) { - ipxrtr_hold(r); - goto unlock; - } - r = NULL; -unlock: - read_unlock_bh(&ipx_routes_lock); - return r; -} - -/* - * Caller must hold a reference to intrfc - */ -int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, - unsigned char *node) -{ - struct ipx_route *rt; - int rc; - - /* Get a route structure; either existing or create */ - rt = ipxrtr_lookup(network); - if (!rt) { - rt = kmalloc(sizeof(*rt), GFP_ATOMIC); - rc = -EAGAIN; - if (!rt) - goto out; - - refcount_set(&rt->refcnt, 1); - ipxrtr_hold(rt); - write_lock_bh(&ipx_routes_lock); - list_add(&rt->node, &ipx_routes); - write_unlock_bh(&ipx_routes_lock); - } else { - rc = -EEXIST; - if (intrfc == ipx_internal_net) - goto out_put; - } - - rt->ir_net = network; - rt->ir_intrfc = intrfc; - if (!node) { - memset(rt->ir_router_node, '\0', IPX_NODE_LEN); - rt->ir_routed = 0; - } else { - memcpy(rt->ir_router_node, node, IPX_NODE_LEN); - rt->ir_routed = 1; - } - - rc = 0; -out_put: - ipxrtr_put(rt); -out: - return rc; -} - -void ipxrtr_del_routes(struct ipx_interface *intrfc) -{ - struct ipx_route *r, *tmp; - - write_lock_bh(&ipx_routes_lock); - list_for_each_entry_safe(r, tmp, &ipx_routes, node) - if (r->ir_intrfc == intrfc) { - list_del(&r->node); - ipxrtr_put(r); - } - write_unlock_bh(&ipx_routes_lock); -} - -static int ipxrtr_create(struct ipx_route_definition *rd) -{ - struct ipx_interface *intrfc; - int rc = -ENETUNREACH; - - /* Find the appropriate interface */ - intrfc = ipxitf_find_using_net(rd->ipx_router_network); - if (!intrfc) - goto out; - rc = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node); - ipxitf_put(intrfc); -out: - return rc; -} - -static int ipxrtr_delete(__be32 net) -{ - struct ipx_route *r, *tmp; - int rc; - - write_lock_bh(&ipx_routes_lock); - list_for_each_entry_safe(r, tmp, &ipx_routes, node) - if (r->ir_net == net) { - /* Directly connected; can't lose route */ - rc = -EPERM; - if (!r->ir_routed) - goto out; - list_del(&r->node); - ipxrtr_put(r); - rc = 0; - goto out; - } - rc = -ENOENT; -out: - write_unlock_bh(&ipx_routes_lock); - return rc; -} - -/* - * The skb has to be unshared, we'll end up calling ipxitf_send, that'll - * modify the packet - */ -int ipxrtr_route_skb(struct sk_buff *skb) -{ - struct ipxhdr *ipx = ipx_hdr(skb); - struct ipx_route *r = ipxrtr_lookup(IPX_SKB_CB(skb)->ipx_dest_net); - - if (!r) { /* no known route */ - kfree_skb(skb); - return 0; - } - - ipxitf_hold(r->ir_intrfc); - ipxitf_send(r->ir_intrfc, skb, r->ir_routed ? - r->ir_router_node : ipx->ipx_dest.node); - ipxitf_put(r->ir_intrfc); - ipxrtr_put(r); - - return 0; -} - -/* - * Route an outgoing frame from a socket. - */ -int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, - struct msghdr *msg, size_t len, int noblock) -{ - struct sk_buff *skb; - struct ipx_sock *ipxs = ipx_sk(sk); - struct ipx_interface *intrfc; - struct ipxhdr *ipx; - size_t size; - int ipx_offset; - struct ipx_route *rt = NULL; - int rc; - - /* Find the appropriate interface on which to send packet */ - if (!usipx->sipx_network && ipx_primary_net) { - usipx->sipx_network = ipx_primary_net->if_netnum; - intrfc = ipx_primary_net; - } else { - rt = ipxrtr_lookup(usipx->sipx_network); - rc = -ENETUNREACH; - if (!rt) - goto out; - intrfc = rt->ir_intrfc; - } - - ipxitf_hold(intrfc); - ipx_offset = intrfc->if_ipx_offset; - size = sizeof(struct ipxhdr) + len + ipx_offset; - - skb = sock_alloc_send_skb(sk, size, noblock, &rc); - if (!skb) - goto out_put; - - skb_reserve(skb, ipx_offset); - skb->sk = sk; - - /* Fill in IPX header */ - skb_reset_network_header(skb); - skb_reset_transport_header(skb); - skb_put(skb, sizeof(struct ipxhdr)); - ipx = ipx_hdr(skb); - ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr)); - IPX_SKB_CB(skb)->ipx_tctrl = 0; - ipx->ipx_type = usipx->sipx_type; - - IPX_SKB_CB(skb)->last_hop.index = -1; -#ifdef CONFIG_IPX_INTERN - IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum; - memcpy(ipx->ipx_source.node, ipxs->node, IPX_NODE_LEN); -#else - rc = ntohs(ipxs->port); - if (rc == 0x453 || rc == 0x452) { - /* RIP/SAP special handling for mars_nwe */ - IPX_SKB_CB(skb)->ipx_source_net = intrfc->if_netnum; - memcpy(ipx->ipx_source.node, intrfc->if_node, IPX_NODE_LEN); - } else { - IPX_SKB_CB(skb)->ipx_source_net = ipxs->intrfc->if_netnum; - memcpy(ipx->ipx_source.node, ipxs->intrfc->if_node, - IPX_NODE_LEN); - } -#endif /* CONFIG_IPX_INTERN */ - ipx->ipx_source.sock = ipxs->port; - IPX_SKB_CB(skb)->ipx_dest_net = usipx->sipx_network; - memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN); - ipx->ipx_dest.sock = usipx->sipx_port; - - rc = memcpy_from_msg(skb_put(skb, len), msg, len); - if (rc) { - kfree_skb(skb); - goto out_put; - } - - /* Apply checksum. Not allowed on 802.3 links. */ - if (sk->sk_no_check_tx || - intrfc->if_dlink_type == htons(IPX_FRAME_8023)) - ipx->ipx_checksum = htons(0xFFFF); - else - ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr)); - - rc = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ? - rt->ir_router_node : ipx->ipx_dest.node); -out_put: - ipxitf_put(intrfc); - if (rt) - ipxrtr_put(rt); -out: - return rc; -} - -/* - * We use a normal struct rtentry for route handling - */ -int ipxrtr_ioctl(unsigned int cmd, void __user *arg) -{ - struct rtentry rt; /* Use these to behave like 'other' stacks */ - struct sockaddr_ipx *sg, *st; - int rc = -EFAULT; - - if (copy_from_user(&rt, arg, sizeof(rt))) - goto out; - - sg = (struct sockaddr_ipx *)&rt.rt_gateway; - st = (struct sockaddr_ipx *)&rt.rt_dst; - - rc = -EINVAL; - if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */ - sg->sipx_family != AF_IPX || - st->sipx_family != AF_IPX) - goto out; - - switch (cmd) { - case SIOCDELRT: - rc = ipxrtr_delete(st->sipx_network); - break; - case SIOCADDRT: { - struct ipx_route_definition f; - f.ipx_network = st->sipx_network; - f.ipx_router_network = sg->sipx_network; - memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN); - rc = ipxrtr_create(&f); - break; - } - } - -out: - return rc; -} diff --git a/net/ipx/pe2.c b/net/ipx/pe2.c deleted file mode 100644 index ba7d4214bbff..000000000000 --- a/net/ipx/pe2.c +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include - -#include - -static int pEII_request(struct datalink_proto *dl, - struct sk_buff *skb, unsigned char *dest_node) -{ - struct net_device *dev = skb->dev; - - skb->protocol = htons(ETH_P_IPX); - dev_hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len); - return dev_queue_xmit(skb); -} - -struct datalink_proto *make_EII_client(void) -{ - struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC); - - if (proto) { - proto->header_length = 0; - proto->request = pEII_request; - } - - return proto; -} - -void destroy_EII_client(struct datalink_proto *dl) -{ - kfree(dl); -} diff --git a/net/ipx/sysctl_net_ipx.c b/net/ipx/sysctl_net_ipx.c deleted file mode 100644 index c3eef457db88..000000000000 --- a/net/ipx/sysctl_net_ipx.c +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* -*- linux-c -*- - * sysctl_net_ipx.c: sysctl interface to net IPX subsystem. - * - * Begun April 1, 1996, Mike Shaver. - * Added /proc/sys/net/ipx directory entry (empty =) ). [MS] - * Added /proc/sys/net/ipx/ipx_pprop_broadcasting - acme March 4, 2001 - */ - -#include -#include -#include -#include - -#ifndef CONFIG_SYSCTL -#error This file should not be compiled without CONFIG_SYSCTL defined -#endif - -static struct ctl_table ipx_table[] = { - { - .procname = "ipx_pprop_broadcasting", - .data = &sysctl_ipx_pprop_broadcasting, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec, - }, - { }, -}; - -static struct ctl_table_header *ipx_table_header; - -void ipx_register_sysctl(void) -{ - ipx_table_header = register_net_sysctl(&init_net, "net/ipx", ipx_table); -} - -void ipx_unregister_sysctl(void) -{ - unregister_net_sysctl_table(ipx_table_header); -} -- cgit v1.2.3 From 1bb8155080c652c4853e6228f8f0d262b3049699 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 14 Nov 2017 08:37:15 -0800 Subject: ncpfs: move net/ncpfs to drivers/staging/ncpfs The Netware Core Protocol is a file system that talks to Netware clients over IPX. Since IPX has been dead for many years move the file system into staging for eventual interment. Signed-off-by: Stephen Hemminger Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/ncpfs/Kconfig | 108 +++ drivers/staging/ncpfs/Makefile | 17 + drivers/staging/ncpfs/TODO | 4 + drivers/staging/ncpfs/dir.c | 1232 +++++++++++++++++++++++++++++ drivers/staging/ncpfs/file.c | 263 +++++++ drivers/staging/ncpfs/getopt.c | 76 ++ drivers/staging/ncpfs/getopt.h | 17 + drivers/staging/ncpfs/inode.c | 1066 +++++++++++++++++++++++++ drivers/staging/ncpfs/ioctl.c | 923 ++++++++++++++++++++++ drivers/staging/ncpfs/mmap.c | 125 +++ drivers/staging/ncpfs/ncp_fs.h | 101 +++ drivers/staging/ncpfs/ncp_fs_i.h | 31 + drivers/staging/ncpfs/ncp_fs_sb.h | 174 +++++ drivers/staging/ncpfs/ncplib_kernel.c | 1322 ++++++++++++++++++++++++++++++++ drivers/staging/ncpfs/ncplib_kernel.h | 215 ++++++ drivers/staging/ncpfs/ncpsign_kernel.c | 128 ++++ drivers/staging/ncpfs/ncpsign_kernel.h | 27 + drivers/staging/ncpfs/sock.c | 854 +++++++++++++++++++++ drivers/staging/ncpfs/symlink.c | 182 +++++ fs/Kconfig | 1 - fs/Makefile | 1 - fs/ncpfs/Kconfig | 108 --- fs/ncpfs/Makefile | 17 - fs/ncpfs/dir.c | 1232 ----------------------------- fs/ncpfs/file.c | 263 ------- fs/ncpfs/getopt.c | 76 -- fs/ncpfs/getopt.h | 17 - fs/ncpfs/inode.c | 1066 ------------------------- fs/ncpfs/ioctl.c | 923 ---------------------- fs/ncpfs/mmap.c | 125 --- fs/ncpfs/ncp_fs.h | 101 --- fs/ncpfs/ncp_fs_i.h | 31 - fs/ncpfs/ncp_fs_sb.h | 174 ----- fs/ncpfs/ncplib_kernel.c | 1322 -------------------------------- fs/ncpfs/ncplib_kernel.h | 215 ------ fs/ncpfs/ncpsign_kernel.c | 128 ---- fs/ncpfs/ncpsign_kernel.h | 27 - fs/ncpfs/sock.c | 854 --------------------- fs/ncpfs/symlink.c | 182 ----- 42 files changed, 6869 insertions(+), 6864 deletions(-) create mode 100644 drivers/staging/ncpfs/Kconfig create mode 100644 drivers/staging/ncpfs/Makefile create mode 100644 drivers/staging/ncpfs/TODO create mode 100644 drivers/staging/ncpfs/dir.c create mode 100644 drivers/staging/ncpfs/file.c create mode 100644 drivers/staging/ncpfs/getopt.c create mode 100644 drivers/staging/ncpfs/getopt.h create mode 100644 drivers/staging/ncpfs/inode.c create mode 100644 drivers/staging/ncpfs/ioctl.c create mode 100644 drivers/staging/ncpfs/mmap.c create mode 100644 drivers/staging/ncpfs/ncp_fs.h create mode 100644 drivers/staging/ncpfs/ncp_fs_i.h create mode 100644 drivers/staging/ncpfs/ncp_fs_sb.h create mode 100644 drivers/staging/ncpfs/ncplib_kernel.c create mode 100644 drivers/staging/ncpfs/ncplib_kernel.h create mode 100644 drivers/staging/ncpfs/ncpsign_kernel.c create mode 100644 drivers/staging/ncpfs/ncpsign_kernel.h create mode 100644 drivers/staging/ncpfs/sock.c create mode 100644 drivers/staging/ncpfs/symlink.c delete mode 100644 fs/ncpfs/Kconfig delete mode 100644 fs/ncpfs/Makefile delete mode 100644 fs/ncpfs/dir.c delete mode 100644 fs/ncpfs/file.c delete mode 100644 fs/ncpfs/getopt.c delete mode 100644 fs/ncpfs/getopt.h delete mode 100644 fs/ncpfs/inode.c delete mode 100644 fs/ncpfs/ioctl.c delete mode 100644 fs/ncpfs/mmap.c delete mode 100644 fs/ncpfs/ncp_fs.h delete mode 100644 fs/ncpfs/ncp_fs_i.h delete mode 100644 fs/ncpfs/ncp_fs_sb.h delete mode 100644 fs/ncpfs/ncplib_kernel.c delete mode 100644 fs/ncpfs/ncplib_kernel.h delete mode 100644 fs/ncpfs/ncpsign_kernel.c delete mode 100644 fs/ncpfs/ncpsign_kernel.h delete mode 100644 fs/ncpfs/sock.c delete mode 100644 fs/ncpfs/symlink.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 56cc7261c7e4..630a19e2b2b4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9362,7 +9362,7 @@ F: drivers/net/ethernet/natsemi/natsemi.c NCP FILESYSTEM M: Petr Vandrovec S: Odd Fixes -F: fs/ncpfs/ +F: drivers/staging/ncpfs/ NCR 5380 SCSI DRIVERS M: Finn Thain diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 3744640bed5a..e95ab683331e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -28,6 +28,8 @@ source "drivers/staging/irda/net/Kconfig" source "drivers/staging/ipx/Kconfig" +source "drivers/staging/ncpfs/Kconfig" + source "drivers/staging/wlan-ng/Kconfig" source "drivers/staging/comedi/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index f4c0506470ff..af8cd6a3a1f6 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -4,6 +4,7 @@ obj-y += media/ obj-y += typec/ obj-$(CONFIG_IPX) += ipx/ +obj-$(CONFIG_NCP_FS) += ncpfs/ obj-$(CONFIG_IRDA) += irda/net/ obj-$(CONFIG_IRDA) += irda/drivers/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ diff --git a/drivers/staging/ncpfs/Kconfig b/drivers/staging/ncpfs/Kconfig new file mode 100644 index 000000000000..c931cf22a1f6 --- /dev/null +++ b/drivers/staging/ncpfs/Kconfig @@ -0,0 +1,108 @@ +# +# NCP Filesystem configuration +# +config NCP_FS + tristate "NCP file system support (to mount NetWare volumes)" + depends on IPX!=n || INET + help + NCP (NetWare Core Protocol) is a protocol that runs over IPX and is + used by Novell NetWare clients to talk to file servers. It is to + IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you + to mount NetWare file server volumes and to access them just like + any other Unix directory. For details, please read the file + in the kernel source and + the IPX-HOWTO from . + + You do not have to say Y here if you want your Linux box to act as a + file *server* for Novell NetWare clients. + + General information about how to connect Linux, Windows machines and + Macs is on the WWW at . + + To compile this as a module, choose M here: the module will be called + ncpfs. Say N unless you are connected to a Novell network. + +config NCPFS_PACKET_SIGNING + bool "Packet signatures" + depends on NCP_FS + help + NCP allows packets to be signed for stronger security. If you want + security, say Y. Normal users can leave it off. To be able to use + packet signing you must use ncpfs > 2.0.12. + +config NCPFS_IOCTL_LOCKING + bool "Proprietary file locking" + depends on NCP_FS + help + Allows locking of records on remote volumes. Say N unless you have + special applications which are able to utilize this locking scheme. + +config NCPFS_STRONG + bool "Clear remove/delete inhibit when needed" + depends on NCP_FS + help + Allows manipulation of files flagged as Delete or Rename Inhibit. + To use this feature you must mount volumes with the ncpmount + parameter "-s" (ncpfs-2.0.12 and newer). Say Y unless you are not + mounting volumes with -f 444. + +config NCPFS_NFS_NS + bool "Use NFS namespace if available" + depends on NCP_FS + help + Allows you to utilize NFS namespace on NetWare servers. It brings + you case sensitive filenames. Say Y. You can disable it at + mount-time with the `-N nfs' parameter of ncpmount. + +config NCPFS_OS2_NS + bool "Use LONG (OS/2) namespace if available" + depends on NCP_FS + help + Allows you to utilize OS2/LONG namespace on NetWare servers. + Filenames in this namespace are limited to 255 characters, they are + case insensitive, and case in names is preserved. Say Y. You can + disable it at mount time with the -N os2 parameter of ncpmount. + +config NCPFS_SMALLDOS + bool "Lowercase DOS filenames" + depends on NCP_FS + ---help--- + If you say Y here, every filename on a NetWare server volume using + the OS2/LONG namespace and created under DOS or on a volume using + DOS namespace will be converted to lowercase characters. + Saying N here will give you these filenames in uppercase. + + This is only a cosmetic option since the OS2/LONG namespace is case + insensitive. The only major reason for this option is backward + compatibility when moving from DOS to OS2/LONG namespace support. + Long filenames (created by Win95) will not be affected. + + This option does not solve the problem that filenames appear + differently under Linux and under Windows, since Windows does an + additional conversions on the client side. You can achieve similar + effects by saying Y to "Allow using of Native Language Support" + below. + +config NCPFS_NLS + bool "Use Native Language Support" + depends on NCP_FS + select NLS + help + Allows you to use codepages and I/O charsets for file name + translation between the server file system and input/output. This + may be useful, if you want to access the server with other operating + systems, e.g. Windows 95. See also NLS for more Information. + + To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer. + +config NCPFS_EXTRAS + bool "Enable symbolic links and execute flags" + depends on NCP_FS + help + This enables the use of symbolic links and an execute permission + bit on NCPFS. The file server need not have long name space or NFS + name space loaded for these to work. + + To use the new attributes, it is recommended to use the flags + '-f 600 -d 755' on the ncpmount command line. + diff --git a/drivers/staging/ncpfs/Makefile b/drivers/staging/ncpfs/Makefile new file mode 100644 index 000000000000..66fe5f878817 --- /dev/null +++ b/drivers/staging/ncpfs/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the linux ncp filesystem routines. +# + +obj-$(CONFIG_NCP_FS) += ncpfs.o + +ncpfs-y := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \ + ncpsign_kernel.o getopt.o + +ncpfs-$(CONFIG_NCPFS_EXTRAS) += symlink.o +ncpfs-$(CONFIG_NCPFS_NFS_NS) += symlink.o + +# If you want debugging output, please uncomment the following line +# ccflags-y := -DDEBUG_NCP=1 + +CFLAGS_ncplib_kernel.o := -finline-functions diff --git a/drivers/staging/ncpfs/TODO b/drivers/staging/ncpfs/TODO new file mode 100644 index 000000000000..9b6d38b7e248 --- /dev/null +++ b/drivers/staging/ncpfs/TODO @@ -0,0 +1,4 @@ +The ncpfs code will be removed soon from the kernel tree as it is old and +obsolete and broken. + +Don't worry about fixing up anything here, it's not needed. diff --git a/drivers/staging/ncpfs/dir.c b/drivers/staging/ncpfs/dir.c new file mode 100644 index 000000000000..0c57c5c5d40a --- /dev/null +++ b/drivers/staging/ncpfs/dir.c @@ -0,0 +1,1232 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * dir.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified for big endian by J.F. Chadima and David S. Miller + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998, 1999 Wolfram Pienkoss for NLS + * Modified 1999 Wolfram Pienkoss for directory caching + * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ncp_fs.h" + +static void ncp_read_volume_list(struct file *, struct dir_context *, + struct ncp_cache_control *); +static void ncp_do_readdir(struct file *, struct dir_context *, + struct ncp_cache_control *); + +static int ncp_readdir(struct file *, struct dir_context *); + +static int ncp_create(struct inode *, struct dentry *, umode_t, bool); +static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int); +static int ncp_unlink(struct inode *, struct dentry *); +static int ncp_mkdir(struct inode *, struct dentry *, umode_t); +static int ncp_rmdir(struct inode *, struct dentry *); +static int ncp_rename(struct inode *, struct dentry *, + struct inode *, struct dentry *, unsigned int); +static int ncp_mknod(struct inode * dir, struct dentry *dentry, + umode_t mode, dev_t rdev); +#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) +extern int ncp_symlink(struct inode *, struct dentry *, const char *); +#else +#define ncp_symlink NULL +#endif + +const struct file_operations ncp_dir_operations = +{ + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = ncp_readdir, + .unlocked_ioctl = ncp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ncp_compat_ioctl, +#endif +}; + +const struct inode_operations ncp_dir_inode_operations = +{ + .create = ncp_create, + .lookup = ncp_lookup, + .unlink = ncp_unlink, + .symlink = ncp_symlink, + .mkdir = ncp_mkdir, + .rmdir = ncp_rmdir, + .mknod = ncp_mknod, + .rename = ncp_rename, + .setattr = ncp_notify_change, +}; + +/* + * Dentry operations routines + */ +static int ncp_lookup_validate(struct dentry *, unsigned int); +static int ncp_hash_dentry(const struct dentry *, struct qstr *); +static int ncp_compare_dentry(const struct dentry *, + unsigned int, const char *, const struct qstr *); +static int ncp_delete_dentry(const struct dentry *); +static void ncp_d_prune(struct dentry *dentry); + +const struct dentry_operations ncp_dentry_operations = +{ + .d_revalidate = ncp_lookup_validate, + .d_hash = ncp_hash_dentry, + .d_compare = ncp_compare_dentry, + .d_delete = ncp_delete_dentry, + .d_prune = ncp_d_prune, +}; + +#define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) + +static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) +{ +#ifdef CONFIG_NCPFS_SMALLDOS + int ns = ncp_namespace(i); + + if ((ns == NW_NS_DOS) +#ifdef CONFIG_NCPFS_OS2_NS + || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS)) +#endif /* CONFIG_NCPFS_OS2_NS */ + ) + return 0; +#endif /* CONFIG_NCPFS_SMALLDOS */ + return 1; +} + +#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) + +static inline int ncp_case_sensitive(const struct inode *i) +{ +#ifdef CONFIG_NCPFS_NFS_NS + return ncp_namespace(i) == NW_NS_NFS; +#else + return 0; +#endif /* CONFIG_NCPFS_NFS_NS */ +} + +/* + * Note: leave the hash unchanged if the directory + * is case-sensitive. + */ +static int +ncp_hash_dentry(const struct dentry *dentry, struct qstr *this) +{ + struct inode *inode = d_inode_rcu(dentry); + + if (!inode) + return 0; + + if (!ncp_case_sensitive(inode)) { + struct nls_table *t; + unsigned long hash; + int i; + + t = NCP_IO_TABLE(dentry->d_sb); + hash = init_name_hash(dentry); + for (i=0; ilen ; i++) + hash = partial_name_hash(ncp_tolower(t, this->name[i]), + hash); + this->hash = end_name_hash(hash); + } + return 0; +} + +static int +ncp_compare_dentry(const struct dentry *dentry, + unsigned int len, const char *str, const struct qstr *name) +{ + struct inode *pinode; + + if (len != name->len) + return 1; + + pinode = d_inode_rcu(dentry->d_parent); + if (!pinode) + return 1; + + if (ncp_case_sensitive(pinode)) + return strncmp(str, name->name, len); + + return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len); +} + +/* + * This is the callback from dput() when d_count is going to 0. + * We use this to unhash dentries with bad inodes. + * Closing files can be safely postponed until iput() - it's done there anyway. + */ +static int +ncp_delete_dentry(const struct dentry * dentry) +{ + struct inode *inode = d_inode(dentry); + + if (inode) { + if (is_bad_inode(inode)) + return 1; + } else + { + /* N.B. Unhash negative dentries? */ + } + return 0; +} + +static inline int +ncp_single_volume(struct ncp_server *server) +{ + return (server->m.mounted_vol[0] != '\0'); +} + +static inline int ncp_is_server_root(struct inode *inode) +{ + return !ncp_single_volume(NCP_SERVER(inode)) && + is_root_inode(inode); +} + + +/* + * This is the callback when the dcache has a lookup hit. + */ + + +#ifdef CONFIG_NCPFS_STRONG +/* try to delete a readonly file (NW R bit set) */ + +static int +ncp_force_unlink(struct inode *dir, struct dentry* dentry) +{ + int res=0x9c,res2; + struct nw_modify_dos_info info; + __le32 old_nwattr; + struct inode *inode; + + memset(&info, 0, sizeof(info)); + + /* remove the Read-Only flag on the NW server */ + inode = d_inode(dentry); + + old_nwattr = NCP_FINFO(inode)->nwattr; + info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); + if (res2) + goto leave_me; + + /* now try again the delete operation */ + res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry); + + if (res) /* delete failed, set R bit again */ + { + info.attributes = old_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); + if (res2) + goto leave_me; + } +leave_me: + return(res); +} +#endif /* CONFIG_NCPFS_STRONG */ + +#ifdef CONFIG_NCPFS_STRONG +static int +ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name, + struct inode *new_dir, struct dentry* new_dentry, char *_new_name) +{ + struct nw_modify_dos_info info; + int res=0x90,res2; + struct inode *old_inode = d_inode(old_dentry); + __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr; + __le32 new_nwattr = 0; /* shut compiler warning */ + int old_nwattr_changed = 0; + int new_nwattr_changed = 0; + + memset(&info, 0, sizeof(info)); + + /* remove the Read-Only flag on the NW server */ + + info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); + if (!res2) + old_nwattr_changed = 1; + if (new_dentry && d_really_is_positive(new_dentry)) { + new_nwattr = NCP_FINFO(d_inode(new_dentry))->nwattr; + info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); + if (!res2) + new_nwattr_changed = 1; + } + /* now try again the rename operation */ + /* but only if something really happened */ + if (new_nwattr_changed || old_nwattr_changed) { + res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), + old_dir, _old_name, + new_dir, _new_name); + } + if (res) + goto leave_me; + /* file was successfully renamed, so: + do not set attributes on old file - it no longer exists + copy attributes from old file to new */ + new_nwattr_changed = old_nwattr_changed; + new_nwattr = old_nwattr; + old_nwattr_changed = 0; + +leave_me:; + if (old_nwattr_changed) { + info.attributes = old_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); + /* ignore errors */ + } + if (new_nwattr_changed) { + info.attributes = new_nwattr; + res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); + /* ignore errors */ + } + return(res); +} +#endif /* CONFIG_NCPFS_STRONG */ + + +static int +ncp_lookup_validate(struct dentry *dentry, unsigned int flags) +{ + struct ncp_server *server; + struct dentry *parent; + struct inode *dir; + struct ncp_entry_info finfo; + int res, val = 0, len; + __u8 __name[NCP_MAXPATHLEN + 1]; + + if (dentry == dentry->d_sb->s_root) + return 1; + + if (flags & LOOKUP_RCU) + return -ECHILD; + + parent = dget_parent(dentry); + dir = d_inode(parent); + + if (d_really_is_negative(dentry)) + goto finished; + + server = NCP_SERVER(dir); + + /* + * Inspired by smbfs: + * The default validation is based on dentry age: + * We set the max age at mount time. (But each + * successful server lookup renews the timestamp.) + */ + val = NCP_TEST_AGE(server, dentry); + if (val) + goto finished; + + ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n", + dentry, NCP_GET_AGE(dentry)); + + len = sizeof(__name); + if (ncp_is_server_root(dir)) { + res = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, 1); + if (!res) { + res = ncp_lookup_volume(server, __name, &(finfo.i)); + if (!res) + ncp_update_known_namespace(server, finfo.i.volNumber, NULL); + } + } else { + res = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (!res) + res = ncp_obtain_info(server, dir, __name, &(finfo.i)); + } + finfo.volume = finfo.i.volNumber; + ncp_dbg(2, "looked for %pd/%s, res=%d\n", + dentry->d_parent, __name, res); + /* + * If we didn't find it, or if it has a different dirEntNum to + * what we remember, it's not valid any more. + */ + if (!res) { + struct inode *inode = d_inode(dentry); + + inode_lock(inode); + if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) { + ncp_new_dentry(dentry); + val=1; + } else + ncp_dbg(2, "found, but dirEntNum changed\n"); + + ncp_update_inode2(inode, &finfo); + inode_unlock(inode); + } + +finished: + ncp_dbg(2, "result=%d\n", val); + dput(parent); + return val; +} + +static time_t ncp_obtain_mtime(struct dentry *dentry) +{ + struct inode *inode = d_inode(dentry); + struct ncp_server *server = NCP_SERVER(inode); + struct nw_info_struct i; + + if (!ncp_conn_valid(server) || ncp_is_server_root(inode)) + return 0; + + if (ncp_obtain_info(server, inode, NULL, &i)) + return 0; + + return ncp_date_dos2unix(i.modifyTime, i.modifyDate); +} + +static inline void +ncp_invalidate_dircache_entries(struct dentry *parent) +{ + struct ncp_server *server = NCP_SERVER(d_inode(parent)); + struct dentry *dentry; + + spin_lock(&parent->d_lock); + list_for_each_entry(dentry, &parent->d_subdirs, d_child) { + dentry->d_fsdata = NULL; + ncp_age_dentry(server, dentry); + } + spin_unlock(&parent->d_lock); +} + +static int ncp_readdir(struct file *file, struct dir_context *ctx) +{ + struct dentry *dentry = file->f_path.dentry; + struct inode *inode = d_inode(dentry); + struct page *page = NULL; + struct ncp_server *server = NCP_SERVER(inode); + union ncp_dir_cache *cache = NULL; + struct ncp_cache_control ctl; + int result, mtime_valid = 0; + time_t mtime = 0; + + ctl.page = NULL; + ctl.cache = NULL; + + ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos); + + result = -EIO; + /* Do not generate '.' and '..' when server is dead. */ + if (!ncp_conn_valid(server)) + goto out; + + result = 0; + if (!dir_emit_dots(file, ctx)) + goto out; + + page = grab_cache_page(&inode->i_data, 0); + if (!page) + goto read_really; + + ctl.cache = cache = kmap(page); + ctl.head = cache->head; + + if (!PageUptodate(page) || !ctl.head.eof) + goto init_cache; + + if (ctx->pos == 2) { + if (jiffies - ctl.head.time >= NCP_MAX_AGE(server)) + goto init_cache; + + mtime = ncp_obtain_mtime(dentry); + mtime_valid = 1; + if ((!mtime) || (mtime != ctl.head.mtime)) + goto init_cache; + } + + if (ctx->pos > ctl.head.end) + goto finished; + + ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2); + ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE; + ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE; + + for (;;) { + if (ctl.ofs != 0) { + ctl.page = find_lock_page(&inode->i_data, ctl.ofs); + if (!ctl.page) + goto invalid_cache; + ctl.cache = kmap(ctl.page); + if (!PageUptodate(ctl.page)) + goto invalid_cache; + } + while (ctl.idx < NCP_DIRCACHE_SIZE) { + struct dentry *dent; + bool over; + + spin_lock(&dentry->d_lock); + if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) { + spin_unlock(&dentry->d_lock); + goto invalid_cache; + } + dent = ctl.cache->dentry[ctl.idx]; + if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) { + spin_unlock(&dentry->d_lock); + goto invalid_cache; + } + spin_unlock(&dentry->d_lock); + if (d_really_is_negative(dent)) { + dput(dent); + goto invalid_cache; + } + over = !dir_emit(ctx, dent->d_name.name, + dent->d_name.len, + d_inode(dent)->i_ino, DT_UNKNOWN); + dput(dent); + if (over) + goto finished; + ctx->pos += 1; + ctl.idx += 1; + if (ctx->pos > ctl.head.end) + goto finished; + } + if (ctl.page) { + kunmap(ctl.page); + SetPageUptodate(ctl.page); + unlock_page(ctl.page); + put_page(ctl.page); + ctl.page = NULL; + } + ctl.idx = 0; + ctl.ofs += 1; + } +invalid_cache: + if (ctl.page) { + kunmap(ctl.page); + unlock_page(ctl.page); + put_page(ctl.page); + ctl.page = NULL; + } + ctl.cache = cache; +init_cache: + ncp_invalidate_dircache_entries(dentry); + if (!mtime_valid) { + mtime = ncp_obtain_mtime(dentry); + mtime_valid = 1; + } + ctl.head.mtime = mtime; + ctl.head.time = jiffies; + ctl.head.eof = 0; + ctl.fpos = 2; + ctl.ofs = 0; + ctl.idx = NCP_DIRCACHE_START; + ctl.filled = 0; + ctl.valid = 1; +read_really: + spin_lock(&dentry->d_lock); + NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE; + spin_unlock(&dentry->d_lock); + if (ncp_is_server_root(inode)) { + ncp_read_volume_list(file, ctx, &ctl); + } else { + ncp_do_readdir(file, ctx, &ctl); + } + ctl.head.end = ctl.fpos - 1; + ctl.head.eof = ctl.valid; +finished: + if (ctl.page) { + kunmap(ctl.page); + SetPageUptodate(ctl.page); + unlock_page(ctl.page); + put_page(ctl.page); + } + if (page) { + cache->head = ctl.head; + kunmap(page); + SetPageUptodate(page); + unlock_page(page); + put_page(page); + } +out: + return result; +} + +static void ncp_d_prune(struct dentry *dentry) +{ + if (!dentry->d_fsdata) /* not referenced from page cache */ + return; + NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE; +} + +static int +ncp_fill_cache(struct file *file, struct dir_context *ctx, + struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, + int inval_childs) +{ + struct dentry *newdent, *dentry = file->f_path.dentry; + struct inode *dir = d_inode(dentry); + struct ncp_cache_control ctl = *ctrl; + struct qstr qname; + int valid = 0; + int hashed = 0; + ino_t ino = 0; + __u8 __name[NCP_MAXPATHLEN + 1]; + + qname.len = sizeof(__name); + if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len, + entry->i.entryName, entry->i.nameLen, + !ncp_preserve_entry_case(dir, entry->i.NSCreator))) + return 1; /* I'm not sure */ + + qname.name = __name; + + newdent = d_hash_and_lookup(dentry, &qname); + if (IS_ERR(newdent)) + goto end_advance; + if (!newdent) { + newdent = d_alloc(dentry, &qname); + if (!newdent) + goto end_advance; + } else { + hashed = 1; + + /* If case sensitivity changed for this volume, all entries below this one + should be thrown away. This entry itself is not affected, as its case + sensitivity is controlled by its own parent. */ + if (inval_childs) + shrink_dcache_parent(newdent); + + /* + * NetWare's OS2 namespace is case preserving yet case + * insensitive. So we update dentry's name as received from + * server. Parent dir's i_mutex is locked because we're in + * readdir. + */ + dentry_update_name_case(newdent, &qname); + } + + if (d_really_is_negative(newdent)) { + struct inode *inode; + + entry->opened = 0; + entry->ino = iunique(dir->i_sb, 2); + inode = ncp_iget(dir->i_sb, entry); + if (inode) { + d_instantiate(newdent, inode); + if (!hashed) + d_rehash(newdent); + } else { + spin_lock(&dentry->d_lock); + NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE; + spin_unlock(&dentry->d_lock); + } + } else { + struct inode *inode = d_inode(newdent); + + inode_lock_nested(inode, I_MUTEX_CHILD); + ncp_update_inode2(inode, entry); + inode_unlock(inode); + } + + if (ctl.idx >= NCP_DIRCACHE_SIZE) { + if (ctl.page) { + kunmap(ctl.page); + SetPageUptodate(ctl.page); + unlock_page(ctl.page); + put_page(ctl.page); + } + ctl.cache = NULL; + ctl.idx -= NCP_DIRCACHE_SIZE; + ctl.ofs += 1; + ctl.page = grab_cache_page(&dir->i_data, ctl.ofs); + if (ctl.page) + ctl.cache = kmap(ctl.page); + } + if (ctl.cache) { + if (d_really_is_positive(newdent)) { + newdent->d_fsdata = newdent; + ctl.cache->dentry[ctl.idx] = newdent; + ino = d_inode(newdent)->i_ino; + ncp_new_dentry(newdent); + } + valid = 1; + } + dput(newdent); +end_advance: + if (!valid) + ctl.valid = 0; + if (!ctl.filled && (ctl.fpos == ctx->pos)) { + if (!ino) + ino = iunique(dir->i_sb, 2); + ctl.filled = !dir_emit(ctx, qname.name, qname.len, + ino, DT_UNKNOWN); + if (!ctl.filled) + ctx->pos += 1; + } + ctl.fpos += 1; + ctl.idx += 1; + *ctrl = ctl; + return (ctl.valid || !ctl.filled); +} + +static void +ncp_read_volume_list(struct file *file, struct dir_context *ctx, + struct ncp_cache_control *ctl) +{ + struct inode *inode = file_inode(file); + struct ncp_server *server = NCP_SERVER(inode); + struct ncp_volume_info info; + struct ncp_entry_info entry; + int i; + + ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos); + + for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { + int inval_dentry; + + if (ncp_get_volume_info_with_number(server, i, &info) != 0) + return; + if (!strlen(info.volume_name)) + continue; + + ncp_dbg(1, "found vol: %s\n", info.volume_name); + + if (ncp_lookup_volume(server, info.volume_name, + &entry.i)) { + ncp_dbg(1, "could not lookup vol %s\n", + info.volume_name); + continue; + } + inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL); + entry.volume = entry.i.volNumber; + if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry)) + return; + } +} + +static void +ncp_do_readdir(struct file *file, struct dir_context *ctx, + struct ncp_cache_control *ctl) +{ + struct inode *dir = file_inode(file); + struct ncp_server *server = NCP_SERVER(dir); + struct nw_search_sequence seq; + struct ncp_entry_info entry; + int err; + void* buf; + int more; + size_t bufsize; + + ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos); + ncp_vdbg("init %pD, volnum=%d, dirent=%u\n", + file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum); + + err = ncp_initialize_search(server, dir, &seq); + if (err) { + ncp_dbg(1, "init failed, err=%d\n", err); + return; + } + /* We MUST NOT use server->buffer_size handshaked with server if we are + using UDP, as for UDP server uses max. buffer size determined by + MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). + So we use 128KB, just to be sure, as there is no way how to know + this value in advance. */ + bufsize = 131072; + buf = vmalloc(bufsize); + if (!buf) + return; + do { + int cnt; + char* rpl; + size_t rpls; + + err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls); + if (err) /* Error */ + break; + if (!cnt) /* prevent endless loop */ + break; + while (cnt--) { + size_t onerpl; + + if (rpls < offsetof(struct nw_info_struct, entryName)) + break; /* short packet */ + ncp_extract_file_info(rpl, &entry.i); + onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen; + if (rpls < onerpl) + break; /* short packet */ + (void)ncp_obtain_nfs_info(server, &entry.i); + rpl += onerpl; + rpls -= onerpl; + entry.volume = entry.i.volNumber; + if (!ncp_fill_cache(file, ctx, ctl, &entry, 0)) + break; + } + } while (more); + vfree(buf); + return; +} + +int ncp_conn_logged_in(struct super_block *sb) +{ + struct ncp_server* server = NCP_SBP(sb); + int result; + + if (ncp_single_volume(server)) { + int len; + struct dentry* dent; + __u32 volNumber; + __le32 dirEntNum; + __le32 DosDirNum; + __u8 __name[NCP_MAXPATHLEN + 1]; + + len = sizeof(__name); + result = ncp_io2vol(server, __name, &len, server->m.mounted_vol, + strlen(server->m.mounted_vol), 1); + if (result) + goto out; + result = -ENOENT; + if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) { + ncp_vdbg("%s not found\n", server->m.mounted_vol); + goto out; + } + dent = sb->s_root; + if (dent) { + struct inode* ino = d_inode(dent); + if (ino) { + ncp_update_known_namespace(server, volNumber, NULL); + NCP_FINFO(ino)->volNumber = volNumber; + NCP_FINFO(ino)->dirEntNum = dirEntNum; + NCP_FINFO(ino)->DosDirNum = DosDirNum; + result = 0; + } else { + ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n"); + } + } else { + ncp_dbg(1, "sb->s_root == NULL!\n"); + } + } else + result = 0; + +out: + return result; +} + +static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) +{ + struct ncp_server *server = NCP_SERVER(dir); + struct inode *inode = NULL; + struct ncp_entry_info finfo; + int error, res, len; + __u8 __name[NCP_MAXPATHLEN + 1]; + + error = -EIO; + if (!ncp_conn_valid(server)) + goto finished; + + ncp_vdbg("server lookup for %pd2\n", dentry); + + len = sizeof(__name); + if (ncp_is_server_root(dir)) { + res = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, 1); + if (!res) + res = ncp_lookup_volume(server, __name, &(finfo.i)); + if (!res) + ncp_update_known_namespace(server, finfo.i.volNumber, NULL); + } else { + res = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (!res) + res = ncp_obtain_info(server, dir, __name, &(finfo.i)); + } + ncp_vdbg("looked for %pd2, res=%d\n", dentry, res); + /* + * If we didn't find an entry, make a negative dentry. + */ + if (res) + goto add_entry; + + /* + * Create an inode for the entry. + */ + finfo.opened = 0; + finfo.ino = iunique(dir->i_sb, 2); + finfo.volume = finfo.i.volNumber; + error = -EACCES; + inode = ncp_iget(dir->i_sb, &finfo); + + if (inode) { + ncp_new_dentry(dentry); +add_entry: + d_add(dentry, inode); + error = 0; + } + +finished: + ncp_vdbg("result=%d\n", error); + return ERR_PTR(error); +} + +/* + * This code is common to create, mkdir, and mknod. + */ +static int ncp_instantiate(struct inode *dir, struct dentry *dentry, + struct ncp_entry_info *finfo) +{ + struct inode *inode; + int error = -EINVAL; + + finfo->ino = iunique(dir->i_sb, 2); + inode = ncp_iget(dir->i_sb, finfo); + if (!inode) + goto out_close; + d_instantiate(dentry,inode); + error = 0; +out: + return error; + +out_close: + ncp_vdbg("%pd2 failed, closing file\n", dentry); + ncp_close_file(NCP_SERVER(dir), finfo->file_handle); + goto out; +} + +int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode, + dev_t rdev, __le32 attributes) +{ + struct ncp_server *server = NCP_SERVER(dir); + struct ncp_entry_info finfo; + int error, result, len; + int opmode; + __u8 __name[NCP_MAXPATHLEN + 1]; + + ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode); + + ncp_age_dentry(server, dentry); + len = sizeof(__name); + error = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (error) + goto out; + + error = -EACCES; + + if (S_ISREG(mode) && + (server->m.flags & NCP_MOUNT_EXTRAS) && + (mode & S_IXUGO)) + attributes |= aSYSTEM | aSHARED; + + result = ncp_open_create_file_or_subdir(server, dir, __name, + OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, + attributes, AR_READ | AR_WRITE, &finfo); + opmode = O_RDWR; + if (result) { + result = ncp_open_create_file_or_subdir(server, dir, __name, + OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, + attributes, AR_WRITE, &finfo); + if (result) { + if (result == 0x87) + error = -ENAMETOOLONG; + else if (result < 0) + error = result; + ncp_dbg(1, "%pd2 failed\n", dentry); + goto out; + } + opmode = O_WRONLY; + } + finfo.access = opmode; + if (ncp_is_nfs_extras(server, finfo.volume)) { + finfo.i.nfs.mode = mode; + finfo.i.nfs.rdev = new_encode_dev(rdev); + if (ncp_modify_nfs_info(server, finfo.volume, + finfo.i.dirEntNum, + mode, new_encode_dev(rdev)) != 0) + goto out; + } + + error = ncp_instantiate(dir, dentry, &finfo); +out: + return error; +} + +static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +{ + return ncp_create_new(dir, dentry, mode, 0, 0); +} + +static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct ncp_entry_info finfo; + struct ncp_server *server = NCP_SERVER(dir); + int error, len; + __u8 __name[NCP_MAXPATHLEN + 1]; + + ncp_dbg(1, "making %pd2\n", dentry); + + ncp_age_dentry(server, dentry); + len = sizeof(__name); + error = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (error) + goto out; + + error = ncp_open_create_file_or_subdir(server, dir, __name, + OC_MODE_CREATE, aDIR, + cpu_to_le16(0xffff), + &finfo); + if (error == 0) { + if (ncp_is_nfs_extras(server, finfo.volume)) { + mode |= S_IFDIR; + finfo.i.nfs.mode = mode; + if (ncp_modify_nfs_info(server, + finfo.volume, + finfo.i.dirEntNum, + mode, 0) != 0) + goto out; + } + error = ncp_instantiate(dir, dentry, &finfo); + } else if (error > 0) { + error = -EACCES; + } +out: + return error; +} + +static int ncp_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct ncp_server *server = NCP_SERVER(dir); + int error, result, len; + __u8 __name[NCP_MAXPATHLEN + 1]; + + ncp_dbg(1, "removing %pd2\n", dentry); + + len = sizeof(__name); + error = ncp_io2vol(server, __name, &len, dentry->d_name.name, + dentry->d_name.len, !ncp_preserve_case(dir)); + if (error) + goto out; + + result = ncp_del_file_or_subdir(server, dir, __name); + switch (result) { + case 0x00: + error = 0; + break; + case 0x85: /* unauthorized to delete file */ + case 0x8A: /* unauthorized to delete file */ + error = -EACCES; + break; + case 0x8F: + case 0x90: /* read only */ + error = -EPERM; + break; + case 0x9F: /* in use by another client */ + error = -EBUSY; + break; + case 0xA0: /* directory not empty */ + error = -ENOTEMPTY; + break; + case 0xFF: /* someone deleted file */ + error = -ENOENT; + break; + default: + error = result < 0 ? result : -EACCES; + break; + } +out: + return error; +} + +static int ncp_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = d_inode(dentry); + struct ncp_server *server; + int error; + + server = NCP_SERVER(dir); + ncp_dbg(1, "unlinking %pd2\n", dentry); + + /* + * Check whether to close the file ... + */ + if (inode) { + ncp_vdbg("closing file\n"); + ncp_make_closed(inode); + } + + error = ncp_del_file_or_subdir2(server, dentry); +#ifdef CONFIG_NCPFS_STRONG + /* 9C is Invalid path.. It should be 8F, 90 - read only, but + it is not :-( */ + if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */ + error = ncp_force_unlink(dir, dentry); + } +#endif + switch (error) { + case 0x00: + ncp_dbg(1, "removed %pd2\n", dentry); + break; + case 0x85: + case 0x8A: + error = -EACCES; + break; + case 0x8D: /* some files in use */ + case 0x8E: /* all files in use */ + error = -EBUSY; + break; + case 0x8F: /* some read only */ + case 0x90: /* all read only */ + case 0x9C: /* !!! returned when in-use or read-only by NW4 */ + error = -EPERM; + break; + case 0xFF: + error = -ENOENT; + break; + default: + error = error < 0 ? error : -EACCES; + break; + } + return error; +} + +static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + struct ncp_server *server = NCP_SERVER(old_dir); + int error; + int old_len, new_len; + __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1]; + + if (flags) + return -EINVAL; + + ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry); + + ncp_age_dentry(server, old_dentry); + ncp_age_dentry(server, new_dentry); + + old_len = sizeof(__old_name); + error = ncp_io2vol(server, __old_name, &old_len, + old_dentry->d_name.name, old_dentry->d_name.len, + !ncp_preserve_case(old_dir)); + if (error) + goto out; + + new_len = sizeof(__new_name); + error = ncp_io2vol(server, __new_name, &new_len, + new_dentry->d_name.name, new_dentry->d_name.len, + !ncp_preserve_case(new_dir)); + if (error) + goto out; + + error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name, + new_dir, __new_name); +#ifdef CONFIG_NCPFS_STRONG + if ((error == 0x90 || error == 0x8B || error == -EACCES) && + server->m.flags & NCP_MOUNT_STRONG) { /* RO */ + error = ncp_force_rename(old_dir, old_dentry, __old_name, + new_dir, new_dentry, __new_name); + } +#endif + switch (error) { + case 0x00: + ncp_dbg(1, "renamed %pd -> %pd\n", + old_dentry, new_dentry); + ncp_d_prune(old_dentry); + ncp_d_prune(new_dentry); + break; + case 0x9E: + error = -ENAMETOOLONG; + break; + case 0xFF: + error = -ENOENT; + break; + default: + error = error < 0 ? error : -EACCES; + break; + } +out: + return error; +} + +static int ncp_mknod(struct inode * dir, struct dentry *dentry, + umode_t mode, dev_t rdev) +{ + if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { + ncp_dbg(1, "mode = 0%ho\n", mode); + return ncp_create_new(dir, dentry, mode, rdev, 0); + } + return -EPERM; /* Strange, but true */ +} + +/* The following routines are taken directly from msdos-fs */ + +/* Linear day numbers of the respective 1sts in non-leap years. */ + +static int day_n[] = +{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0}; +/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ + +static int utc2local(int time) +{ + return time - sys_tz.tz_minuteswest * 60; +} + +static int local2utc(int time) +{ + return time + sys_tz.tz_minuteswest * 60; +} + +/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ +int +ncp_date_dos2unix(__le16 t, __le16 d) +{ + unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d); + int month, year, secs; + + /* first subtract and mask after that... Otherwise, if + date == 0, bad things happen */ + month = ((date >> 5) - 1) & 15; + year = date >> 9; + secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + + 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + + year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653); + /* days since 1.1.70 plus 80's leap day */ + return local2utc(secs); +} + + +/* Convert linear UNIX date to a MS-DOS time/date pair. */ +void +ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date) +{ + int day, year, nl_day, month; + + unix_date = utc2local(unix_date); + *time = cpu_to_le16( + (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) + + (((unix_date / 3600) % 24) << 11)); + day = unix_date / 86400 - 3652; + year = day / 365; + if ((year + 3) / 4 + 365 * year > day) + year--; + day -= (year + 3) / 4 + 365 * year; + if (day == 59 && !(year & 3)) { + nl_day = day; + month = 2; + } else { + nl_day = (year & 3) || day <= 59 ? day : day - 1; + for (month = 1; month < 12; month++) + if (day_n[month] > nl_day) + break; + } + *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9)); +} diff --git a/drivers/staging/ncpfs/file.c b/drivers/staging/ncpfs/file.c new file mode 100644 index 000000000000..8f8cc0334ddd --- /dev/null +++ b/drivers/staging/ncpfs/file.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * file.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ncp_fs.h" + +static int ncp_fsync(struct file *file, loff_t start, loff_t end, int datasync) +{ + return file_write_and_wait_range(file, start, end); +} + +/* + * Open a file with the specified read/write mode. + */ +int ncp_make_open(struct inode *inode, int right) +{ + int error; + int access; + + error = -EINVAL; + if (!inode) { + pr_err("%s: got NULL inode\n", __func__); + goto out; + } + + ncp_dbg(1, "opened=%d, volume # %u, dir entry # %u\n", + atomic_read(&NCP_FINFO(inode)->opened), + NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum); + error = -EACCES; + mutex_lock(&NCP_FINFO(inode)->open_mutex); + if (!atomic_read(&NCP_FINFO(inode)->opened)) { + struct ncp_entry_info finfo; + int result; + + /* tries max. rights */ + finfo.access = O_RDWR; + result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), + inode, NULL, OC_MODE_OPEN, + 0, AR_READ | AR_WRITE, &finfo); + if (!result) + goto update; + /* RDWR did not succeeded, try readonly or writeonly as requested */ + switch (right) { + case O_RDONLY: + finfo.access = O_RDONLY; + result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), + inode, NULL, OC_MODE_OPEN, + 0, AR_READ, &finfo); + break; + case O_WRONLY: + finfo.access = O_WRONLY; + result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), + inode, NULL, OC_MODE_OPEN, + 0, AR_WRITE, &finfo); + break; + } + if (result) { + ncp_vdbg("failed, result=%d\n", result); + goto out_unlock; + } + /* + * Update the inode information. + */ + update: + ncp_update_inode(inode, &finfo); + atomic_set(&NCP_FINFO(inode)->opened, 1); + } + + access = NCP_FINFO(inode)->access; + ncp_vdbg("file open, access=%x\n", access); + if (access == right || access == O_RDWR) { + atomic_inc(&NCP_FINFO(inode)->opened); + error = 0; + } + +out_unlock: + mutex_unlock(&NCP_FINFO(inode)->open_mutex); +out: + return error; +} + +static ssize_t +ncp_file_read_iter(struct kiocb *iocb, struct iov_iter *to) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); + size_t already_read = 0; + off_t pos = iocb->ki_pos; + size_t bufsize; + int error; + void *freepage; + size_t freelen; + + ncp_dbg(1, "enter %pD2\n", file); + + if (!iov_iter_count(to)) + return 0; + if (pos > inode->i_sb->s_maxbytes) + return 0; + iov_iter_truncate(to, inode->i_sb->s_maxbytes - pos); + + error = ncp_make_open(inode, O_RDONLY); + if (error) { + ncp_dbg(1, "open failed, error=%d\n", error); + return error; + } + + bufsize = NCP_SERVER(inode)->buffer_size; + + error = -EIO; + freelen = ncp_read_bounce_size(bufsize); + freepage = vmalloc(freelen); + if (!freepage) + goto outrel; + error = 0; + /* First read in as much as possible for each bufsize. */ + while (iov_iter_count(to)) { + int read_this_time; + size_t to_read = min_t(size_t, + bufsize - (pos % bufsize), + iov_iter_count(to)); + + error = ncp_read_bounce(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + pos, to_read, to, &read_this_time, + freepage, freelen); + if (error) { + error = -EIO; /* NW errno -> Linux errno */ + break; + } + pos += read_this_time; + already_read += read_this_time; + + if (read_this_time != to_read) + break; + } + vfree(freepage); + + iocb->ki_pos = pos; + + file_accessed(file); + + ncp_dbg(1, "exit %pD2\n", file); +outrel: + ncp_inode_close(inode); + return already_read ? already_read : error; +} + +static ssize_t +ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); + size_t already_written = 0; + size_t bufsize; + int errno; + void *bouncebuffer; + off_t pos; + + ncp_dbg(1, "enter %pD2\n", file); + errno = generic_write_checks(iocb, from); + if (errno <= 0) + return errno; + + errno = ncp_make_open(inode, O_WRONLY); + if (errno) { + ncp_dbg(1, "open failed, error=%d\n", errno); + return errno; + } + bufsize = NCP_SERVER(inode)->buffer_size; + + errno = file_update_time(file); + if (errno) + goto outrel; + + bouncebuffer = vmalloc(bufsize); + if (!bouncebuffer) { + errno = -EIO; /* -ENOMEM */ + goto outrel; + } + pos = iocb->ki_pos; + while (iov_iter_count(from)) { + int written_this_time; + size_t to_write = min_t(size_t, + bufsize - (pos % bufsize), + iov_iter_count(from)); + + if (!copy_from_iter_full(bouncebuffer, to_write, from)) { + errno = -EFAULT; + break; + } + if (ncp_write_kernel(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + pos, to_write, bouncebuffer, &written_this_time) != 0) { + errno = -EIO; + break; + } + pos += written_this_time; + already_written += written_this_time; + + if (written_this_time != to_write) + break; + } + vfree(bouncebuffer); + + iocb->ki_pos = pos; + + if (pos > i_size_read(inode)) { + inode_lock(inode); + if (pos > i_size_read(inode)) + i_size_write(inode, pos); + inode_unlock(inode); + } + ncp_dbg(1, "exit %pD2\n", file); +outrel: + ncp_inode_close(inode); + return already_written ? already_written : errno; +} + +static int ncp_release(struct inode *inode, struct file *file) { + if (ncp_make_closed(inode)) { + ncp_dbg(1, "failed to close\n"); + } + return 0; +} + +const struct file_operations ncp_file_operations = +{ + .llseek = generic_file_llseek, + .read_iter = ncp_file_read_iter, + .write_iter = ncp_file_write_iter, + .unlocked_ioctl = ncp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ncp_compat_ioctl, +#endif + .mmap = ncp_mmap, + .release = ncp_release, + .fsync = ncp_fsync, +}; + +const struct inode_operations ncp_file_inode_operations = +{ + .setattr = ncp_notify_change, +}; diff --git a/drivers/staging/ncpfs/getopt.c b/drivers/staging/ncpfs/getopt.c new file mode 100644 index 000000000000..5c941bef14c4 --- /dev/null +++ b/drivers/staging/ncpfs/getopt.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * getopt.c + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include + +#include + +#include "getopt.h" + +/** + * ncp_getopt - option parser + * @caller: name of the caller, for error messages + * @options: the options string + * @opts: an array of &struct option entries controlling parser operations + * @optopt: output; will contain the current option + * @optarg: output; will contain the value (if one exists) + * @value: output; may be NULL; will be overwritten with the integer value + * of the current argument. + * + * Helper to parse options on the format used by mount ("a=b,c=d,e,f"). + * Returns opts->val if a matching entry in the 'opts' array is found, + * 0 when no more tokens are found, -1 if an error is encountered. + */ +int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, + char **optopt, char **optarg, unsigned long *value) +{ + char *token; + char *val; + + do { + if ((token = strsep(options, ",")) == NULL) + return 0; + } while (*token == '\0'); + if (optopt) + *optopt = token; + + if ((val = strchr (token, '=')) != NULL) { + *val++ = 0; + } + *optarg = val; + for (; opts->name; opts++) { + if (!strcmp(opts->name, token)) { + if (!val) { + if (opts->has_arg & OPT_NOPARAM) { + return opts->val; + } + pr_info("%s: the %s option requires an argument\n", + caller, token); + return -EINVAL; + } + if (opts->has_arg & OPT_INT) { + int rc = kstrtoul(val, 0, value); + + if (rc) { + pr_info("%s: invalid numeric value in %s=%s\n", + caller, token, val); + return rc; + } + return opts->val; + } + if (opts->has_arg & OPT_STRING) { + return opts->val; + } + pr_info("%s: unexpected argument %s to the %s option\n", + caller, val, token); + return -EINVAL; + } + } + pr_info("%s: Unrecognized mount option %s\n", caller, token); + return -EOPNOTSUPP; +} diff --git a/drivers/staging/ncpfs/getopt.h b/drivers/staging/ncpfs/getopt.h new file mode 100644 index 000000000000..30f0da317670 --- /dev/null +++ b/drivers/staging/ncpfs/getopt.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_GETOPT_H +#define _LINUX_GETOPT_H + +#define OPT_NOPARAM 1 +#define OPT_INT 2 +#define OPT_STRING 4 +struct ncp_option { + const char *name; + unsigned int has_arg; + int val; +}; + +extern int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, + char **optopt, char **optarg, unsigned long *value); + +#endif /* _LINUX_GETOPT_H */ diff --git a/drivers/staging/ncpfs/inode.c b/drivers/staging/ncpfs/inode.c new file mode 100644 index 000000000000..129f1937fa2c --- /dev/null +++ b/drivers/staging/ncpfs/inode.c @@ -0,0 +1,1066 @@ +/* + * inode.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified for big endian by J.F. Chadima and David S. Miller + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998 Wolfram Pienkoss for NLS + * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ncp_fs.h" +#include "getopt.h" + +#define NCP_DEFAULT_FILE_MODE 0600 +#define NCP_DEFAULT_DIR_MODE 0700 +#define NCP_DEFAULT_TIME_OUT 10 +#define NCP_DEFAULT_RETRY_COUNT 20 + +static void ncp_evict_inode(struct inode *); +static void ncp_put_super(struct super_block *); +static int ncp_statfs(struct dentry *, struct kstatfs *); +static int ncp_show_options(struct seq_file *, struct dentry *); + +static struct kmem_cache * ncp_inode_cachep; + +static struct inode *ncp_alloc_inode(struct super_block *sb) +{ + struct ncp_inode_info *ei; + ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL); + if (!ei) + return NULL; + return &ei->vfs_inode; +} + +static void ncp_i_callback(struct rcu_head *head) +{ + struct inode *inode = container_of(head, struct inode, i_rcu); + kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); +} + +static void ncp_destroy_inode(struct inode *inode) +{ + call_rcu(&inode->i_rcu, ncp_i_callback); +} + +static void init_once(void *foo) +{ + struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; + + mutex_init(&ei->open_mutex); + inode_init_once(&ei->vfs_inode); +} + +static int init_inodecache(void) +{ + ncp_inode_cachep = kmem_cache_create("ncp_inode_cache", + sizeof(struct ncp_inode_info), + 0, (SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD|SLAB_ACCOUNT), + init_once); + if (ncp_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + +static void destroy_inodecache(void) +{ + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); + kmem_cache_destroy(ncp_inode_cachep); +} + +static int ncp_remount(struct super_block *sb, int *flags, char* data) +{ + sync_filesystem(sb); + *flags |= MS_NODIRATIME; + return 0; +} + +static const struct super_operations ncp_sops = +{ + .alloc_inode = ncp_alloc_inode, + .destroy_inode = ncp_destroy_inode, + .drop_inode = generic_delete_inode, + .evict_inode = ncp_evict_inode, + .put_super = ncp_put_super, + .statfs = ncp_statfs, + .remount_fs = ncp_remount, + .show_options = ncp_show_options, +}; + +/* + * Fill in the ncpfs-specific information in the inode. + */ +static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo) +{ + NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum; + NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum; + NCP_FINFO(inode)->volNumber = nwinfo->volume; +} + +void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo) +{ + ncp_update_dirent(inode, nwinfo); + NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; + NCP_FINFO(inode)->access = nwinfo->access; + memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, + sizeof(nwinfo->file_handle)); + ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n", + nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum); +} + +static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) +{ + /* NFS namespace mode overrides others if it's set. */ + ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode); + if (nwi->nfs.mode) { + /* XXX Security? */ + inode->i_mode = nwi->nfs.mode; + } + + inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; + + inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); + inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); + inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate); + inode->i_atime.tv_nsec = 0; + inode->i_mtime.tv_nsec = 0; + inode->i_ctime.tv_nsec = 0; +} + +static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo) +{ + struct nw_info_struct *nwi = &nwinfo->i; + struct ncp_server *server = NCP_SERVER(inode); + + if (nwi->attributes & aDIR) { + inode->i_mode = server->m.dir_mode; + /* for directories dataStreamSize seems to be some + Object ID ??? */ + i_size_write(inode, NCP_BLOCK_SIZE); + } else { + u32 size; + + inode->i_mode = server->m.file_mode; + size = le32_to_cpu(nwi->dataStreamSize); + i_size_write(inode, size); +#ifdef CONFIG_NCPFS_EXTRAS + if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) + && (nwi->attributes & aSHARED)) { + switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { + case aHIDDEN: + if (server->m.flags & NCP_MOUNT_SYMLINKS) { + if (/* (size >= NCP_MIN_SYMLINK_SIZE) + && */ (size <= NCP_MAX_SYMLINK_SIZE)) { + inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; + NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; + break; + } + } + /* FALLTHROUGH */ + case 0: + if (server->m.flags & NCP_MOUNT_EXTRAS) + inode->i_mode |= S_IRUGO; + break; + case aSYSTEM: + if (server->m.flags & NCP_MOUNT_EXTRAS) + inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO; + break; + /* case aSYSTEM|aHIDDEN: */ + default: + /* reserved combination */ + break; + } + } +#endif + } + if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO; +} + +void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo) +{ + NCP_FINFO(inode)->flags = 0; + if (!atomic_read(&NCP_FINFO(inode)->opened)) { + NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; + ncp_update_attrs(inode, nwinfo); + } + + ncp_update_dates(inode, &nwinfo->i); + ncp_update_dirent(inode, nwinfo); +} + +/* + * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes. + */ +static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) +{ + struct ncp_server *server = NCP_SERVER(inode); + + NCP_FINFO(inode)->flags = 0; + + ncp_update_attrs(inode, nwinfo); + + ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode); + + set_nlink(inode, 1); + inode->i_uid = server->m.uid; + inode->i_gid = server->m.gid; + + ncp_update_dates(inode, &nwinfo->i); + ncp_update_inode(inode, nwinfo); +} + +#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) +static const struct inode_operations ncp_symlink_inode_operations = { + .get_link = page_get_link, + .setattr = ncp_notify_change, +}; +#endif + +/* + * Get a new inode. + */ +struct inode * +ncp_iget(struct super_block *sb, struct ncp_entry_info *info) +{ + struct inode *inode; + + if (info == NULL) { + pr_err("%s: info is NULL\n", __func__); + return NULL; + } + + inode = new_inode(sb); + if (inode) { + atomic_set(&NCP_FINFO(inode)->opened, info->opened); + + inode->i_ino = info->ino; + ncp_set_attr(inode, info); + if (S_ISREG(inode->i_mode)) { + inode->i_op = &ncp_file_inode_operations; + inode->i_fop = &ncp_file_operations; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &ncp_dir_inode_operations; + inode->i_fop = &ncp_dir_operations; +#ifdef CONFIG_NCPFS_NFS_NS + } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + init_special_inode(inode, inode->i_mode, + new_decode_dev(info->i.nfs.rdev)); +#endif +#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &ncp_symlink_inode_operations; + inode_nohighmem(inode); + inode->i_data.a_ops = &ncp_symlink_aops; +#endif + } else { + make_bad_inode(inode); + } + insert_inode_hash(inode); + } else + pr_err("%s: iget failed!\n", __func__); + return inode; +} + +static void +ncp_evict_inode(struct inode *inode) +{ + truncate_inode_pages_final(&inode->i_data); + clear_inode(inode); + + if (S_ISDIR(inode->i_mode)) { + ncp_dbg(2, "put directory %ld\n", inode->i_ino); + } + + if (ncp_make_closed(inode) != 0) { + /* We can't do anything but complain. */ + pr_err("%s: could not close\n", __func__); + } +} + +static void ncp_stop_tasks(struct ncp_server *server) { + struct sock* sk = server->ncp_sock->sk; + + lock_sock(sk); + sk->sk_error_report = server->error_report; + sk->sk_data_ready = server->data_ready; + sk->sk_write_space = server->write_space; + release_sock(sk); + del_timer_sync(&server->timeout_tm); + + flush_work(&server->rcv.tq); + if (sk->sk_socket->type == SOCK_STREAM) + flush_work(&server->tx.tq); + else + flush_work(&server->timeout_tq); +} + +static int ncp_show_options(struct seq_file *seq, struct dentry *root) +{ + struct ncp_server *server = NCP_SBP(root->d_sb); + unsigned int tmp; + + if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID)) + seq_printf(seq, ",uid=%u", + from_kuid_munged(&init_user_ns, server->m.uid)); + if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID)) + seq_printf(seq, ",gid=%u", + from_kgid_munged(&init_user_ns, server->m.gid)); + if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID)) + seq_printf(seq, ",owner=%u", + from_kuid_munged(&init_user_ns, server->m.mounted_uid)); + tmp = server->m.file_mode & S_IALLUGO; + if (tmp != NCP_DEFAULT_FILE_MODE) + seq_printf(seq, ",mode=0%o", tmp); + tmp = server->m.dir_mode & S_IALLUGO; + if (tmp != NCP_DEFAULT_DIR_MODE) + seq_printf(seq, ",dirmode=0%o", tmp); + if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) { + tmp = server->m.time_out * 100 / HZ; + seq_printf(seq, ",timeout=%u", tmp); + } + if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT) + seq_printf(seq, ",retry=%u", server->m.retry_count); + if (server->m.flags != 0) + seq_printf(seq, ",flags=%lu", server->m.flags); + if (server->m.wdog_pid != NULL) + seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid)); + + return 0; +} + +static const struct ncp_option ncp_opts[] = { + { "uid", OPT_INT, 'u' }, + { "gid", OPT_INT, 'g' }, + { "owner", OPT_INT, 'o' }, + { "mode", OPT_INT, 'm' }, + { "dirmode", OPT_INT, 'd' }, + { "timeout", OPT_INT, 't' }, + { "retry", OPT_INT, 'r' }, + { "flags", OPT_INT, 'f' }, + { "wdogpid", OPT_INT, 'w' }, + { "ncpfd", OPT_INT, 'n' }, + { "infofd", OPT_INT, 'i' }, /* v5 */ + { "version", OPT_INT, 'v' }, + { NULL, 0, 0 } }; + +static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) { + int optval; + char *optarg; + unsigned long optint; + int version = 0; + int ret; + + data->flags = 0; + data->int_flags = 0; + data->mounted_uid = GLOBAL_ROOT_UID; + data->wdog_pid = NULL; + data->ncp_fd = ~0; + data->time_out = NCP_DEFAULT_TIME_OUT; + data->retry_count = NCP_DEFAULT_RETRY_COUNT; + data->uid = GLOBAL_ROOT_UID; + data->gid = GLOBAL_ROOT_GID; + data->file_mode = NCP_DEFAULT_FILE_MODE; + data->dir_mode = NCP_DEFAULT_DIR_MODE; + data->info_fd = -1; + data->mounted_vol[0] = 0; + + while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) { + ret = optval; + if (ret < 0) + goto err; + switch (optval) { + case 'u': + data->uid = make_kuid(current_user_ns(), optint); + if (!uid_valid(data->uid)) { + ret = -EINVAL; + goto err; + } + break; + case 'g': + data->gid = make_kgid(current_user_ns(), optint); + if (!gid_valid(data->gid)) { + ret = -EINVAL; + goto err; + } + break; + case 'o': + data->mounted_uid = make_kuid(current_user_ns(), optint); + if (!uid_valid(data->mounted_uid)) { + ret = -EINVAL; + goto err; + } + break; + case 'm': + data->file_mode = optint; + break; + case 'd': + data->dir_mode = optint; + break; + case 't': + data->time_out = optint; + break; + case 'r': + data->retry_count = optint; + break; + case 'f': + data->flags = optint; + break; + case 'w': + data->wdog_pid = find_get_pid(optint); + break; + case 'n': + data->ncp_fd = optint; + break; + case 'i': + data->info_fd = optint; + break; + case 'v': + ret = -ECHRNG; + if (optint < NCP_MOUNT_VERSION_V4) + goto err; + if (optint > NCP_MOUNT_VERSION_V5) + goto err; + version = optint; + break; + + } + } + return 0; +err: + put_pid(data->wdog_pid); + data->wdog_pid = NULL; + return ret; +} + +static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) +{ + struct ncp_mount_data_kernel data; + struct ncp_server *server; + struct inode *root_inode; + struct socket *sock; + int error; + int default_bufsize; +#ifdef CONFIG_NCPFS_PACKET_SIGNING + int options; +#endif + struct ncp_entry_info finfo; + + memset(&data, 0, sizeof(data)); + server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); + if (!server) + return -ENOMEM; + sb->s_fs_info = server; + + error = -EFAULT; + if (raw_data == NULL) + goto out; + switch (*(int*)raw_data) { + case NCP_MOUNT_VERSION: + { + struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; + + data.flags = md->flags; + data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; + data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); + data.wdog_pid = find_get_pid(md->wdog_pid); + data.ncp_fd = md->ncp_fd; + data.time_out = md->time_out; + data.retry_count = md->retry_count; + data.uid = make_kuid(current_user_ns(), md->uid); + data.gid = make_kgid(current_user_ns(), md->gid); + data.file_mode = md->file_mode; + data.dir_mode = md->dir_mode; + data.info_fd = -1; + memcpy(data.mounted_vol, md->mounted_vol, + NCP_VOLNAME_LEN+1); + } + break; + case NCP_MOUNT_VERSION_V4: + { + struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; + + data.flags = md->flags; + data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); + data.wdog_pid = find_get_pid(md->wdog_pid); + data.ncp_fd = md->ncp_fd; + data.time_out = md->time_out; + data.retry_count = md->retry_count; + data.uid = make_kuid(current_user_ns(), md->uid); + data.gid = make_kgid(current_user_ns(), md->gid); + data.file_mode = md->file_mode; + data.dir_mode = md->dir_mode; + data.info_fd = -1; + } + break; + default: + error = -ECHRNG; + if (memcmp(raw_data, "vers", 4) == 0) { + error = ncp_parse_options(&data, raw_data); + } + if (error) + goto out; + break; + } + error = -EINVAL; + if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) || + !gid_valid(data.gid)) + goto out; + sock = sockfd_lookup(data.ncp_fd, &error); + if (!sock) + goto out; + + if (sock->type == SOCK_STREAM) + default_bufsize = 0xF000; + else + default_bufsize = 1024; + + sb->s_flags |= MS_NODIRATIME; /* probably even noatime */ + sb->s_maxbytes = 0xFFFFFFFFU; + sb->s_blocksize = 1024; /* Eh... Is this correct? */ + sb->s_blocksize_bits = 10; + sb->s_magic = NCP_SUPER_MAGIC; + sb->s_op = &ncp_sops; + sb->s_d_op = &ncp_dentry_operations; + + server = NCP_SBP(sb); + memset(server, 0, sizeof(*server)); + + error = super_setup_bdi(sb); + if (error) + goto out_fput; + + server->ncp_sock = sock; + + if (data.info_fd != -1) { + struct socket *info_sock = sockfd_lookup(data.info_fd, &error); + if (!info_sock) + goto out_fput; + server->info_sock = info_sock; + error = -EBADFD; + if (info_sock->type != SOCK_STREAM) + goto out_fput2; + } + +/* server->lock = 0; */ + mutex_init(&server->mutex); + server->packet = NULL; +/* server->buffer_size = 0; */ +/* server->conn_status = 0; */ +/* server->root_dentry = NULL; */ +/* server->root_setuped = 0; */ + mutex_init(&server->root_setup_lock); +#ifdef CONFIG_NCPFS_PACKET_SIGNING +/* server->sign_wanted = 0; */ +/* server->sign_active = 0; */ +#endif + init_rwsem(&server->auth_rwsem); + server->auth.auth_type = NCP_AUTH_NONE; +/* server->auth.object_name_len = 0; */ +/* server->auth.object_name = NULL; */ +/* server->auth.object_type = 0; */ +/* server->priv.len = 0; */ +/* server->priv.data = NULL; */ + + server->m = data; + /* Although anything producing this is buggy, it happens + now because of PATH_MAX changes.. */ + if (server->m.time_out < 1) { + server->m.time_out = 10; + pr_info("You need to recompile your ncpfs utils..\n"); + } + server->m.time_out = server->m.time_out * HZ / 100; + server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; + server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR; + +#ifdef CONFIG_NCPFS_NLS + /* load the default NLS charsets */ + server->nls_vol = load_nls_default(); + server->nls_io = load_nls_default(); +#endif /* CONFIG_NCPFS_NLS */ + + atomic_set(&server->dentry_ttl, 0); /* no caching */ + + INIT_LIST_HEAD(&server->tx.requests); + mutex_init(&server->rcv.creq_mutex); + server->tx.creq = NULL; + server->rcv.creq = NULL; + + timer_setup(&server->timeout_tm, ncpdgram_timeout_call, 0); +#undef NCP_PACKET_SIZE +#define NCP_PACKET_SIZE 131072 + error = -ENOMEM; + server->packet_size = NCP_PACKET_SIZE; + server->packet = vmalloc(NCP_PACKET_SIZE); + if (server->packet == NULL) + goto out_nls; + server->txbuf = vmalloc(NCP_PACKET_SIZE); + if (server->txbuf == NULL) + goto out_packet; + server->rxbuf = vmalloc(NCP_PACKET_SIZE); + if (server->rxbuf == NULL) + goto out_txbuf; + + lock_sock(sock->sk); + server->data_ready = sock->sk->sk_data_ready; + server->write_space = sock->sk->sk_write_space; + server->error_report = sock->sk->sk_error_report; + sock->sk->sk_user_data = server; + sock->sk->sk_data_ready = ncp_tcp_data_ready; + sock->sk->sk_error_report = ncp_tcp_error_report; + if (sock->type == SOCK_STREAM) { + server->rcv.ptr = (unsigned char*)&server->rcv.buf; + server->rcv.len = 10; + server->rcv.state = 0; + INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); + INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); + sock->sk->sk_write_space = ncp_tcp_write_space; + } else { + INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); + INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); + } + release_sock(sock->sk); + + ncp_lock_server(server); + error = ncp_connect(server); + ncp_unlock_server(server); + if (error < 0) + goto out_rxbuf; + ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb)); + + error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (ncp_negotiate_size_and_options(server, default_bufsize, + NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) + { + if (options != NCP_DEFAULT_OPTIONS) + { + if (ncp_negotiate_size_and_options(server, + default_bufsize, + options & 2, + &(server->buffer_size), &options) != 0) + + { + goto out_disconnect; + } + } + ncp_lock_server(server); + if (options & 2) + server->sign_wanted = 1; + ncp_unlock_server(server); + } + else +#endif /* CONFIG_NCPFS_PACKET_SIGNING */ + if (ncp_negotiate_buffersize(server, default_bufsize, + &(server->buffer_size)) != 0) + goto out_disconnect; + ncp_dbg(1, "bufsize = %d\n", server->buffer_size); + + memset(&finfo, 0, sizeof(finfo)); + finfo.i.attributes = aDIR; + finfo.i.dataStreamSize = 0; /* ignored */ + finfo.i.dirEntNum = 0; + finfo.i.DosDirNum = 0; +#ifdef CONFIG_NCPFS_SMALLDOS + finfo.i.NSCreator = NW_NS_DOS; +#endif + finfo.volume = NCP_NUMBER_OF_VOLUMES; + /* set dates of mountpoint to Jan 1, 1986; 00:00 */ + finfo.i.creationTime = finfo.i.modifyTime + = cpu_to_le16(0x0000); + finfo.i.creationDate = finfo.i.modifyDate + = finfo.i.lastAccessDate + = cpu_to_le16(0x0C21); + finfo.i.nameLen = 0; + finfo.i.entryName[0] = '\0'; + + finfo.opened = 0; + finfo.ino = 2; /* tradition */ + + server->name_space[finfo.volume] = NW_NS_DOS; + + error = -ENOMEM; + root_inode = ncp_iget(sb, &finfo); + if (!root_inode) + goto out_disconnect; + ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber); + sb->s_root = d_make_root(root_inode); + if (!sb->s_root) + goto out_disconnect; + return 0; + +out_disconnect: + ncp_lock_server(server); + ncp_disconnect(server); + ncp_unlock_server(server); +out_rxbuf: + ncp_stop_tasks(server); + vfree(server->rxbuf); +out_txbuf: + vfree(server->txbuf); +out_packet: + vfree(server->packet); +out_nls: +#ifdef CONFIG_NCPFS_NLS + unload_nls(server->nls_io); + unload_nls(server->nls_vol); +#endif + mutex_destroy(&server->rcv.creq_mutex); + mutex_destroy(&server->root_setup_lock); + mutex_destroy(&server->mutex); +out_fput2: + if (server->info_sock) + sockfd_put(server->info_sock); +out_fput: + sockfd_put(sock); +out: + put_pid(data.wdog_pid); + sb->s_fs_info = NULL; + kfree(server); + return error; +} + +static void delayed_free(struct rcu_head *p) +{ + struct ncp_server *server = container_of(p, struct ncp_server, rcu); +#ifdef CONFIG_NCPFS_NLS + /* unload the NLS charsets */ + unload_nls(server->nls_vol); + unload_nls(server->nls_io); +#endif /* CONFIG_NCPFS_NLS */ + kfree(server); +} + +static void ncp_put_super(struct super_block *sb) +{ + struct ncp_server *server = NCP_SBP(sb); + + ncp_lock_server(server); + ncp_disconnect(server); + ncp_unlock_server(server); + + ncp_stop_tasks(server); + + mutex_destroy(&server->rcv.creq_mutex); + mutex_destroy(&server->root_setup_lock); + mutex_destroy(&server->mutex); + + if (server->info_sock) + sockfd_put(server->info_sock); + sockfd_put(server->ncp_sock); + kill_pid(server->m.wdog_pid, SIGTERM, 1); + put_pid(server->m.wdog_pid); + + kfree(server->priv.data); + kfree(server->auth.object_name); + vfree(server->rxbuf); + vfree(server->txbuf); + vfree(server->packet); + call_rcu(&server->rcu, delayed_free); +} + +static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct dentry* d; + struct inode* i; + struct ncp_inode_info* ni; + struct ncp_server* s; + struct ncp_volume_info vi; + struct super_block *sb = dentry->d_sb; + int err; + __u8 dh; + + d = sb->s_root; + if (!d) { + goto dflt; + } + i = d_inode(d); + if (!i) { + goto dflt; + } + ni = NCP_FINFO(i); + if (!ni) { + goto dflt; + } + s = NCP_SBP(sb); + if (!s) { + goto dflt; + } + if (!s->m.mounted_vol[0]) { + goto dflt; + } + + err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh); + if (err) { + goto dflt; + } + err = ncp_get_directory_info(s, dh, &vi); + ncp_dirhandle_free(s, dh); + if (err) { + goto dflt; + } + buf->f_type = NCP_SUPER_MAGIC; + buf->f_bsize = vi.sectors_per_block * 512; + buf->f_blocks = vi.total_blocks; + buf->f_bfree = vi.free_blocks; + buf->f_bavail = vi.free_blocks; + buf->f_files = vi.total_dir_entries; + buf->f_ffree = vi.available_dir_entries; + buf->f_namelen = 12; + return 0; + + /* We cannot say how much disk space is left on a mounted + NetWare Server, because free space is distributed over + volumes, and the current user might have disk quotas. So + free space is not that simple to determine. Our decision + here is to err conservatively. */ + +dflt:; + buf->f_type = NCP_SUPER_MAGIC; + buf->f_bsize = NCP_BLOCK_SIZE; + buf->f_blocks = 0; + buf->f_bfree = 0; + buf->f_bavail = 0; + buf->f_namelen = 12; + return 0; +} + +int ncp_notify_change(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = d_inode(dentry); + int result = 0; + __le32 info_mask; + struct nw_modify_dos_info info; + struct ncp_server *server; + + result = -EIO; + + server = NCP_SERVER(inode); + if (!server) /* How this could happen? */ + goto out; + + result = -EPERM; + if (IS_DEADDIR(d_inode(dentry))) + goto out; + + /* ageing the dentry to force validation */ + ncp_age_dentry(server, dentry); + + result = setattr_prepare(dentry, attr); + if (result < 0) + goto out; + + result = -EPERM; + if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid)) + goto out; + + if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid)) + goto out; + + if (((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & + ~(S_IFREG | S_IFDIR | S_IRWXUGO)))) + goto out; + + info_mask = 0; + memset(&info, 0, sizeof(info)); + +#if 1 + if ((attr->ia_valid & ATTR_MODE) != 0) + { + umode_t newmode = attr->ia_mode; + + info_mask |= DM_ATTRIBUTES; + + if (S_ISDIR(inode->i_mode)) { + newmode &= server->m.dir_mode; + } else { +#ifdef CONFIG_NCPFS_EXTRAS + if (server->m.flags & NCP_MOUNT_EXTRAS) { + /* any non-default execute bit set */ + if (newmode & ~server->m.file_mode & S_IXUGO) + info.attributes |= aSHARED | aSYSTEM; + /* read for group/world and not in default file_mode */ + else if (newmode & ~server->m.file_mode & S_IRUGO) + info.attributes |= aSHARED; + } else +#endif + newmode &= server->m.file_mode; + } + if (newmode & S_IWUGO) + info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + else + info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); + +#ifdef CONFIG_NCPFS_NFS_NS + if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) { + result = ncp_modify_nfs_info(server, + NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum, + attr->ia_mode, 0); + if (result != 0) + goto out; + info.attributes &= ~(aSHARED | aSYSTEM); + { + /* mark partial success */ + struct iattr tmpattr; + + tmpattr.ia_valid = ATTR_MODE; + tmpattr.ia_mode = attr->ia_mode; + + setattr_copy(inode, &tmpattr); + mark_inode_dirty(inode); + } + } +#endif + } +#endif + + /* Do SIZE before attributes, otherwise mtime together with size does not work... + */ + if ((attr->ia_valid & ATTR_SIZE) != 0) { + int written; + + ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size); + + if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { + result = -EACCES; + goto out; + } + ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + attr->ia_size, 0, "", &written); + + /* According to ndir, the changes only take effect after + closing the file */ + ncp_inode_close(inode); + result = ncp_make_closed(inode); + if (result) + goto out; + + if (attr->ia_size != i_size_read(inode)) { + truncate_setsize(inode, attr->ia_size); + mark_inode_dirty(inode); + } + } + if ((attr->ia_valid & ATTR_CTIME) != 0) { + info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE); + ncp_date_unix2dos(attr->ia_ctime.tv_sec, + &info.creationTime, &info.creationDate); + } + if ((attr->ia_valid & ATTR_MTIME) != 0) { + info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); + ncp_date_unix2dos(attr->ia_mtime.tv_sec, + &info.modifyTime, &info.modifyDate); + } + if ((attr->ia_valid & ATTR_ATIME) != 0) { + __le16 dummy; + info_mask |= (DM_LAST_ACCESS_DATE); + ncp_date_unix2dos(attr->ia_atime.tv_sec, + &dummy, &info.lastAccessDate); + } + if (info_mask != 0) { + result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), + inode, info_mask, &info); + if (result != 0) { + if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { + /* NetWare seems not to allow this. I + do not know why. So, just tell the + user everything went fine. This is + a terrible hack, but I do not know + how to do this correctly. */ + result = 0; + } else + goto out; + } +#ifdef CONFIG_NCPFS_STRONG + if ((!result) && (info_mask & DM_ATTRIBUTES)) + NCP_FINFO(inode)->nwattr = info.attributes; +#endif + } + if (result) + goto out; + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + +out: + if (result > 0) + result = -EACCES; + return result; +} + +static struct dentry *ncp_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) +{ + return mount_nodev(fs_type, flags, data, ncp_fill_super); +} + +static struct file_system_type ncp_fs_type = { + .owner = THIS_MODULE, + .name = "ncpfs", + .mount = ncp_mount, + .kill_sb = kill_anon_super, + .fs_flags = FS_BINARY_MOUNTDATA, +}; +MODULE_ALIAS_FS("ncpfs"); + +static int __init init_ncp_fs(void) +{ + int err; + ncp_dbg(1, "called\n"); + + err = init_inodecache(); + if (err) + goto out1; + err = register_filesystem(&ncp_fs_type); + if (err) + goto out; + return 0; +out: + destroy_inodecache(); +out1: + return err; +} + +static void __exit exit_ncp_fs(void) +{ + ncp_dbg(1, "called\n"); + unregister_filesystem(&ncp_fs_type); + destroy_inodecache(); +} + +module_init(init_ncp_fs) +module_exit(exit_ncp_fs) +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/ncpfs/ioctl.c b/drivers/staging/ncpfs/ioctl.c new file mode 100644 index 000000000000..d378b98cd7b6 --- /dev/null +++ b/drivers/staging/ncpfs/ioctl.c @@ -0,0 +1,923 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ioctl.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998, 1999 Wolfram Pienkoss for NLS + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ncp_fs.h" + +/* maximum limit for ncp_objectname_ioctl */ +#define NCP_OBJECT_NAME_MAX_LEN 4096 +/* maximum limit for ncp_privatedata_ioctl */ +#define NCP_PRIVATE_DATA_MAX_LEN 8192 +/* maximum negotiable packet size */ +#define NCP_PACKET_SIZE_INTERNAL 65536 + +static int +ncp_get_fs_info(struct ncp_server * server, struct inode *inode, + struct ncp_fs_info __user *arg) +{ + struct ncp_fs_info info; + + if (copy_from_user(&info, arg, sizeof(info))) + return -EFAULT; + + if (info.version != NCP_GET_FS_INFO_VERSION) { + ncp_dbg(1, "info.version invalid: %d\n", info.version); + return -EINVAL; + } + /* TODO: info.addr = server->m.serv_addr; */ + SET_UID(info.mounted_uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid)); + info.connection = server->connection; + info.buffer_size = server->buffer_size; + info.volume_number = NCP_FINFO(inode)->volNumber; + info.directory_id = NCP_FINFO(inode)->DosDirNum; + + if (copy_to_user(arg, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +static int +ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode, + struct ncp_fs_info_v2 __user * arg) +{ + struct ncp_fs_info_v2 info2; + + if (copy_from_user(&info2, arg, sizeof(info2))) + return -EFAULT; + + if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { + ncp_dbg(1, "info.version invalid: %d\n", info2.version); + return -EINVAL; + } + info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); + info2.connection = server->connection; + info2.buffer_size = server->buffer_size; + info2.volume_number = NCP_FINFO(inode)->volNumber; + info2.directory_id = NCP_FINFO(inode)->DosDirNum; + info2.dummy1 = info2.dummy2 = info2.dummy3 = 0; + + if (copy_to_user(arg, &info2, sizeof(info2))) + return -EFAULT; + return 0; +} + +#ifdef CONFIG_COMPAT +struct compat_ncp_objectname_ioctl +{ + s32 auth_type; + u32 object_name_len; + compat_caddr_t object_name; /* a userspace data, in most cases user name */ +}; + +struct compat_ncp_fs_info_v2 { + s32 version; + u32 mounted_uid; + u32 connection; + u32 buffer_size; + + u32 volume_number; + u32 directory_id; + + u32 dummy1; + u32 dummy2; + u32 dummy3; +}; + +struct compat_ncp_ioctl_request { + u32 function; + u32 size; + compat_caddr_t data; +}; + +struct compat_ncp_privatedata_ioctl +{ + u32 len; + compat_caddr_t data; /* ~1000 for NDS */ +}; + +#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct compat_ncp_fs_info_v2) +#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct compat_ncp_ioctl_request) +#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct compat_ncp_objectname_ioctl) +#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct compat_ncp_objectname_ioctl) +#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct compat_ncp_privatedata_ioctl) +#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl) + +static int +ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode, + struct compat_ncp_fs_info_v2 __user * arg) +{ + struct compat_ncp_fs_info_v2 info2; + + if (copy_from_user(&info2, arg, sizeof(info2))) + return -EFAULT; + + if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { + ncp_dbg(1, "info.version invalid: %d\n", info2.version); + return -EINVAL; + } + info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); + info2.connection = server->connection; + info2.buffer_size = server->buffer_size; + info2.volume_number = NCP_FINFO(inode)->volNumber; + info2.directory_id = NCP_FINFO(inode)->DosDirNum; + info2.dummy1 = info2.dummy2 = info2.dummy3 = 0; + + if (copy_to_user(arg, &info2, sizeof(info2))) + return -EFAULT; + return 0; +} +#endif + +#define NCP_IOC_GETMOUNTUID16 _IOW('n', 2, u16) +#define NCP_IOC_GETMOUNTUID32 _IOW('n', 2, u32) +#define NCP_IOC_GETMOUNTUID64 _IOW('n', 2, u64) + +#ifdef CONFIG_NCPFS_NLS +/* Here we are select the iocharset and the codepage for NLS. + * Thanks Petr Vandrovec for idea and many hints. + */ +static int +ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) +{ + struct ncp_nls_ioctl user; + struct nls_table *codepage; + struct nls_table *iocharset; + struct nls_table *oldset_io; + struct nls_table *oldset_cp; + int utf8; + int err; + + if (copy_from_user(&user, arg, sizeof(user))) + return -EFAULT; + + codepage = NULL; + user.codepage[NCP_IOCSNAME_LEN] = 0; + if (!user.codepage[0] || !strcmp(user.codepage, "default")) + codepage = load_nls_default(); + else { + codepage = load_nls(user.codepage); + if (!codepage) { + return -EBADRQC; + } + } + + iocharset = NULL; + user.iocharset[NCP_IOCSNAME_LEN] = 0; + if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) { + iocharset = load_nls_default(); + utf8 = 0; + } else if (!strcmp(user.iocharset, "utf8")) { + iocharset = load_nls_default(); + utf8 = 1; + } else { + iocharset = load_nls(user.iocharset); + if (!iocharset) { + unload_nls(codepage); + return -EBADRQC; + } + utf8 = 0; + } + + mutex_lock(&server->root_setup_lock); + if (server->root_setuped) { + oldset_cp = codepage; + oldset_io = iocharset; + err = -EBUSY; + } else { + if (utf8) + NCP_SET_FLAG(server, NCP_FLAG_UTF8); + else + NCP_CLR_FLAG(server, NCP_FLAG_UTF8); + oldset_cp = server->nls_vol; + server->nls_vol = codepage; + oldset_io = server->nls_io; + server->nls_io = iocharset; + err = 0; + } + mutex_unlock(&server->root_setup_lock); + unload_nls(oldset_cp); + unload_nls(oldset_io); + + return err; +} + +static int +ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) +{ + struct ncp_nls_ioctl user; + int len; + + memset(&user, 0, sizeof(user)); + mutex_lock(&server->root_setup_lock); + if (server->nls_vol && server->nls_vol->charset) { + len = strlen(server->nls_vol->charset); + if (len > NCP_IOCSNAME_LEN) + len = NCP_IOCSNAME_LEN; + strncpy(user.codepage, server->nls_vol->charset, len); + user.codepage[len] = 0; + } + + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) + strcpy(user.iocharset, "utf8"); + else if (server->nls_io && server->nls_io->charset) { + len = strlen(server->nls_io->charset); + if (len > NCP_IOCSNAME_LEN) + len = NCP_IOCSNAME_LEN; + strncpy(user.iocharset, server->nls_io->charset, len); + user.iocharset[len] = 0; + } + mutex_unlock(&server->root_setup_lock); + + if (copy_to_user(arg, &user, sizeof(user))) + return -EFAULT; + return 0; +} +#endif /* CONFIG_NCPFS_NLS */ + +static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg) +{ + struct ncp_server *server = NCP_SERVER(inode); + int result; + struct ncp_ioctl_request request; + char* bouncebuffer; + void __user *argp = (void __user *)arg; + + switch (cmd) { +#ifdef CONFIG_COMPAT + case NCP_IOC_NCPREQUEST_32: +#endif + case NCP_IOC_NCPREQUEST: +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_NCPREQUEST_32) { + struct compat_ncp_ioctl_request request32; + if (copy_from_user(&request32, argp, sizeof(request32))) + return -EFAULT; + request.function = request32.function; + request.size = request32.size; + request.data = compat_ptr(request32.data); + } else +#endif + if (copy_from_user(&request, argp, sizeof(request))) + return -EFAULT; + + if ((request.function > 255) + || (request.size > + NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) { + return -EINVAL; + } + bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL); + if (!bouncebuffer) + return -ENOMEM; + if (copy_from_user(bouncebuffer, request.data, request.size)) { + vfree(bouncebuffer); + return -EFAULT; + } + ncp_lock_server(server); + + /* FIXME: We hack around in the server's structures + here to be able to use ncp_request */ + + server->has_subfunction = 0; + server->current_size = request.size; + memcpy(server->packet, bouncebuffer, request.size); + + result = ncp_request2(server, request.function, + bouncebuffer, NCP_PACKET_SIZE_INTERNAL); + if (result < 0) + result = -EIO; + else + result = server->reply_size; + ncp_unlock_server(server); + ncp_dbg(1, "copy %d bytes\n", result); + if (result >= 0) + if (copy_to_user(request.data, bouncebuffer, result)) + result = -EFAULT; + vfree(bouncebuffer); + return result; + + case NCP_IOC_CONN_LOGGED_IN: + + if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE)) + return -EINVAL; + mutex_lock(&server->root_setup_lock); + if (server->root_setuped) + result = -EBUSY; + else { + result = ncp_conn_logged_in(inode->i_sb); + if (result == 0) + server->root_setuped = 1; + } + mutex_unlock(&server->root_setup_lock); + return result; + + case NCP_IOC_GET_FS_INFO: + return ncp_get_fs_info(server, inode, argp); + + case NCP_IOC_GET_FS_INFO_V2: + return ncp_get_fs_info_v2(server, inode, argp); + +#ifdef CONFIG_COMPAT + case NCP_IOC_GET_FS_INFO_V2_32: + return ncp_get_compat_fs_info_v2(server, inode, argp); +#endif + /* we have too many combinations of CONFIG_COMPAT, + * CONFIG_64BIT and CONFIG_UID16, so just handle + * any of the possible ioctls */ + case NCP_IOC_GETMOUNTUID16: + { + u16 uid; + + SET_UID(uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid)); + if (put_user(uid, (u16 __user *)argp)) + return -EFAULT; + return 0; + } + case NCP_IOC_GETMOUNTUID32: + { + uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); + if (put_user(uid, (u32 __user *)argp)) + return -EFAULT; + return 0; + } + case NCP_IOC_GETMOUNTUID64: + { + uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); + if (put_user(uid, (u64 __user *)argp)) + return -EFAULT; + return 0; + } + case NCP_IOC_GETROOT: + { + struct ncp_setroot_ioctl sr; + + result = -EACCES; + mutex_lock(&server->root_setup_lock); + if (server->m.mounted_vol[0]) { + struct dentry* dentry = inode->i_sb->s_root; + + if (dentry) { + struct inode* s_inode = d_inode(dentry); + + if (s_inode) { + sr.volNumber = NCP_FINFO(s_inode)->volNumber; + sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum; + sr.namespace = server->name_space[sr.volNumber]; + result = 0; + } else + ncp_dbg(1, "d_inode(s_root)==NULL\n"); + } else + ncp_dbg(1, "s_root==NULL\n"); + } else { + sr.volNumber = -1; + sr.namespace = 0; + sr.dirEntNum = 0; + result = 0; + } + mutex_unlock(&server->root_setup_lock); + if (!result && copy_to_user(argp, &sr, sizeof(sr))) + result = -EFAULT; + return result; + } + + case NCP_IOC_SETROOT: + { + struct ncp_setroot_ioctl sr; + __u32 vnum; + __le32 de; + __le32 dosde; + struct dentry* dentry; + + if (copy_from_user(&sr, argp, sizeof(sr))) + return -EFAULT; + mutex_lock(&server->root_setup_lock); + if (server->root_setuped) + result = -EBUSY; + else { + if (sr.volNumber < 0) { + server->m.mounted_vol[0] = 0; + vnum = NCP_NUMBER_OF_VOLUMES; + de = 0; + dosde = 0; + result = 0; + } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) { + result = -EINVAL; + } else if (ncp_mount_subdir(server, sr.volNumber, + sr.namespace, sr.dirEntNum, + &vnum, &de, &dosde)) { + result = -ENOENT; + } else + result = 0; + + if (result == 0) { + dentry = inode->i_sb->s_root; + if (dentry) { + struct inode* s_inode = d_inode(dentry); + + if (s_inode) { + NCP_FINFO(s_inode)->volNumber = vnum; + NCP_FINFO(s_inode)->dirEntNum = de; + NCP_FINFO(s_inode)->DosDirNum = dosde; + server->root_setuped = 1; + } else { + ncp_dbg(1, "d_inode(s_root)==NULL\n"); + result = -EIO; + } + } else { + ncp_dbg(1, "s_root==NULL\n"); + result = -EIO; + } + } + } + mutex_unlock(&server->root_setup_lock); + + return result; + } + +#ifdef CONFIG_NCPFS_PACKET_SIGNING + case NCP_IOC_SIGN_INIT: + { + struct ncp_sign_init sign; + + if (argp) + if (copy_from_user(&sign, argp, sizeof(sign))) + return -EFAULT; + ncp_lock_server(server); + mutex_lock(&server->rcv.creq_mutex); + if (argp) { + if (server->sign_wanted) { + memcpy(server->sign_root,sign.sign_root,8); + memcpy(server->sign_last,sign.sign_last,16); + server->sign_active = 1; + } + /* ignore when signatures not wanted */ + } else { + server->sign_active = 0; + } + mutex_unlock(&server->rcv.creq_mutex); + ncp_unlock_server(server); + return 0; + } + + case NCP_IOC_SIGN_WANTED: + { + int state; + + ncp_lock_server(server); + state = server->sign_wanted; + ncp_unlock_server(server); + if (put_user(state, (int __user *)argp)) + return -EFAULT; + return 0; + } + + case NCP_IOC_SET_SIGN_WANTED: + { + int newstate; + + /* get only low 8 bits... */ + if (get_user(newstate, (unsigned char __user *)argp)) + return -EFAULT; + result = 0; + ncp_lock_server(server); + if (server->sign_active) { + /* cannot turn signatures OFF when active */ + if (!newstate) + result = -EINVAL; + } else { + server->sign_wanted = newstate != 0; + } + ncp_unlock_server(server); + return result; + } + +#endif /* CONFIG_NCPFS_PACKET_SIGNING */ + +#ifdef CONFIG_NCPFS_IOCTL_LOCKING + case NCP_IOC_LOCKUNLOCK: + { + struct ncp_lock_ioctl rqdata; + + if (copy_from_user(&rqdata, argp, sizeof(rqdata))) + return -EFAULT; + if (rqdata.origin != 0) + return -EINVAL; + /* check for cmd */ + switch (rqdata.cmd) { + case NCP_LOCK_EX: + case NCP_LOCK_SH: + if (rqdata.timeout < 0) + return -EINVAL; + if (rqdata.timeout == 0) + rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; + else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT) + rqdata.timeout = NCP_LOCK_MAX_TIMEOUT; + break; + case NCP_LOCK_LOG: + rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; /* has no effect */ + case NCP_LOCK_CLEAR: + break; + default: + return -EINVAL; + } + /* locking needs both read and write access */ + if ((result = ncp_make_open(inode, O_RDWR)) != 0) + { + return result; + } + result = -EISDIR; + if (!S_ISREG(inode->i_mode)) + goto outrel; + if (rqdata.cmd == NCP_LOCK_CLEAR) + { + result = ncp_ClearPhysicalRecord(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + rqdata.offset, + rqdata.length); + if (result > 0) result = 0; /* no such lock */ + } + else + { + int lockcmd; + + switch (rqdata.cmd) + { + case NCP_LOCK_EX: lockcmd=1; break; + case NCP_LOCK_SH: lockcmd=3; break; + default: lockcmd=0; break; + } + result = ncp_LogPhysicalRecord(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + lockcmd, + rqdata.offset, + rqdata.length, + rqdata.timeout); + if (result > 0) result = -EAGAIN; + } +outrel: + ncp_inode_close(inode); + return result; + } +#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ + +#ifdef CONFIG_COMPAT + case NCP_IOC_GETOBJECTNAME_32: + { + struct compat_ncp_objectname_ioctl user; + size_t outl; + + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + down_read(&server->auth_rwsem); + user.auth_type = server->auth.auth_type; + outl = user.object_name_len; + user.object_name_len = server->auth.object_name_len; + if (outl > user.object_name_len) + outl = user.object_name_len; + result = 0; + if (outl) { + if (copy_to_user(compat_ptr(user.object_name), + server->auth.object_name, + outl)) + result = -EFAULT; + } + up_read(&server->auth_rwsem); + if (!result && copy_to_user(argp, &user, sizeof(user))) + result = -EFAULT; + return result; + } +#endif + + case NCP_IOC_GETOBJECTNAME: + { + struct ncp_objectname_ioctl user; + size_t outl; + + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + down_read(&server->auth_rwsem); + user.auth_type = server->auth.auth_type; + outl = user.object_name_len; + user.object_name_len = server->auth.object_name_len; + if (outl > user.object_name_len) + outl = user.object_name_len; + result = 0; + if (outl) { + if (copy_to_user(user.object_name, + server->auth.object_name, + outl)) + result = -EFAULT; + } + up_read(&server->auth_rwsem); + if (!result && copy_to_user(argp, &user, sizeof(user))) + result = -EFAULT; + return result; + } + +#ifdef CONFIG_COMPAT + case NCP_IOC_SETOBJECTNAME_32: +#endif + case NCP_IOC_SETOBJECTNAME: + { + struct ncp_objectname_ioctl user; + void* newname; + void* oldname; + size_t oldnamelen; + void* oldprivate; + size_t oldprivatelen; + +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_SETOBJECTNAME_32) { + struct compat_ncp_objectname_ioctl user32; + if (copy_from_user(&user32, argp, sizeof(user32))) + return -EFAULT; + user.auth_type = user32.auth_type; + user.object_name_len = user32.object_name_len; + user.object_name = compat_ptr(user32.object_name); + } else +#endif + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + + if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) + return -ENOMEM; + if (user.object_name_len) { + newname = memdup_user(user.object_name, + user.object_name_len); + if (IS_ERR(newname)) + return PTR_ERR(newname); + } else { + newname = NULL; + } + down_write(&server->auth_rwsem); + oldname = server->auth.object_name; + oldnamelen = server->auth.object_name_len; + oldprivate = server->priv.data; + oldprivatelen = server->priv.len; + server->auth.auth_type = user.auth_type; + server->auth.object_name_len = user.object_name_len; + server->auth.object_name = newname; + server->priv.len = 0; + server->priv.data = NULL; + up_write(&server->auth_rwsem); + kfree(oldprivate); + kfree(oldname); + return 0; + } + +#ifdef CONFIG_COMPAT + case NCP_IOC_GETPRIVATEDATA_32: +#endif + case NCP_IOC_GETPRIVATEDATA: + { + struct ncp_privatedata_ioctl user; + size_t outl; + +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_GETPRIVATEDATA_32) { + struct compat_ncp_privatedata_ioctl user32; + if (copy_from_user(&user32, argp, sizeof(user32))) + return -EFAULT; + user.len = user32.len; + user.data = compat_ptr(user32.data); + } else +#endif + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + + down_read(&server->auth_rwsem); + outl = user.len; + user.len = server->priv.len; + if (outl > user.len) outl = user.len; + result = 0; + if (outl) { + if (copy_to_user(user.data, + server->priv.data, + outl)) + result = -EFAULT; + } + up_read(&server->auth_rwsem); + if (result) + return result; +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_GETPRIVATEDATA_32) { + struct compat_ncp_privatedata_ioctl user32; + user32.len = user.len; + user32.data = (unsigned long) user.data; + if (copy_to_user(argp, &user32, sizeof(user32))) + return -EFAULT; + } else +#endif + if (copy_to_user(argp, &user, sizeof(user))) + return -EFAULT; + + return 0; + } + +#ifdef CONFIG_COMPAT + case NCP_IOC_SETPRIVATEDATA_32: +#endif + case NCP_IOC_SETPRIVATEDATA: + { + struct ncp_privatedata_ioctl user; + void* new; + void* old; + size_t oldlen; + +#ifdef CONFIG_COMPAT + if (cmd == NCP_IOC_SETPRIVATEDATA_32) { + struct compat_ncp_privatedata_ioctl user32; + if (copy_from_user(&user32, argp, sizeof(user32))) + return -EFAULT; + user.len = user32.len; + user.data = compat_ptr(user32.data); + } else +#endif + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + + if (user.len > NCP_PRIVATE_DATA_MAX_LEN) + return -ENOMEM; + if (user.len) { + new = memdup_user(user.data, user.len); + if (IS_ERR(new)) + return PTR_ERR(new); + } else { + new = NULL; + } + down_write(&server->auth_rwsem); + old = server->priv.data; + oldlen = server->priv.len; + server->priv.len = user.len; + server->priv.data = new; + up_write(&server->auth_rwsem); + kfree(old); + return 0; + } + +#ifdef CONFIG_NCPFS_NLS + case NCP_IOC_SETCHARSETS: + return ncp_set_charsets(server, argp); + + case NCP_IOC_GETCHARSETS: + return ncp_get_charsets(server, argp); + +#endif /* CONFIG_NCPFS_NLS */ + + case NCP_IOC_SETDENTRYTTL: + { + u_int32_t user; + + if (copy_from_user(&user, argp, sizeof(user))) + return -EFAULT; + /* 20 secs at most... */ + if (user > 20000) + return -EINVAL; + user = (user * HZ) / 1000; + atomic_set(&server->dentry_ttl, user); + return 0; + } + + case NCP_IOC_GETDENTRYTTL: + { + u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ; + if (copy_to_user(argp, &user, sizeof(user))) + return -EFAULT; + return 0; + } + + } + return -EINVAL; +} + +long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct ncp_server *server = NCP_SERVER(inode); + kuid_t uid = current_uid(); + int need_drop_write = 0; + long ret; + + switch (cmd) { + case NCP_IOC_SETCHARSETS: + case NCP_IOC_CONN_LOGGED_IN: + case NCP_IOC_SETROOT: + if (!capable(CAP_SYS_ADMIN)) { + ret = -EPERM; + goto out; + } + break; + } + if (!uid_eq(server->m.mounted_uid, uid)) { + switch (cmd) { + /* + * Only mount owner can issue these ioctls. Information + * necessary to authenticate to other NDS servers are + * stored here. + */ + case NCP_IOC_GETOBJECTNAME: + case NCP_IOC_SETOBJECTNAME: + case NCP_IOC_GETPRIVATEDATA: + case NCP_IOC_SETPRIVATEDATA: +#ifdef CONFIG_COMPAT + case NCP_IOC_GETOBJECTNAME_32: + case NCP_IOC_SETOBJECTNAME_32: + case NCP_IOC_GETPRIVATEDATA_32: + case NCP_IOC_SETPRIVATEDATA_32: +#endif + ret = -EACCES; + goto out; + /* + * These require write access on the inode if user id + * does not match. Note that they do not write to the + * file... But old code did mnt_want_write, so I keep + * it as is. Of course not for mountpoint owner, as + * that breaks read-only mounts altogether as ncpmount + * needs working NCP_IOC_NCPREQUEST and + * NCP_IOC_GET_FS_INFO. Some of these codes (setdentryttl, + * signinit, setsignwanted) should be probably restricted + * to owner only, or even more to CAP_SYS_ADMIN). + */ + case NCP_IOC_GET_FS_INFO: + case NCP_IOC_GET_FS_INFO_V2: + case NCP_IOC_NCPREQUEST: + case NCP_IOC_SETDENTRYTTL: + case NCP_IOC_SIGN_INIT: + case NCP_IOC_LOCKUNLOCK: + case NCP_IOC_SET_SIGN_WANTED: +#ifdef CONFIG_COMPAT + case NCP_IOC_GET_FS_INFO_V2_32: + case NCP_IOC_NCPREQUEST_32: +#endif + ret = mnt_want_write_file(filp); + if (ret) + goto out; + need_drop_write = 1; + ret = inode_permission(inode, MAY_WRITE); + if (ret) + goto outDropWrite; + break; + /* + * Read access required. + */ + case NCP_IOC_GETMOUNTUID16: + case NCP_IOC_GETMOUNTUID32: + case NCP_IOC_GETMOUNTUID64: + case NCP_IOC_GETROOT: + case NCP_IOC_SIGN_WANTED: + ret = inode_permission(inode, MAY_READ); + if (ret) + goto out; + break; + /* + * Anybody can read these. + */ + case NCP_IOC_GETCHARSETS: + case NCP_IOC_GETDENTRYTTL: + default: + /* Three codes below are protected by CAP_SYS_ADMIN above. */ + case NCP_IOC_SETCHARSETS: + case NCP_IOC_CONN_LOGGED_IN: + case NCP_IOC_SETROOT: + break; + } + } + ret = __ncp_ioctl(inode, cmd, arg); +outDropWrite: + if (need_drop_write) + mnt_drop_write_file(filp); +out: + return ret; +} + +#ifdef CONFIG_COMPAT +long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + + arg = (unsigned long) compat_ptr(arg); + ret = ncp_ioctl(file, cmd, arg); + return ret; +} +#endif diff --git a/drivers/staging/ncpfs/mmap.c b/drivers/staging/ncpfs/mmap.c new file mode 100644 index 000000000000..a5c5cf2ff007 --- /dev/null +++ b/drivers/staging/ncpfs/mmap.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mmap.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ncp_fs.h" + +/* + * Fill in the supplied page for mmap + * XXX: how are we excluding truncate/invalidate here? Maybe need to lock + * page? + */ +static int ncp_file_mmap_fault(struct vm_fault *vmf) +{ + struct inode *inode = file_inode(vmf->vma->vm_file); + char *pg_addr; + unsigned int already_read; + unsigned int count; + int bufsize; + int pos; /* XXX: loff_t ? */ + + /* + * ncpfs has nothing against high pages as long + * as recvmsg and memset works on it + */ + vmf->page = alloc_page(GFP_HIGHUSER); + if (!vmf->page) + return VM_FAULT_OOM; + pg_addr = kmap(vmf->page); + pos = vmf->pgoff << PAGE_SHIFT; + + count = PAGE_SIZE; + /* what we can read in one go */ + bufsize = NCP_SERVER(inode)->buffer_size; + + already_read = 0; + if (ncp_make_open(inode, O_RDONLY) >= 0) { + while (already_read < count) { + int read_this_time; + int to_read; + + to_read = bufsize - (pos % bufsize); + + to_read = min_t(unsigned int, to_read, count - already_read); + + if (ncp_read_kernel(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + pos, to_read, + pg_addr + already_read, + &read_this_time) != 0) { + read_this_time = 0; + } + pos += read_this_time; + already_read += read_this_time; + + if (read_this_time < to_read) { + break; + } + } + ncp_inode_close(inode); + + } + + if (already_read < PAGE_SIZE) + memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); + flush_dcache_page(vmf->page); + kunmap(vmf->page); + + /* + * If I understand ncp_read_kernel() properly, the above always + * fetches from the network, here the analogue of disk. + * -- nyc + */ + count_vm_event(PGMAJFAULT); + count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT); + return VM_FAULT_MAJOR; +} + +static const struct vm_operations_struct ncp_file_mmap = +{ + .fault = ncp_file_mmap_fault, +}; + + +/* This is used for a general mmap of a ncp file */ +int ncp_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct inode *inode = file_inode(file); + + ncp_dbg(1, "called\n"); + + if (!ncp_conn_valid(NCP_SERVER(inode))) + return -EIO; + + /* only PAGE_COW or read-only supported now */ + if (vma->vm_flags & VM_SHARED) + return -EINVAL; + /* we do not support files bigger than 4GB... We eventually + supports just 4GB... */ + if (vma_pages(vma) + vma->vm_pgoff + > (1U << (32 - PAGE_SHIFT))) + return -EFBIG; + + vma->vm_ops = &ncp_file_mmap; + file_accessed(file); + return 0; +} diff --git a/drivers/staging/ncpfs/ncp_fs.h b/drivers/staging/ncpfs/ncp_fs.h new file mode 100644 index 000000000000..bdd262b6c198 --- /dev/null +++ b/drivers/staging/ncpfs/ncp_fs.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include "ncp_fs_i.h" +#include "ncp_fs_sb.h" + +#undef NCPFS_PARANOIA +#ifdef NCPFS_PARANOIA +#define ncp_vdbg(fmt, ...) \ + pr_debug(fmt, ##__VA_ARGS__) +#else +#define ncp_vdbg(fmt, ...) \ +do { \ + if (0) \ + pr_debug(fmt, ##__VA_ARGS__); \ +} while (0) +#endif + +#ifndef DEBUG_NCP +#define DEBUG_NCP 0 +#endif + +#if DEBUG_NCP > 0 && !defined(DEBUG) +#define DEBUG +#endif + +#define ncp_dbg(level, fmt, ...) \ +do { \ + if (level <= DEBUG_NCP) \ + pr_debug(fmt, ##__VA_ARGS__); \ +} while (0) + +#define NCP_MAX_RPC_TIMEOUT (6*HZ) + + +struct ncp_entry_info { + struct nw_info_struct i; + ino_t ino; + int opened; + int access; + unsigned int volume; + __u8 file_handle[6]; +}; + +static inline struct ncp_server *NCP_SBP(const struct super_block *sb) +{ + return sb->s_fs_info; +} + +#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) +static inline struct ncp_inode_info *NCP_FINFO(const struct inode *inode) +{ + return container_of(inode, struct ncp_inode_info, vfs_inode); +} + +/* linux/fs/ncpfs/inode.c */ +int ncp_notify_change(struct dentry *, struct iattr *); +struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *); +void ncp_update_inode(struct inode *, struct ncp_entry_info *); +void ncp_update_inode2(struct inode *, struct ncp_entry_info *); + +/* linux/fs/ncpfs/dir.c */ +extern const struct inode_operations ncp_dir_inode_operations; +extern const struct file_operations ncp_dir_operations; +extern const struct dentry_operations ncp_dentry_operations; +int ncp_conn_logged_in(struct super_block *); +int ncp_date_dos2unix(__le16 time, __le16 date); +void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date); + +/* linux/fs/ncpfs/ioctl.c */ +long ncp_ioctl(struct file *, unsigned int, unsigned long); +long ncp_compat_ioctl(struct file *, unsigned int, unsigned long); + +/* linux/fs/ncpfs/sock.c */ +int ncp_request2(struct ncp_server *server, int function, + void* reply, int max_reply_size); +static inline int ncp_request(struct ncp_server *server, int function) { + return ncp_request2(server, function, server->packet, server->packet_size); +} +int ncp_connect(struct ncp_server *server); +int ncp_disconnect(struct ncp_server *server); +void ncp_lock_server(struct ncp_server *server); +void ncp_unlock_server(struct ncp_server *server); + +/* linux/fs/ncpfs/symlink.c */ +#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) +extern const struct address_space_operations ncp_symlink_aops; +int ncp_symlink(struct inode*, struct dentry*, const char*); +#endif + +/* linux/fs/ncpfs/file.c */ +extern const struct inode_operations ncp_file_inode_operations; +extern const struct file_operations ncp_file_operations; +int ncp_make_open(struct inode *, int); + +/* linux/fs/ncpfs/mmap.c */ +int ncp_mmap(struct file *, struct vm_area_struct *); + +/* linux/fs/ncpfs/ncplib_kernel.c */ +int ncp_make_closed(struct inode *); + +#include "ncplib_kernel.h" diff --git a/drivers/staging/ncpfs/ncp_fs_i.h b/drivers/staging/ncpfs/ncp_fs_i.h new file mode 100644 index 000000000000..3432bafb53a5 --- /dev/null +++ b/drivers/staging/ncpfs/ncp_fs_i.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ncp_fs_i.h + * + * Copyright (C) 1995 Volker Lendecke + * + */ + +#ifndef _LINUX_NCP_FS_I +#define _LINUX_NCP_FS_I + +/* + * This is the ncpfs part of the inode structure. This must contain + * all the information we need to work with an inode after creation. + */ +struct ncp_inode_info { + __le32 dirEntNum; + __le32 DosDirNum; + __u8 volNumber; + __le32 nwattr; + struct mutex open_mutex; + atomic_t opened; + int access; + int flags; +#define NCPI_KLUDGE_SYMLINK 0x0001 +#define NCPI_DIR_CACHE 0x0002 + __u8 file_handle[6]; + struct inode vfs_inode; +}; + +#endif /* _LINUX_NCP_FS_I */ diff --git a/drivers/staging/ncpfs/ncp_fs_sb.h b/drivers/staging/ncpfs/ncp_fs_sb.h new file mode 100644 index 000000000000..f06cde4adf71 --- /dev/null +++ b/drivers/staging/ncpfs/ncp_fs_sb.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ncp_fs_sb.h + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * + */ + +#ifndef _NCP_FS_SB +#define _NCP_FS_SB + +#include +#include +#include +#include +#include +#include + +#define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */ + +struct sock; + +struct ncp_mount_data_kernel { + unsigned long flags; /* NCP_MOUNT_* flags */ + unsigned int int_flags; /* internal flags */ +#define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001 + kuid_t mounted_uid; /* Who may umount() this filesystem? */ + struct pid *wdog_pid; /* Who cares for our watchdog packets? */ + unsigned int ncp_fd; /* The socket to the ncp port */ + unsigned int time_out; /* How long should I wait after + sending a NCP request? */ + unsigned int retry_count; /* And how often should I retry? */ + unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; + kuid_t uid; + kgid_t gid; + umode_t file_mode; + umode_t dir_mode; + int info_fd; +}; + +struct ncp_server { + struct rcu_head rcu; + struct ncp_mount_data_kernel m; /* Nearly all of the mount data is of + interest for us later, so we store + it completely. */ + + __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2]; + + struct socket *ncp_sock;/* ncp socket */ + struct socket *info_sock; + + u8 sequence; + u8 task; + u16 connection; /* Remote connection number */ + + u8 completion; /* Status message from server */ + u8 conn_status; /* Bit 4 = 1 ==> Server going down, no + requests allowed anymore. + Bit 0 = 1 ==> Server is down. */ + + int buffer_size; /* Negotiated bufsize */ + + int reply_size; /* Size of last reply */ + + int packet_size; + unsigned char *packet; /* Here we prepare requests and + receive replies */ + unsigned char *txbuf; /* Storage for current request */ + unsigned char *rxbuf; /* Storage for reply to current request */ + + int lock; /* To prevent mismatch in protocols. */ + struct mutex mutex; + + int current_size; /* for packet preparation */ + int has_subfunction; + int ncp_reply_size; + + int root_setuped; + struct mutex root_setup_lock; + + /* info for packet signing */ + int sign_wanted; /* 1=Server needs signed packets */ + int sign_active; /* 0=don't do signing, 1=do */ + char sign_root[8]; /* generated from password and encr. key */ + char sign_last[16]; + + /* Authentication info: NDS or BINDERY, username */ + struct { + int auth_type; + size_t object_name_len; + void* object_name; + int object_type; + } auth; + /* Password info */ + struct { + size_t len; + void* data; + } priv; + struct rw_semaphore auth_rwsem; + + /* nls info: codepage for volume and charset for I/O */ + struct nls_table *nls_vol; + struct nls_table *nls_io; + + /* maximum age in jiffies */ + atomic_t dentry_ttl; + + /* miscellaneous */ + unsigned int flags; + + spinlock_t requests_lock; /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */ + + void (*data_ready)(struct sock* sk); + void (*error_report)(struct sock* sk); + void (*write_space)(struct sock* sk); /* STREAM mode only */ + struct { + struct work_struct tq; /* STREAM/DGRAM: data/error ready */ + struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */ + struct mutex creq_mutex; /* DGRAM only: lock accesses to rcv.creq */ + + unsigned int state; /* STREAM only: receiver state */ + struct { + __u32 magic __packed; + __u32 len __packed; + __u16 type __packed; + __u16 p1 __packed; + __u16 p2 __packed; + __u16 p3 __packed; + __u16 type2 __packed; + } buf; /* STREAM only: temporary buffer */ + unsigned char* ptr; /* STREAM only: pointer to data */ + size_t len; /* STREAM only: length of data to receive */ + } rcv; + struct { + struct list_head requests; /* STREAM only: queued requests */ + struct work_struct tq; /* STREAM only: transmitter ready */ + struct ncp_request_reply* creq; /* STREAM only: currently transmitted entry */ + } tx; + struct timer_list timeout_tm; /* DGRAM only: timeout timer */ + struct work_struct timeout_tq; /* DGRAM only: associated queue, we run timers from process context */ + int timeout_last; /* DGRAM only: current timeout length */ + int timeout_retries; /* DGRAM only: retries left */ + struct { + size_t len; + __u8 data[128]; + } unexpected_packet; +}; + +extern void ncp_tcp_rcv_proc(struct work_struct *work); +extern void ncp_tcp_tx_proc(struct work_struct *work); +extern void ncpdgram_rcv_proc(struct work_struct *work); +extern void ncpdgram_timeout_proc(struct work_struct *work); +extern void ncpdgram_timeout_call(struct timer_list *t); +extern void ncp_tcp_data_ready(struct sock* sk); +extern void ncp_tcp_write_space(struct sock* sk); +extern void ncp_tcp_error_report(struct sock* sk); + +#define NCP_FLAG_UTF8 1 + +#define NCP_CLR_FLAG(server, flag) ((server)->flags &= ~(flag)) +#define NCP_SET_FLAG(server, flag) ((server)->flags |= (flag)) +#define NCP_IS_FLAG(server, flag) ((server)->flags & (flag)) + +static inline int ncp_conn_valid(struct ncp_server *server) +{ + return ((server->conn_status & 0x11) == 0); +} + +static inline void ncp_invalidate_conn(struct ncp_server *server) +{ + server->conn_status |= 0x01; +} + +#endif diff --git a/drivers/staging/ncpfs/ncplib_kernel.c b/drivers/staging/ncpfs/ncplib_kernel.c new file mode 100644 index 000000000000..804adfebba2f --- /dev/null +++ b/drivers/staging/ncpfs/ncplib_kernel.c @@ -0,0 +1,1322 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ncplib_kernel.c + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified for big endian by J.F. Chadima and David S. Miller + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1999 Wolfram Pienkoss for NLS + * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include "ncp_fs.h" + +static inline void assert_server_locked(struct ncp_server *server) +{ + if (server->lock == 0) { + ncp_dbg(1, "server not locked!\n"); + } +} + +static void ncp_add_byte(struct ncp_server *server, __u8 x) +{ + assert_server_locked(server); + *(__u8 *) (&(server->packet[server->current_size])) = x; + server->current_size += 1; + return; +} + +static void ncp_add_word(struct ncp_server *server, __le16 x) +{ + assert_server_locked(server); + put_unaligned(x, (__le16 *) (&(server->packet[server->current_size]))); + server->current_size += 2; + return; +} + +static void ncp_add_be16(struct ncp_server *server, __u16 x) +{ + assert_server_locked(server); + put_unaligned(cpu_to_be16(x), (__be16 *) (&(server->packet[server->current_size]))); + server->current_size += 2; +} + +static void ncp_add_dword(struct ncp_server *server, __le32 x) +{ + assert_server_locked(server); + put_unaligned(x, (__le32 *) (&(server->packet[server->current_size]))); + server->current_size += 4; + return; +} + +static void ncp_add_be32(struct ncp_server *server, __u32 x) +{ + assert_server_locked(server); + put_unaligned(cpu_to_be32(x), (__be32 *)(&(server->packet[server->current_size]))); + server->current_size += 4; +} + +static inline void ncp_add_dword_lh(struct ncp_server *server, __u32 x) { + ncp_add_dword(server, cpu_to_le32(x)); +} + +static void ncp_add_mem(struct ncp_server *server, const void *source, int size) +{ + assert_server_locked(server); + memcpy(&(server->packet[server->current_size]), source, size); + server->current_size += size; + return; +} + +static void ncp_add_pstring(struct ncp_server *server, const char *s) +{ + int len = strlen(s); + assert_server_locked(server); + if (len > 255) { + ncp_dbg(1, "string too long: %s\n", s); + len = 255; + } + ncp_add_byte(server, len); + ncp_add_mem(server, s, len); + return; +} + +static inline void ncp_init_request(struct ncp_server *server) +{ + ncp_lock_server(server); + + server->current_size = sizeof(struct ncp_request_header); + server->has_subfunction = 0; +} + +static inline void ncp_init_request_s(struct ncp_server *server, int subfunction) +{ + ncp_lock_server(server); + + server->current_size = sizeof(struct ncp_request_header) + 2; + ncp_add_byte(server, subfunction); + + server->has_subfunction = 1; +} + +static inline char * +ncp_reply_data(struct ncp_server *server, int offset) +{ + return &(server->packet[sizeof(struct ncp_reply_header) + offset]); +} + +static inline u8 BVAL(const void *data) +{ + return *(const u8 *)data; +} + +static u8 ncp_reply_byte(struct ncp_server *server, int offset) +{ + return *(const u8 *)ncp_reply_data(server, offset); +} + +static inline u16 WVAL_LH(const void *data) +{ + return get_unaligned_le16(data); +} + +static u16 +ncp_reply_le16(struct ncp_server *server, int offset) +{ + return get_unaligned_le16(ncp_reply_data(server, offset)); +} + +static u16 +ncp_reply_be16(struct ncp_server *server, int offset) +{ + return get_unaligned_be16(ncp_reply_data(server, offset)); +} + +static inline u32 DVAL_LH(const void *data) +{ + return get_unaligned_le32(data); +} + +static __le32 +ncp_reply_dword(struct ncp_server *server, int offset) +{ + return get_unaligned((__le32 *)ncp_reply_data(server, offset)); +} + +static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) { + return le32_to_cpu(ncp_reply_dword(server, offset)); +} + +int +ncp_negotiate_buffersize(struct ncp_server *server, int size, int *target) +{ + int result; + + ncp_init_request(server); + ncp_add_be16(server, size); + + if ((result = ncp_request(server, 33)) != 0) { + ncp_unlock_server(server); + return result; + } + *target = min_t(unsigned int, ncp_reply_be16(server, 0), size); + + ncp_unlock_server(server); + return 0; +} + + +/* options: + * bit 0 ipx checksum + * bit 1 packet signing + */ +int +ncp_negotiate_size_and_options(struct ncp_server *server, + int size, int options, int *ret_size, int *ret_options) { + int result; + + /* there is minimum */ + if (size < NCP_BLOCK_SIZE) size = NCP_BLOCK_SIZE; + + ncp_init_request(server); + ncp_add_be16(server, size); + ncp_add_byte(server, options); + + if ((result = ncp_request(server, 0x61)) != 0) + { + ncp_unlock_server(server); + return result; + } + + /* NCP over UDP returns 0 (!!!) */ + result = ncp_reply_be16(server, 0); + if (result >= NCP_BLOCK_SIZE) + size = min(result, size); + *ret_size = size; + *ret_options = ncp_reply_byte(server, 4); + + ncp_unlock_server(server); + return 0; +} + +int ncp_get_volume_info_with_number(struct ncp_server* server, + int n, struct ncp_volume_info* target) { + int result; + int len; + + ncp_init_request_s(server, 44); + ncp_add_byte(server, n); + + if ((result = ncp_request(server, 22)) != 0) { + goto out; + } + target->total_blocks = ncp_reply_dword_lh(server, 0); + target->free_blocks = ncp_reply_dword_lh(server, 4); + target->purgeable_blocks = ncp_reply_dword_lh(server, 8); + target->not_yet_purgeable_blocks = ncp_reply_dword_lh(server, 12); + target->total_dir_entries = ncp_reply_dword_lh(server, 16); + target->available_dir_entries = ncp_reply_dword_lh(server, 20); + target->sectors_per_block = ncp_reply_byte(server, 28); + + memset(&(target->volume_name), 0, sizeof(target->volume_name)); + + result = -EIO; + len = ncp_reply_byte(server, 29); + if (len > NCP_VOLNAME_LEN) { + ncp_dbg(1, "volume name too long: %d\n", len); + goto out; + } + memcpy(&(target->volume_name), ncp_reply_data(server, 30), len); + result = 0; +out: + ncp_unlock_server(server); + return result; +} + +int ncp_get_directory_info(struct ncp_server* server, __u8 n, + struct ncp_volume_info* target) { + int result; + int len; + + ncp_init_request_s(server, 45); + ncp_add_byte(server, n); + + if ((result = ncp_request(server, 22)) != 0) { + goto out; + } + target->total_blocks = ncp_reply_dword_lh(server, 0); + target->free_blocks = ncp_reply_dword_lh(server, 4); + target->purgeable_blocks = 0; + target->not_yet_purgeable_blocks = 0; + target->total_dir_entries = ncp_reply_dword_lh(server, 8); + target->available_dir_entries = ncp_reply_dword_lh(server, 12); + target->sectors_per_block = ncp_reply_byte(server, 20); + + memset(&(target->volume_name), 0, sizeof(target->volume_name)); + + result = -EIO; + len = ncp_reply_byte(server, 21); + if (len > NCP_VOLNAME_LEN) { + ncp_dbg(1, "volume name too long: %d\n", len); + goto out; + } + memcpy(&(target->volume_name), ncp_reply_data(server, 22), len); + result = 0; +out: + ncp_unlock_server(server); + return result; +} + +int +ncp_close_file(struct ncp_server *server, const char *file_id) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + + result = ncp_request(server, 66); + ncp_unlock_server(server); + return result; +} + +int +ncp_make_closed(struct inode *inode) +{ + int err; + + err = 0; + mutex_lock(&NCP_FINFO(inode)->open_mutex); + if (atomic_read(&NCP_FINFO(inode)->opened) == 1) { + atomic_set(&NCP_FINFO(inode)->opened, 0); + err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle); + + if (!err) + ncp_vdbg("volnum=%d, dirent=%u, error=%d\n", + NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum, err); + } + mutex_unlock(&NCP_FINFO(inode)->open_mutex); + return err; +} + +static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num, + __le32 dir_base, int have_dir_base, + const char *path) +{ + ncp_add_byte(server, vol_num); + ncp_add_dword(server, dir_base); + if (have_dir_base != 0) { + ncp_add_byte(server, 1); /* dir_base */ + } else { + ncp_add_byte(server, 0xff); /* no handle */ + } + if (path != NULL) { + ncp_add_byte(server, 1); /* 1 component */ + ncp_add_pstring(server, path); + } else { + ncp_add_byte(server, 0); + } +} + +int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __le32 dirent, + __u8* dirhandle) { + int result; + + ncp_init_request(server); + ncp_add_byte(server, 12); /* subfunction */ + ncp_add_byte(server, NW_NS_DOS); + ncp_add_byte(server, 0); + ncp_add_word(server, 0); + ncp_add_handle_path(server, volnum, dirent, 1, NULL); + if ((result = ncp_request(server, 87)) == 0) { + *dirhandle = ncp_reply_byte(server, 0); + } + ncp_unlock_server(server); + return result; +} + +int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) { + int result; + + ncp_init_request_s(server, 20); + ncp_add_byte(server, dirhandle); + result = ncp_request(server, 22); + ncp_unlock_server(server); + return result; +} + +void ncp_extract_file_info(const void *structure, struct nw_info_struct *target) +{ + const __u8 *name_len; + const int info_struct_size = offsetof(struct nw_info_struct, nameLen); + + memcpy(target, structure, info_struct_size); + name_len = structure + info_struct_size; + target->nameLen = *name_len; + memcpy(target->entryName, name_len + 1, *name_len); + target->entryName[*name_len] = '\0'; + target->volNumber = le32_to_cpu(target->volNumber); + return; +} + +#ifdef CONFIG_NCPFS_NFS_NS +static inline void ncp_extract_nfs_info(const unsigned char *structure, + struct nw_nfs_info *target) +{ + target->mode = DVAL_LH(structure); + target->rdev = DVAL_LH(structure + 8); +} +#endif + +int ncp_obtain_nfs_info(struct ncp_server *server, + struct nw_info_struct *target) + +{ + int result = 0; +#ifdef CONFIG_NCPFS_NFS_NS + __u32 volnum = target->volNumber; + + if (ncp_is_nfs_extras(server, volnum)) { + ncp_init_request(server); + ncp_add_byte(server, 19); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, NW_NS_NFS); + ncp_add_byte(server, 0); + ncp_add_byte(server, volnum); + ncp_add_dword(server, target->dirEntNum); + /* We must retrieve both nlinks and rdev, otherwise some server versions + report zeroes instead of valid data */ + ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV); + + if ((result = ncp_request(server, 87)) == 0) { + ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs); + ncp_dbg(1, "(%s) mode=0%o, rdev=0x%x\n", + target->entryName, target->nfs.mode, + target->nfs.rdev); + } else { + target->nfs.mode = 0; + target->nfs.rdev = 0; + } + ncp_unlock_server(server); + + } else +#endif + { + target->nfs.mode = 0; + target->nfs.rdev = 0; + } + return result; +} + +/* + * Returns information for a (one-component) name relative to + * the specified directory. + */ +int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path, + struct nw_info_struct *target) +{ + __u8 volnum = NCP_FINFO(dir)->volNumber; + __le32 dirent = NCP_FINFO(dir)->dirEntNum; + int result; + + if (target == NULL) { + pr_err("%s: invalid call\n", __func__); + return -EINVAL; + } + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */ + ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ + ncp_add_dword(server, RIM_ALL); + ncp_add_handle_path(server, volnum, dirent, 1, path); + + if ((result = ncp_request(server, 87)) != 0) + goto out; + ncp_extract_file_info(ncp_reply_data(server, 0), target); + ncp_unlock_server(server); + + result = ncp_obtain_nfs_info(server, target); + return result; + +out: + ncp_unlock_server(server); + return result; +} + +#ifdef CONFIG_NCPFS_NFS_NS +static int +ncp_obtain_DOS_dir_base(struct ncp_server *server, + __u8 ns, __u8 volnum, __le32 dirent, + const char *path, /* At most 1 component */ + __le32 *DOS_dir_base) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, ns); + ncp_add_byte(server, ns); + ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ + ncp_add_dword(server, RIM_DIRECTORY); + ncp_add_handle_path(server, volnum, dirent, 1, path); + + if ((result = ncp_request(server, 87)) == 0) + { + if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34); + } + ncp_unlock_server(server); + return result; +} +#endif /* CONFIG_NCPFS_NFS_NS */ + +static inline int +ncp_get_known_namespace(struct ncp_server *server, __u8 volume) +{ +#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) + int result; + __u8 *namespace; + __u16 no_namespaces; + + ncp_init_request(server); + ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */ + ncp_add_word(server, 0); + ncp_add_byte(server, volume); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return NW_NS_DOS; /* not result ?? */ + } + + result = NW_NS_DOS; + no_namespaces = ncp_reply_le16(server, 0); + namespace = ncp_reply_data(server, 2); + + while (no_namespaces > 0) { + ncp_dbg(1, "found %d on %d\n", *namespace, volume); + +#ifdef CONFIG_NCPFS_NFS_NS + if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) + { + result = NW_NS_NFS; + break; + } +#endif /* CONFIG_NCPFS_NFS_NS */ +#ifdef CONFIG_NCPFS_OS2_NS + if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2)) + { + result = NW_NS_OS2; + } +#endif /* CONFIG_NCPFS_OS2_NS */ + namespace += 1; + no_namespaces -= 1; + } + ncp_unlock_server(server); + return result; +#else /* neither OS2 nor NFS - only DOS */ + return NW_NS_DOS; +#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */ +} + +int +ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns) +{ + int ns = ncp_get_known_namespace(server, volume); + + if (ret_ns) + *ret_ns = ns; + + ncp_dbg(1, "namespace[%d] = %d\n", volume, server->name_space[volume]); + + if (server->name_space[volume] == ns) + return 0; + server->name_space[volume] = ns; + return 1; +} + +static int +ncp_ObtainSpecificDirBase(struct ncp_server *server, + __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base, + const char *path, /* At most 1 component */ + __le32 *dirEntNum, __le32 *DosDirNum) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, nsSrc); + ncp_add_byte(server, nsDst); + ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ + ncp_add_dword(server, RIM_ALL); + ncp_add_handle_path(server, vol_num, dir_base, 1, path); + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + if (dirEntNum) + *dirEntNum = ncp_reply_dword(server, 0x30); + if (DosDirNum) + *DosDirNum = ncp_reply_dword(server, 0x34); + ncp_unlock_server(server); + return 0; +} + +int +ncp_mount_subdir(struct ncp_server *server, + __u8 volNumber, __u8 srcNS, __le32 dirEntNum, + __u32* volume, __le32* newDirEnt, __le32* newDosEnt) +{ + int dstNS; + int result; + + ncp_update_known_namespace(server, volNumber, &dstNS); + if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, + dirEntNum, NULL, newDirEnt, newDosEnt)) != 0) + { + return result; + } + *volume = volNumber; + server->m.mounted_vol[1] = 0; + server->m.mounted_vol[0] = 'X'; + return 0; +} + +int +ncp_get_volume_root(struct ncp_server *server, + const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent) +{ + int result; + + ncp_dbg(1, "looking up vol %s\n", volname); + + ncp_init_request(server); + ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */ + ncp_add_byte(server, 0); /* DOS namespace */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + + ncp_add_byte(server, 0); /* faked volume number */ + ncp_add_dword(server, 0); /* faked dir_base */ + ncp_add_byte(server, 0xff); /* Don't have a dir_base */ + ncp_add_byte(server, 1); /* 1 path component */ + ncp_add_pstring(server, volname); + + if ((result = ncp_request(server, 87)) != 0) { + ncp_unlock_server(server); + return result; + } + *dirent = *dosdirent = ncp_reply_dword(server, 4); + *volume = ncp_reply_byte(server, 8); + ncp_unlock_server(server); + return 0; +} + +int +ncp_lookup_volume(struct ncp_server *server, + const char *volname, struct nw_info_struct *target) +{ + int result; + + memset(target, 0, sizeof(*target)); + result = ncp_get_volume_root(server, volname, + &target->volNumber, &target->dirEntNum, &target->DosDirNum); + if (result) { + return result; + } + ncp_update_known_namespace(server, target->volNumber, NULL); + target->nameLen = strlen(volname); + memcpy(target->entryName, volname, target->nameLen+1); + target->attributes = aDIR; + /* set dates to Jan 1, 1986 00:00 */ + target->creationTime = target->modifyTime = cpu_to_le16(0x0000); + target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21); + target->nfs.mode = 0; + return 0; +} + +int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server, + struct inode *dir, + const char *path, + __le32 info_mask, + const struct nw_modify_dos_info *info) +{ + __u8 volnum = NCP_FINFO(dir)->volNumber; + __le32 dirent = NCP_FINFO(dir)->dirEntNum; + int result; + + ncp_init_request(server); + ncp_add_byte(server, 7); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_word(server, cpu_to_le16(0x8006)); /* search attribs: all */ + + ncp_add_dword(server, info_mask); + ncp_add_mem(server, info, sizeof(*info)); + ncp_add_handle_path(server, volnum, dirent, 1, path); + + result = ncp_request(server, 87); + ncp_unlock_server(server); + return result; +} + +int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, + struct inode *dir, + __le32 info_mask, + const struct nw_modify_dos_info *info) +{ + return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL, + info_mask, info); +} + +#ifdef CONFIG_NCPFS_NFS_NS +int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent, + __u32 mode, __u32 rdev) + +{ + int result = 0; + + ncp_init_request(server); + if (server->name_space[volnum] == NW_NS_NFS) { + ncp_add_byte(server, 25); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, NW_NS_NFS); + ncp_add_byte(server, volnum); + ncp_add_dword(server, dirent); + /* we must always operate on both nlinks and rdev, otherwise + rdev is not set */ + ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV); + ncp_add_dword_lh(server, mode); + ncp_add_dword_lh(server, 1); /* nlinks */ + ncp_add_dword_lh(server, rdev); + result = ncp_request(server, 87); + } + ncp_unlock_server(server); + return result; +} +#endif + + +static int +ncp_DeleteNSEntry(struct ncp_server *server, + __u8 have_dir_base, __u8 volnum, __le32 dirent, + const char* name, __u8 ns, __le16 attr) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 8); /* subfunction */ + ncp_add_byte(server, ns); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_word(server, attr); /* search attribs: all */ + ncp_add_handle_path(server, volnum, dirent, have_dir_base, name); + + result = ncp_request(server, 87); + ncp_unlock_server(server); + return result; +} + +int +ncp_del_file_or_subdir2(struct ncp_server *server, + struct dentry *dentry) +{ + struct inode *inode = d_inode(dentry); + __u8 volnum; + __le32 dirent; + + if (!inode) { + return 0xFF; /* Any error */ + } + volnum = NCP_FINFO(inode)->volNumber; + dirent = NCP_FINFO(inode)->DosDirNum; + return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006)); +} + +int +ncp_del_file_or_subdir(struct ncp_server *server, + struct inode *dir, const char *name) +{ + __u8 volnum = NCP_FINFO(dir)->volNumber; + __le32 dirent = NCP_FINFO(dir)->dirEntNum; + int name_space; + + name_space = server->name_space[volnum]; +#ifdef CONFIG_NCPFS_NFS_NS + if (name_space == NW_NS_NFS) + { + int result; + + result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent); + if (result) return result; + name = NULL; + name_space = NW_NS_DOS; + } +#endif /* CONFIG_NCPFS_NFS_NS */ + return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006)); +} + +static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6]) +{ + __le16 *dest = (__le16 *) ret; + dest[1] = cpu_to_le16(v0); + dest[2] = cpu_to_le16(v1); + dest[0] = cpu_to_le16(v0 + 1); + return; +} + +/* If both dir and name are NULL, then in target there's already a + looked-up entry that wants to be opened. */ +int ncp_open_create_file_or_subdir(struct ncp_server *server, + struct inode *dir, const char *name, + int open_create_mode, + __le32 create_attributes, + __le16 desired_acc_rights, + struct ncp_entry_info *target) +{ + __le16 search_attribs = cpu_to_le16(0x0006); + __u8 volnum; + __le32 dirent; + int result; + + volnum = NCP_FINFO(dir)->volNumber; + dirent = NCP_FINFO(dir)->dirEntNum; + + if ((create_attributes & aDIR) != 0) { + search_attribs |= cpu_to_le16(0x8000); + } + ncp_init_request(server); + ncp_add_byte(server, 1); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, open_create_mode); + ncp_add_word(server, search_attribs); + ncp_add_dword(server, RIM_ALL); + ncp_add_dword(server, create_attributes); + /* The desired acc rights seem to be the inherited rights mask + for directories */ + ncp_add_word(server, desired_acc_rights); + ncp_add_handle_path(server, volnum, dirent, 1, name); + + if ((result = ncp_request(server, 87)) != 0) + goto out; + if (!(create_attributes & aDIR)) + target->opened = 1; + + /* in target there's a new finfo to fill */ + ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i)); + target->volume = target->i.volNumber; + ConvertToNWfromDWORD(ncp_reply_le16(server, 0), + ncp_reply_le16(server, 2), + target->file_handle); + + ncp_unlock_server(server); + + (void)ncp_obtain_nfs_info(server, &(target->i)); + return 0; + +out: + ncp_unlock_server(server); + return result; +} + +int +ncp_initialize_search(struct ncp_server *server, struct inode *dir, + struct nw_search_sequence *target) +{ + __u8 volnum = NCP_FINFO(dir)->volNumber; + __le32 dirent = NCP_FINFO(dir)->dirEntNum; + int result; + + ncp_init_request(server); + ncp_add_byte(server, 2); /* subfunction */ + ncp_add_byte(server, server->name_space[volnum]); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_handle_path(server, volnum, dirent, 1, NULL); + + result = ncp_request(server, 87); + if (result) + goto out; + memcpy(target, ncp_reply_data(server, 0), sizeof(*target)); + +out: + ncp_unlock_server(server); + return result; +} + +int ncp_search_for_fileset(struct ncp_server *server, + struct nw_search_sequence *seq, + int* more, + int* cnt, + char* buffer, + size_t bufsize, + char** rbuf, + size_t* rsize) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 20); + ncp_add_byte(server, server->name_space[seq->volNumber]); + ncp_add_byte(server, 0); /* datastream */ + ncp_add_word(server, cpu_to_le16(0x8006)); + ncp_add_dword(server, RIM_ALL); + ncp_add_word(server, cpu_to_le16(32767)); /* max returned items */ + ncp_add_mem(server, seq, 9); +#ifdef CONFIG_NCPFS_NFS_NS + if (server->name_space[seq->volNumber] == NW_NS_NFS) { + ncp_add_byte(server, 0); /* 0 byte pattern */ + } else +#endif + { + ncp_add_byte(server, 2); /* 2 byte pattern */ + ncp_add_byte(server, 0xff); /* following is a wildcard */ + ncp_add_byte(server, '*'); + } + result = ncp_request2(server, 87, buffer, bufsize); + if (result) { + ncp_unlock_server(server); + return result; + } + if (server->ncp_reply_size < 12) { + ncp_unlock_server(server); + return 0xFF; + } + *rsize = server->ncp_reply_size - 12; + ncp_unlock_server(server); + buffer = buffer + sizeof(struct ncp_reply_header); + *rbuf = buffer + 12; + *cnt = WVAL_LH(buffer + 10); + *more = BVAL(buffer + 9); + memcpy(seq, buffer, 9); + return 0; +} + +static int +ncp_RenameNSEntry(struct ncp_server *server, + struct inode *old_dir, const char *old_name, __le16 old_type, + struct inode *new_dir, const char *new_name) +{ + int result = -EINVAL; + + if ((old_dir == NULL) || (old_name == NULL) || + (new_dir == NULL) || (new_name == NULL)) + goto out; + + ncp_init_request(server); + ncp_add_byte(server, 4); /* subfunction */ + ncp_add_byte(server, server->name_space[NCP_FINFO(old_dir)->volNumber]); + ncp_add_byte(server, 1); /* rename flag */ + ncp_add_word(server, old_type); /* search attributes */ + + /* source Handle Path */ + ncp_add_byte(server, NCP_FINFO(old_dir)->volNumber); + ncp_add_dword(server, NCP_FINFO(old_dir)->dirEntNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 source component */ + + /* dest Handle Path */ + ncp_add_byte(server, NCP_FINFO(new_dir)->volNumber); + ncp_add_dword(server, NCP_FINFO(new_dir)->dirEntNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 destination component */ + + /* source path string */ + ncp_add_pstring(server, old_name); + /* dest path string */ + ncp_add_pstring(server, new_name); + + result = ncp_request(server, 87); + ncp_unlock_server(server); +out: + return result; +} + +int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct inode *old_dir, const char *old_name, + struct inode *new_dir, const char *new_name) +{ + int result; + __le16 old_type = cpu_to_le16(0x06); + +/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */ + result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, + new_dir, new_name); + if (result == 0xFF) /* File Not Found, try directory */ + { + old_type = cpu_to_le16(0x16); + result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, + new_dir, new_name); + } + if (result != 0x92) return result; /* All except NO_FILES_RENAMED */ + result = ncp_del_file_or_subdir(server, new_dir, new_name); + if (result != 0) return -EACCES; + result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, + new_dir, new_name); + return result; +} + + +/* We have to transfer to/from user space */ +int +ncp_read_kernel(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, char *target, int *bytes_read) +{ + const char *source; + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be16(server, to_read); + + if ((result = ncp_request(server, 72)) != 0) { + goto out; + } + *bytes_read = ncp_reply_be16(server, 0); + source = ncp_reply_data(server, 2 + (offset & 1)); + + memcpy(target, source, *bytes_read); +out: + ncp_unlock_server(server); + return result; +} + +/* There is a problem... egrep and some other silly tools do: + x = mmap(NULL, MAP_PRIVATE, PROT_READ|PROT_WRITE, , 32768); + read(, x, 32768); + Now copying read result by copy_to_user causes pagefault. This pagefault + could not be handled because of server was locked due to read. So we have + to use temporary buffer. So ncp_unlock_server must be done before + copy_to_user (and for write, copy_from_user must be done before + ncp_init_request... same applies for send raw packet ioctl). Because of + file is normally read in bigger chunks, caller provides kmalloced + (vmalloced) chunk of memory with size >= to_read... + */ +int +ncp_read_bounce(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, struct iov_iter *to, + int *bytes_read, void *bounce, __u32 bufsize) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be16(server, to_read); + result = ncp_request2(server, 72, bounce, bufsize); + ncp_unlock_server(server); + if (!result) { + int len = get_unaligned_be16((char *)bounce + + sizeof(struct ncp_reply_header)); + result = -EIO; + if (len <= to_read) { + char* source; + + source = (char*)bounce + + sizeof(struct ncp_reply_header) + 2 + + (offset & 1); + *bytes_read = len; + result = 0; + if (copy_to_iter(source, len, to) != len) + result = -EFAULT; + } + } + return result; +} + +int +ncp_write_kernel(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be16(server, to_write); + ncp_add_mem(server, source, to_write); + + if ((result = ncp_request(server, 73)) == 0) + *bytes_written = to_write; + ncp_unlock_server(server); + return result; +} + +#ifdef CONFIG_NCPFS_IOCTL_LOCKING +int +ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id, + __u8 locktype, __u32 offset, __u32 length, __u16 timeout) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, locktype); + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be32(server, length); + ncp_add_be16(server, timeout); + + if ((result = ncp_request(server, 0x1A)) != 0) + { + ncp_unlock_server(server); + return result; + } + ncp_unlock_server(server); + return 0; +} + +int +ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id, + __u32 offset, __u32 length) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); /* who knows... lanalyzer says that */ + ncp_add_mem(server, file_id, 6); + ncp_add_be32(server, offset); + ncp_add_be32(server, length); + + if ((result = ncp_request(server, 0x1E)) != 0) + { + ncp_unlock_server(server); + return result; + } + ncp_unlock_server(server); + return 0; +} +#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ + +#ifdef CONFIG_NCPFS_NLS +/* This are the NLS conversion routines with inspirations and code parts + * from the vfat file system and hints from Petr Vandrovec. + */ + +int +ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen, + const unsigned char *iname, unsigned int ilen, int cc) +{ + struct nls_table *in = server->nls_io; + struct nls_table *out = server->nls_vol; + unsigned char *vname_start; + unsigned char *vname_end; + const unsigned char *iname_end; + + iname_end = iname + ilen; + vname_start = vname; + vname_end = vname + *vlen - 1; + + while (iname < iname_end) { + int chl; + wchar_t ec; + + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { + int k; + unicode_t u; + + k = utf8_to_utf32(iname, iname_end - iname, &u); + if (k < 0 || u > MAX_WCHAR_T) + return -EINVAL; + iname += k; + ec = u; + } else { + if (*iname == NCP_ESC) { + int k; + + if (iname_end - iname < 5) + goto nospec; + + ec = 0; + for (k = 1; k < 5; k++) { + unsigned char nc; + + nc = iname[k] - '0'; + if (nc >= 10) { + nc -= 'A' - '0' - 10; + if ((nc < 10) || (nc > 15)) { + goto nospec; + } + } + ec = (ec << 4) | nc; + } + iname += 5; + } else { +nospec:; + if ( (chl = in->char2uni(iname, iname_end - iname, &ec)) < 0) + return chl; + iname += chl; + } + } + + /* unitoupper should be here! */ + + chl = out->uni2char(ec, vname, vname_end - vname); + if (chl < 0) + return chl; + + /* this is wrong... */ + if (cc) { + int chi; + + for (chi = 0; chi < chl; chi++){ + vname[chi] = ncp_toupper(out, vname[chi]); + } + } + vname += chl; + } + + *vname = 0; + *vlen = vname - vname_start; + return 0; +} + +int +ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen, + const unsigned char *vname, unsigned int vlen, int cc) +{ + struct nls_table *in = server->nls_vol; + struct nls_table *out = server->nls_io; + const unsigned char *vname_end; + unsigned char *iname_start; + unsigned char *iname_end; + unsigned char *vname_cc; + int err; + + vname_cc = NULL; + + if (cc) { + int i; + + /* this is wrong! */ + vname_cc = kmalloc(vlen, GFP_KERNEL); + if (!vname_cc) + return -ENOMEM; + for (i = 0; i < vlen; i++) + vname_cc[i] = ncp_tolower(in, vname[i]); + vname = vname_cc; + } + + iname_start = iname; + iname_end = iname + *ilen - 1; + vname_end = vname + vlen; + + while (vname < vname_end) { + wchar_t ec; + int chl; + + if ( (chl = in->char2uni(vname, vname_end - vname, &ec)) < 0) { + err = chl; + goto quit; + } + vname += chl; + + /* unitolower should be here! */ + + if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { + int k; + + k = utf32_to_utf8(ec, iname, iname_end - iname); + if (k < 0) { + err = -ENAMETOOLONG; + goto quit; + } + iname += k; + } else { + if ( (chl = out->uni2char(ec, iname, iname_end - iname)) >= 0) { + iname += chl; + } else { + int k; + + if (iname_end - iname < 5) { + err = -ENAMETOOLONG; + goto quit; + } + *iname = NCP_ESC; + for (k = 4; k > 0; k--) { + unsigned char v; + + v = (ec & 0xF) + '0'; + if (v > '9') { + v += 'A' - '9' - 1; + } + iname[k] = v; + ec >>= 4; + } + iname += 5; + } + } + } + + *iname = 0; + *ilen = iname - iname_start; + err = 0; +quit:; + if (cc) + kfree(vname_cc); + return err; +} + +#else + +int +ncp__io2vol(unsigned char *vname, unsigned int *vlen, + const unsigned char *iname, unsigned int ilen, int cc) +{ + int i; + + if (*vlen <= ilen) + return -ENAMETOOLONG; + + if (cc) + for (i = 0; i < ilen; i++) { + *vname = toupper(*iname); + vname++; + iname++; + } + else { + memmove(vname, iname, ilen); + vname += ilen; + } + + *vlen = ilen; + *vname = 0; + return 0; +} + +int +ncp__vol2io(unsigned char *iname, unsigned int *ilen, + const unsigned char *vname, unsigned int vlen, int cc) +{ + int i; + + if (*ilen <= vlen) + return -ENAMETOOLONG; + + if (cc) + for (i = 0; i < vlen; i++) { + *iname = tolower(*vname); + iname++; + vname++; + } + else { + memmove(iname, vname, vlen); + iname += vlen; + } + + *ilen = vlen; + *iname = 0; + return 0; +} + +#endif diff --git a/drivers/staging/ncpfs/ncplib_kernel.h b/drivers/staging/ncpfs/ncplib_kernel.h new file mode 100644 index 000000000000..aaae8aa9bf7d --- /dev/null +++ b/drivers/staging/ncpfs/ncplib_kernel.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ncplib_kernel.h + * + * Copyright (C) 1995, 1996 by Volker Lendecke + * Modified for big endian by J.F. Chadima and David S. Miller + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * Modified 1998, 1999 Wolfram Pienkoss for NLS + * Modified 1999 Wolfram Pienkoss for directory caching + * + */ + +#ifndef _NCPLIB_H +#define _NCPLIB_H + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_NCPFS_NLS +#include +#else +#include +#endif /* CONFIG_NCPFS_NLS */ + +#define NCP_MIN_SYMLINK_SIZE 8 +#define NCP_MAX_SYMLINK_SIZE 512 + +#define NCP_BLOCK_SHIFT 9 +#define NCP_BLOCK_SIZE (1 << (NCP_BLOCK_SHIFT)) + +int ncp_negotiate_buffersize(struct ncp_server *, int, int *); +int ncp_negotiate_size_and_options(struct ncp_server *server, int size, + int options, int *ret_size, int *ret_options); + +int ncp_get_volume_info_with_number(struct ncp_server* server, int n, + struct ncp_volume_info *target); + +int ncp_get_directory_info(struct ncp_server* server, __u8 dirhandle, + struct ncp_volume_info* target); + +int ncp_close_file(struct ncp_server *, const char *); +static inline int ncp_read_bounce_size(__u32 size) { + return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8; +}; +int ncp_read_bounce(struct ncp_server *, const char *, __u32, __u16, + struct iov_iter *, int *, void *bounce, __u32 bouncelen); +int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, + char *, int *); +int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16, + const char *, int *); + +static inline void ncp_inode_close(struct inode *inode) { + atomic_dec(&NCP_FINFO(inode)->opened); +} + +void ncp_extract_file_info(const void* src, struct nw_info_struct* target); +int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *, + struct nw_info_struct *target); +int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target); +int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns); +int ncp_get_volume_root(struct ncp_server *server, const char *volname, + __u32 *volume, __le32 *dirent, __le32 *dosdirent); +int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *); +int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *, + __le32, const struct nw_modify_dos_info *info); +int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *, + const char* path, __le32, const struct nw_modify_dos_info *info); +int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent, + __u32 mode, __u32 rdev); + +int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*); +int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *); +int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *, + int, __le32, __le16, struct ncp_entry_info *); + +int ncp_initialize_search(struct ncp_server *, struct inode *, + struct nw_search_sequence *target); +int ncp_search_for_fileset(struct ncp_server *server, + struct nw_search_sequence *seq, + int* more, int* cnt, + char* buffer, size_t bufsize, + char** rbuf, size_t* rsize); + +int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct inode *, const char *, struct inode *, const char *); + + +int +ncp_LogPhysicalRecord(struct ncp_server *server, + const char *file_id, __u8 locktype, + __u32 offset, __u32 length, __u16 timeout); + +#ifdef CONFIG_NCPFS_IOCTL_LOCKING +int +ncp_ClearPhysicalRecord(struct ncp_server *server, + const char *file_id, + __u32 offset, __u32 length); +#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ + +int +ncp_mount_subdir(struct ncp_server *, __u8, __u8, __le32, + __u32* volume, __le32* dirent, __le32* dosdirent); +int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __le32 dirent, __u8 *dirhandle); +int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle); + +int ncp_create_new(struct inode *dir, struct dentry *dentry, + umode_t mode, dev_t rdev, __le32 attributes); + +static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) { +#ifdef CONFIG_NCPFS_NFS_NS + return (server->m.flags & NCP_MOUNT_NFS_EXTRAS) && + (server->name_space[volnum] == NW_NS_NFS); +#else + return 0; +#endif +} + +#ifdef CONFIG_NCPFS_NLS + +int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); +int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); + +#define NCP_ESC ':' +#define NCP_IO_TABLE(sb) (NCP_SBP(sb)->nls_io) +#define ncp_tolower(t, c) nls_tolower(t, c) +#define ncp_toupper(t, c) nls_toupper(t, c) +#define ncp_strnicmp(t, s1, s2, len) \ + nls_strnicmp(t, s1, s2, len) +#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(S,m,i,n,k,U) +#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(S,m,i,n,k,U) + +#else + +int ncp__io2vol(unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); +int ncp__vol2io(unsigned char *, unsigned int *, + const unsigned char *, unsigned int, int); + +#define NCP_IO_TABLE(sb) NULL +#define ncp_tolower(t, c) tolower(c) +#define ncp_toupper(t, c) toupper(c) +#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(m,i,n,k,U) +#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(m,i,n,k,U) + + +static inline int ncp_strnicmp(const struct nls_table *t, + const unsigned char *s1, const unsigned char *s2, int len) +{ + while (len--) { + if (tolower(*s1++) != tolower(*s2++)) + return 1; + } + + return 0; +} + +#endif /* CONFIG_NCPFS_NLS */ + +#define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time) +#define NCP_MAX_AGE(server) atomic_read(&(server)->dentry_ttl) +#define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server)) + +static inline void +ncp_age_dentry(struct ncp_server* server, struct dentry* dentry) +{ + dentry->d_time = jiffies - NCP_MAX_AGE(server); +} + +static inline void +ncp_new_dentry(struct dentry* dentry) +{ + dentry->d_time = jiffies; +} + +struct ncp_cache_head { + time_t mtime; + unsigned long time; /* cache age */ + unsigned long end; /* last valid fpos in cache */ + int eof; +}; + +#define NCP_DIRCACHE_SIZE ((int)(PAGE_SIZE/sizeof(struct dentry *))) +union ncp_dir_cache { + struct ncp_cache_head head; + struct dentry *dentry[NCP_DIRCACHE_SIZE]; +}; + +#define NCP_FIRSTCACHE_SIZE ((int)((NCP_DIRCACHE_SIZE * \ + sizeof(struct dentry *) - sizeof(struct ncp_cache_head)) / \ + sizeof(struct dentry *))) + +#define NCP_DIRCACHE_START (NCP_DIRCACHE_SIZE - NCP_FIRSTCACHE_SIZE) + +struct ncp_cache_control { + struct ncp_cache_head head; + struct page *page; + union ncp_dir_cache *cache; + unsigned long fpos, ofs; + int filled, valid, idx; +}; + +#endif /* _NCPLIB_H */ diff --git a/drivers/staging/ncpfs/ncpsign_kernel.c b/drivers/staging/ncpfs/ncpsign_kernel.c new file mode 100644 index 000000000000..8085b1a3ba47 --- /dev/null +++ b/drivers/staging/ncpfs/ncpsign_kernel.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ncpsign_kernel.c + * + * Arne de Bruijn (arne@knoware.nl), 1997 + * + */ + + +#ifdef CONFIG_NCPFS_PACKET_SIGNING + +#include +#include +#include +#include "ncp_fs.h" +#include "ncpsign_kernel.h" + +/* i386: 32-bit, little endian, handles mis-alignment */ +#ifdef __i386__ +#define GET_LE32(p) (*(const int *)(p)) +#define PUT_LE32(p,v) { *(int *)(p)=v; } +#else +/* from include/ncplib.h */ +#define BVAL(buf,pos) (((const __u8 *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) +#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val)) + +static inline __u16 +WVAL_LH(const __u8 * buf, int pos) +{ + return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8; +} +static inline __u32 +DVAL_LH(const __u8 * buf, int pos) +{ + return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16; +} +static inline void +WSET_LH(__u8 * buf, int pos, __u16 val) +{ + BSET(buf, pos, val & 0xff); + BSET(buf, pos + 1, val >> 8); +} +static inline void +DSET_LH(__u8 * buf, int pos, __u32 val) +{ + WSET_LH(buf, pos, val & 0xffff); + WSET_LH(buf, pos + 2, val >> 16); +} + +#define GET_LE32(p) DVAL_LH(p,0) +#define PUT_LE32(p,v) DSET_LH(p,0,v) +#endif + +static void nwsign(char *r_data1, char *r_data2, char *outdata) { + int i; + unsigned int w0,w1,w2,w3; + static int rbit[4]={0, 2, 1, 3}; +#ifdef __i386__ + unsigned int *data2=(unsigned int *)r_data2; +#else + unsigned int data2[16]; + for (i=0;i<16;i++) + data2[i]=GET_LE32(r_data2+(i<<2)); +#endif + w0=GET_LE32(r_data1); + w1=GET_LE32(r_data1+4); + w2=GET_LE32(r_data1+8); + w3=GET_LE32(r_data1+12); + for (i=0;i<16;i+=4) { + w0=rol32(w0 + ((w1 & w2) | ((~w1) & w3)) + data2[i+0],3); + w3=rol32(w3 + ((w0 & w1) | ((~w0) & w2)) + data2[i+1],7); + w2=rol32(w2 + ((w3 & w0) | ((~w3) & w1)) + data2[i+2],11); + w1=rol32(w1 + ((w2 & w3) | ((~w2) & w0)) + data2[i+3],19); + } + for (i=0;i<4;i++) { + w0=rol32(w0 + (((w2 | w3) & w1) | (w2 & w3)) + 0x5a827999 + data2[i+0],3); + w3=rol32(w3 + (((w1 | w2) & w0) | (w1 & w2)) + 0x5a827999 + data2[i+4],5); + w2=rol32(w2 + (((w0 | w1) & w3) | (w0 & w1)) + 0x5a827999 + data2[i+8],9); + w1=rol32(w1 + (((w3 | w0) & w2) | (w3 & w0)) + 0x5a827999 + data2[i+12],13); + } + for (i=0;i<4;i++) { + w0=rol32(w0 + ((w1 ^ w2) ^ w3) + 0x6ed9eba1 + data2[rbit[i]+0],3); + w3=rol32(w3 + ((w0 ^ w1) ^ w2) + 0x6ed9eba1 + data2[rbit[i]+8],9); + w2=rol32(w2 + ((w3 ^ w0) ^ w1) + 0x6ed9eba1 + data2[rbit[i]+4],11); + w1=rol32(w1 + ((w2 ^ w3) ^ w0) + 0x6ed9eba1 + data2[rbit[i]+12],15); + } + PUT_LE32(outdata,(w0+GET_LE32(r_data1)) & 0xffffffff); + PUT_LE32(outdata+4,(w1+GET_LE32(r_data1+4)) & 0xffffffff); + PUT_LE32(outdata+8,(w2+GET_LE32(r_data1+8)) & 0xffffffff); + PUT_LE32(outdata+12,(w3+GET_LE32(r_data1+12)) & 0xffffffff); +} + +/* Make a signature for the current packet and add it at the end of the */ +/* packet. */ +void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) { + unsigned char data[64]; + + memcpy(data, server->sign_root, 8); + *(__u32*)(data + 8) = totalsize; + if (size < 52) { + memcpy(data + 12, packet, size); + memset(data + 12 + size, 0, 52 - size); + } else { + memcpy(data + 12, packet, 52); + } + nwsign(server->sign_last, data, server->sign_last); + memcpy(sign_buff, server->sign_last, 8); +} + +int sign_verify_reply(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, const void *sign_buff) { + unsigned char data[64]; + unsigned char hash[16]; + + memcpy(data, server->sign_root, 8); + *(__u32*)(data + 8) = totalsize; + if (size < 52) { + memcpy(data + 12, packet, size); + memset(data + 12 + size, 0, 52 - size); + } else { + memcpy(data + 12, packet, 52); + } + nwsign(server->sign_last, data, hash); + return memcmp(sign_buff, hash, 8); +} + +#endif /* CONFIG_NCPFS_PACKET_SIGNING */ + diff --git a/drivers/staging/ncpfs/ncpsign_kernel.h b/drivers/staging/ncpfs/ncpsign_kernel.h new file mode 100644 index 000000000000..57ff0a0650b8 --- /dev/null +++ b/drivers/staging/ncpfs/ncpsign_kernel.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ncpsign_kernel.h + * + * Arne de Bruijn (arne@knoware.nl), 1997 + * + */ + +#ifndef _NCPSIGN_KERNEL_H +#define _NCPSIGN_KERNEL_H + +#ifdef CONFIG_NCPFS_PACKET_SIGNING +void __sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff); +int sign_verify_reply(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, const void *sign_buff); +#endif + +static inline size_t sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff) { +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active) { + __sign_packet(server, data, size, totalsize, sign_buff); + return 8; + } +#endif + return 0; +} + +#endif diff --git a/drivers/staging/ncpfs/sock.c b/drivers/staging/ncpfs/sock.c new file mode 100644 index 000000000000..efb176b1751a --- /dev/null +++ b/drivers/staging/ncpfs/sock.c @@ -0,0 +1,854 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * linux/fs/ncpfs/sock.c + * + * Copyright (C) 1992, 1993 Rick Sladkey + * + * Modified 1995, 1996 by Volker Lendecke to be usable for ncp + * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ncp_fs.h" + +#include "ncpsign_kernel.h" + +static int _recv(struct socket *sock, void *buf, int size, unsigned flags) +{ + struct msghdr msg = {NULL, }; + struct kvec iov = {buf, size}; + return kernel_recvmsg(sock, &msg, &iov, 1, size, flags); +} + +static int _send(struct socket *sock, const void *buff, int len) +{ + struct msghdr msg = { .msg_flags = 0 }; + struct kvec vec = {.iov_base = (void *)buff, .iov_len = len}; + iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &vec, 1, len); + return sock_sendmsg(sock, &msg); +} + +struct ncp_request_reply { + struct list_head req; + wait_queue_head_t wq; + atomic_t refs; + unsigned char* reply_buf; + size_t datalen; + int result; + enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status; + struct iov_iter from; + struct kvec tx_iov[3]; + u_int16_t tx_type; + u_int32_t sign[6]; +}; + +static inline struct ncp_request_reply* ncp_alloc_req(void) +{ + struct ncp_request_reply *req; + + req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL); + if (!req) + return NULL; + + init_waitqueue_head(&req->wq); + atomic_set(&req->refs, (1)); + req->status = RQ_IDLE; + + return req; +} + +static void ncp_req_get(struct ncp_request_reply *req) +{ + atomic_inc(&req->refs); +} + +static void ncp_req_put(struct ncp_request_reply *req) +{ + if (atomic_dec_and_test(&req->refs)) + kfree(req); +} + +void ncp_tcp_data_ready(struct sock *sk) +{ + struct ncp_server *server = sk->sk_user_data; + + server->data_ready(sk); + schedule_work(&server->rcv.tq); +} + +void ncp_tcp_error_report(struct sock *sk) +{ + struct ncp_server *server = sk->sk_user_data; + + server->error_report(sk); + schedule_work(&server->rcv.tq); +} + +void ncp_tcp_write_space(struct sock *sk) +{ + struct ncp_server *server = sk->sk_user_data; + + /* We do not need any locking: we first set tx.creq, and then we do sendmsg, + not vice versa... */ + server->write_space(sk); + if (server->tx.creq) + schedule_work(&server->tx.tq); +} + +void ncpdgram_timeout_call(struct timer_list *t) +{ + struct ncp_server *server = from_timer(server, t, timeout_tm); + + schedule_work(&server->timeout_tq); +} + +static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result) +{ + req->result = result; + if (req->status != RQ_ABANDONED) + memcpy(req->reply_buf, server->rxbuf, req->datalen); + req->status = RQ_DONE; + wake_up_all(&req->wq); + ncp_req_put(req); +} + +static void __abort_ncp_connection(struct ncp_server *server) +{ + struct ncp_request_reply *req; + + ncp_invalidate_conn(server); + del_timer(&server->timeout_tm); + while (!list_empty(&server->tx.requests)) { + req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); + + list_del_init(&req->req); + ncp_finish_request(server, req, -EIO); + } + req = server->rcv.creq; + if (req) { + server->rcv.creq = NULL; + ncp_finish_request(server, req, -EIO); + server->rcv.ptr = NULL; + server->rcv.state = 0; + } + req = server->tx.creq; + if (req) { + server->tx.creq = NULL; + ncp_finish_request(server, req, -EIO); + } +} + +static inline int get_conn_number(struct ncp_reply_header *rp) +{ + return rp->conn_low | (rp->conn_high << 8); +} + +static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) +{ + /* If req is done, we got signal, but we also received answer... */ + switch (req->status) { + case RQ_IDLE: + case RQ_DONE: + break; + case RQ_QUEUED: + list_del_init(&req->req); + ncp_finish_request(server, req, err); + break; + case RQ_INPROGRESS: + req->status = RQ_ABANDONED; + break; + case RQ_ABANDONED: + break; + } +} + +static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) +{ + mutex_lock(&server->rcv.creq_mutex); + __ncp_abort_request(server, req, err); + mutex_unlock(&server->rcv.creq_mutex); +} + +static inline void __ncptcp_abort(struct ncp_server *server) +{ + __abort_ncp_connection(server); +} + +static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) +{ + struct msghdr msg = { .msg_iter = req->from, .msg_flags = MSG_DONTWAIT }; + return sock_sendmsg(sock, &msg); +} + +static void __ncptcp_try_send(struct ncp_server *server) +{ + struct ncp_request_reply *rq; + struct msghdr msg = { .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT }; + int result; + + rq = server->tx.creq; + if (!rq) + return; + + msg.msg_iter = rq->from; + result = sock_sendmsg(server->ncp_sock, &msg); + + if (result == -EAGAIN) + return; + + if (result < 0) { + pr_err("tcp: Send failed: %d\n", result); + __ncp_abort_request(server, rq, result); + return; + } + if (!msg_data_left(&msg)) { + server->rcv.creq = rq; + server->tx.creq = NULL; + return; + } + rq->from = msg.msg_iter; +} + +static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) +{ + req->status = RQ_INPROGRESS; + h->conn_low = server->connection; + h->conn_high = server->connection >> 8; + h->sequence = ++server->sequence; +} + +static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) +{ + size_t signlen, len = req->tx_iov[1].iov_len; + struct ncp_request_header *h = req->tx_iov[1].iov_base; + + ncp_init_header(server, req, h); + signlen = sign_packet(server, + req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, + len - sizeof(struct ncp_request_header) + 1, + cpu_to_le32(len), req->sign); + if (signlen) { + /* NCP over UDP appends signature */ + req->tx_iov[2].iov_base = req->sign; + req->tx_iov[2].iov_len = signlen; + } + iov_iter_kvec(&req->from, WRITE | ITER_KVEC, + req->tx_iov + 1, signlen ? 2 : 1, len + signlen); + server->rcv.creq = req; + server->timeout_last = server->m.time_out; + server->timeout_retries = server->m.retry_count; + ncpdgram_send(server->ncp_sock, req); + mod_timer(&server->timeout_tm, jiffies + server->m.time_out); +} + +#define NCP_TCP_XMIT_MAGIC (0x446D6454) +#define NCP_TCP_XMIT_VERSION (1) +#define NCP_TCP_RCVD_MAGIC (0x744E6350) + +static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) +{ + size_t signlen, len = req->tx_iov[1].iov_len; + struct ncp_request_header *h = req->tx_iov[1].iov_base; + + ncp_init_header(server, req, h); + signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, + len - sizeof(struct ncp_request_header) + 1, + cpu_to_be32(len + 24), req->sign + 4) + 16; + + req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC); + req->sign[1] = htonl(len + signlen); + req->sign[2] = htonl(NCP_TCP_XMIT_VERSION); + req->sign[3] = htonl(req->datalen + 8); + /* NCP over TCP prepends signature */ + req->tx_iov[0].iov_base = req->sign; + req->tx_iov[0].iov_len = signlen; + iov_iter_kvec(&req->from, WRITE | ITER_KVEC, + req->tx_iov, 2, len + signlen); + + server->tx.creq = req; + __ncptcp_try_send(server); +} + +static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) +{ + /* we copy the data so that we do not depend on the caller + staying alive */ + memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len); + req->tx_iov[1].iov_base = server->txbuf; + + if (server->ncp_sock->type == SOCK_STREAM) + ncptcp_start_request(server, req); + else + ncpdgram_start_request(server, req); +} + +static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req) +{ + mutex_lock(&server->rcv.creq_mutex); + if (!ncp_conn_valid(server)) { + mutex_unlock(&server->rcv.creq_mutex); + pr_err("tcp: Server died\n"); + return -EIO; + } + ncp_req_get(req); + if (server->tx.creq || server->rcv.creq) { + req->status = RQ_QUEUED; + list_add_tail(&req->req, &server->tx.requests); + mutex_unlock(&server->rcv.creq_mutex); + return 0; + } + __ncp_start_request(server, req); + mutex_unlock(&server->rcv.creq_mutex); + return 0; +} + +static void __ncp_next_request(struct ncp_server *server) +{ + struct ncp_request_reply *req; + + server->rcv.creq = NULL; + if (list_empty(&server->tx.requests)) { + return; + } + req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); + list_del_init(&req->req); + __ncp_start_request(server, req); +} + +static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) +{ + if (server->info_sock) { + struct msghdr msg = { .msg_flags = MSG_NOSIGNAL }; + __be32 hdr[2] = {cpu_to_be32(len + 8), cpu_to_be32(id)}; + struct kvec iov[2] = { + {.iov_base = hdr, .iov_len = 8}, + {.iov_base = (void *)data, .iov_len = len}, + }; + + iov_iter_kvec(&msg.msg_iter, ITER_KVEC | WRITE, + iov, 2, len + 8); + + sock_sendmsg(server->info_sock, &msg); + } +} + +void ncpdgram_rcv_proc(struct work_struct *work) +{ + struct ncp_server *server = + container_of(work, struct ncp_server, rcv.tq); + struct socket* sock; + + sock = server->ncp_sock; + + while (1) { + struct ncp_reply_header reply; + int result; + + result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT); + if (result < 0) { + break; + } + if (result >= sizeof(reply)) { + struct ncp_request_reply *req; + + if (reply.type == NCP_WATCHDOG) { + unsigned char buf[10]; + + if (server->connection != get_conn_number(&reply)) { + goto drop; + } + result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT); + if (result < 0) { + ncp_dbg(1, "recv failed with %d\n", result); + continue; + } + if (result < 10) { + ncp_dbg(1, "too short (%u) watchdog packet\n", result); + continue; + } + if (buf[9] != '?') { + ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]); + continue; + } + buf[9] = 'Y'; + _send(sock, buf, sizeof(buf)); + continue; + } + if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) { + result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT); + if (result < 0) { + continue; + } + info_server(server, 0, server->unexpected_packet.data, result); + continue; + } + mutex_lock(&server->rcv.creq_mutex); + req = server->rcv.creq; + if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && + server->connection == get_conn_number(&reply)))) { + if (reply.type == NCP_POSITIVE_ACK) { + server->timeout_retries = server->m.retry_count; + server->timeout_last = NCP_MAX_RPC_TIMEOUT; + mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT); + } else if (reply.type == NCP_REPLY) { + result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT); +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { + if (result < 8 + 8) { + result = -EIO; + } else { + unsigned int hdrl; + + result -= 8; + hdrl = sock->sk->sk_family == AF_INET ? 8 : 6; + if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) { + pr_info("Signature violation\n"); + result = -EIO; + } + } + } +#endif + del_timer(&server->timeout_tm); + server->rcv.creq = NULL; + ncp_finish_request(server, req, result); + __ncp_next_request(server); + mutex_unlock(&server->rcv.creq_mutex); + continue; + } + } + mutex_unlock(&server->rcv.creq_mutex); + } +drop:; + _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT); + } +} + +static void __ncpdgram_timeout_proc(struct ncp_server *server) +{ + /* If timer is pending, we are processing another request... */ + if (!timer_pending(&server->timeout_tm)) { + struct ncp_request_reply* req; + + req = server->rcv.creq; + if (req) { + int timeout; + + if (server->m.flags & NCP_MOUNT_SOFT) { + if (server->timeout_retries-- == 0) { + __ncp_abort_request(server, req, -ETIMEDOUT); + return; + } + } + /* Ignore errors */ + ncpdgram_send(server->ncp_sock, req); + timeout = server->timeout_last << 1; + if (timeout > NCP_MAX_RPC_TIMEOUT) { + timeout = NCP_MAX_RPC_TIMEOUT; + } + server->timeout_last = timeout; + mod_timer(&server->timeout_tm, jiffies + timeout); + } + } +} + +void ncpdgram_timeout_proc(struct work_struct *work) +{ + struct ncp_server *server = + container_of(work, struct ncp_server, timeout_tq); + mutex_lock(&server->rcv.creq_mutex); + __ncpdgram_timeout_proc(server); + mutex_unlock(&server->rcv.creq_mutex); +} + +static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) +{ + int result; + + if (buffer) { + result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT); + } else { + static unsigned char dummy[1024]; + + if (len > sizeof(dummy)) { + len = sizeof(dummy); + } + result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT); + } + if (result < 0) { + return result; + } + if (result > len) { + pr_err("tcp: bug in recvmsg (%u > %zu)\n", result, len); + return -EIO; + } + return result; +} + +static int __ncptcp_rcv_proc(struct ncp_server *server) +{ + /* We have to check the result, so store the complete header */ + while (1) { + int result; + struct ncp_request_reply *req; + int datalen; + int type; + + while (server->rcv.len) { + result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len); + if (result == -EAGAIN) { + return 0; + } + if (result <= 0) { + req = server->rcv.creq; + if (req) { + __ncp_abort_request(server, req, -EIO); + } else { + __ncptcp_abort(server); + } + if (result < 0) { + pr_err("tcp: error in recvmsg: %d\n", result); + } else { + ncp_dbg(1, "tcp: EOF\n"); + } + return -EIO; + } + if (server->rcv.ptr) { + server->rcv.ptr += result; + } + server->rcv.len -= result; + } + switch (server->rcv.state) { + case 0: + if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) { + pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic)); + __ncptcp_abort(server); + return -EIO; + } + datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF; + if (datalen < 10) { + pr_err("tcp: Unexpected reply len %d\n", datalen); + __ncptcp_abort(server); + return -EIO; + } +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active) { + if (datalen < 18) { + pr_err("tcp: Unexpected reply len %d\n", datalen); + __ncptcp_abort(server); + return -EIO; + } + server->rcv.buf.len = datalen - 8; + server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1; + server->rcv.len = 8; + server->rcv.state = 4; + break; + } +#endif + type = ntohs(server->rcv.buf.type); +#ifdef CONFIG_NCPFS_PACKET_SIGNING +cont:; +#endif + if (type != NCP_REPLY) { + if (datalen - 8 <= sizeof(server->unexpected_packet.data)) { + *(__u16*)(server->unexpected_packet.data) = htons(type); + server->unexpected_packet.len = datalen - 8; + + server->rcv.state = 5; + server->rcv.ptr = server->unexpected_packet.data + 2; + server->rcv.len = datalen - 10; + break; + } + ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type); +skipdata2:; + server->rcv.state = 2; +skipdata:; + server->rcv.ptr = NULL; + server->rcv.len = datalen - 10; + break; + } + req = server->rcv.creq; + if (!req) { + ncp_dbg(1, "Reply without appropriate request\n"); + goto skipdata2; + } + if (datalen > req->datalen + 8) { + pr_err("tcp: Unexpected reply len %d (expected at most %zd)\n", datalen, req->datalen + 8); + server->rcv.state = 3; + goto skipdata; + } + req->datalen = datalen - 8; + ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY; + server->rcv.ptr = server->rxbuf + 2; + server->rcv.len = datalen - 10; + server->rcv.state = 1; + break; +#ifdef CONFIG_NCPFS_PACKET_SIGNING + case 4: + datalen = server->rcv.buf.len; + type = ntohs(server->rcv.buf.type2); + goto cont; +#endif + case 1: + req = server->rcv.creq; + if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { + if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) { + pr_err("tcp: Bad sequence number\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) { + pr_err("tcp: Connection number mismatch\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + } +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { + if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { + pr_err("tcp: Signature violation\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + } +#endif + ncp_finish_request(server, req, req->datalen); + nextreq:; + __ncp_next_request(server); + case 2: + next:; + server->rcv.ptr = (unsigned char*)&server->rcv.buf; + server->rcv.len = 10; + server->rcv.state = 0; + break; + case 3: + ncp_finish_request(server, server->rcv.creq, -EIO); + goto nextreq; + case 5: + info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len); + goto next; + } + } +} + +void ncp_tcp_rcv_proc(struct work_struct *work) +{ + struct ncp_server *server = + container_of(work, struct ncp_server, rcv.tq); + + mutex_lock(&server->rcv.creq_mutex); + __ncptcp_rcv_proc(server); + mutex_unlock(&server->rcv.creq_mutex); +} + +void ncp_tcp_tx_proc(struct work_struct *work) +{ + struct ncp_server *server = + container_of(work, struct ncp_server, tx.tq); + + mutex_lock(&server->rcv.creq_mutex); + __ncptcp_try_send(server); + mutex_unlock(&server->rcv.creq_mutex); +} + +static int do_ncp_rpc_call(struct ncp_server *server, int size, + unsigned char* reply_buf, int max_reply_size) +{ + int result; + struct ncp_request_reply *req; + + req = ncp_alloc_req(); + if (!req) + return -ENOMEM; + + req->reply_buf = reply_buf; + req->datalen = max_reply_size; + req->tx_iov[1].iov_base = server->packet; + req->tx_iov[1].iov_len = size; + req->tx_type = *(u_int16_t*)server->packet; + + result = ncp_add_request(server, req); + if (result < 0) + goto out; + + if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) { + ncp_abort_request(server, req, -EINTR); + result = -EINTR; + goto out; + } + + result = req->result; + +out: + ncp_req_put(req); + + return result; +} + +/* + * We need the server to be locked here, so check! + */ + +static int ncp_do_request(struct ncp_server *server, int size, + void* reply, int max_reply_size) +{ + int result; + + if (server->lock == 0) { + pr_err("Server not locked!\n"); + return -EIO; + } + if (!ncp_conn_valid(server)) { + return -EIO; + } + { + sigset_t old_set; + unsigned long mask, flags; + + spin_lock_irqsave(¤t->sighand->siglock, flags); + old_set = current->blocked; + if (current->flags & PF_EXITING) + mask = 0; + else + mask = sigmask(SIGKILL); + if (server->m.flags & NCP_MOUNT_INTR) { + /* FIXME: This doesn't seem right at all. So, like, + we can't handle SIGINT and get whatever to stop? + What if we've blocked it ourselves? What about + alarms? Why, in fact, are we mucking with the + sigmask at all? -- r~ */ + if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL) + mask |= sigmask(SIGINT); + if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL) + mask |= sigmask(SIGQUIT); + } + siginitsetinv(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + + result = do_ncp_rpc_call(server, size, reply, max_reply_size); + + spin_lock_irqsave(¤t->sighand->siglock, flags); + current->blocked = old_set; + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + } + + ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result); + + return result; +} + +/* ncp_do_request assures that at least a complete reply header is + * received. It assumes that server->current_size contains the ncp + * request size + */ +int ncp_request2(struct ncp_server *server, int function, + void* rpl, int size) +{ + struct ncp_request_header *h; + struct ncp_reply_header* reply = rpl; + int result; + + h = (struct ncp_request_header *) (server->packet); + if (server->has_subfunction != 0) { + *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2); + } + h->type = NCP_REQUEST; + /* + * The server shouldn't know or care what task is making a + * request, so we always use the same task number. + */ + h->task = 2; /* (current->pid) & 0xff; */ + h->function = function; + + result = ncp_do_request(server, server->current_size, reply, size); + if (result < 0) { + ncp_dbg(1, "ncp_request_error: %d\n", result); + goto out; + } + server->completion = reply->completion_code; + server->conn_status = reply->connection_state; + server->reply_size = result; + server->ncp_reply_size = result - sizeof(struct ncp_reply_header); + + result = reply->completion_code; + + if (result != 0) + ncp_vdbg("completion code=%x\n", result); +out: + return result; +} + +int ncp_connect(struct ncp_server *server) +{ + struct ncp_request_header *h; + int result; + + server->connection = 0xFFFF; + server->sequence = 255; + + h = (struct ncp_request_header *) (server->packet); + h->type = NCP_ALLOC_SLOT_REQUEST; + h->task = 2; /* see above */ + h->function = 0; + + result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); + if (result < 0) + goto out; + server->connection = h->conn_low + (h->conn_high * 256); + result = 0; +out: + return result; +} + +int ncp_disconnect(struct ncp_server *server) +{ + struct ncp_request_header *h; + + h = (struct ncp_request_header *) (server->packet); + h->type = NCP_DEALLOC_SLOT_REQUEST; + h->task = 2; /* see above */ + h->function = 0; + + return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); +} + +void ncp_lock_server(struct ncp_server *server) +{ + mutex_lock(&server->mutex); + if (server->lock) + pr_warn("%s: was locked!\n", __func__); + server->lock = 1; +} + +void ncp_unlock_server(struct ncp_server *server) +{ + if (!server->lock) { + pr_warn("%s: was not locked!\n", __func__); + return; + } + server->lock = 0; + mutex_unlock(&server->mutex); +} diff --git a/drivers/staging/ncpfs/symlink.c b/drivers/staging/ncpfs/symlink.c new file mode 100644 index 000000000000..b6e16da4837a --- /dev/null +++ b/drivers/staging/ncpfs/symlink.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * linux/fs/ncpfs/symlink.c + * + * Code for allowing symbolic links on NCPFS (i.e. NetWare) + * Symbolic links are not supported on native NetWare, so we use an + * infrequently-used flag (Sh) and store a two-word magic header in + * the file to make sure we don't accidentally use a non-link file + * as a link. + * + * When using the NFS namespace, we set the mode to indicate a symlink and + * don't bother with the magic numbers. + * + * from linux/fs/ext2/symlink.c + * + * Copyright (C) 1998-99, Frank A. Vorstenbosch + * + * ncpfs symlink handling code + * NLS support (c) 1999 Petr Vandrovec + * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info + * + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include "ncp_fs.h" + +/* these magic numbers must appear in the symlink file -- this makes it a bit + more resilient against the magic attributes being set on random files. */ + +#define NCP_SYMLINK_MAGIC0 cpu_to_le32(0x6c6d7973) /* "symlnk->" */ +#define NCP_SYMLINK_MAGIC1 cpu_to_le32(0x3e2d6b6e) + +/* ----- read a symbolic link ------------------------------------------ */ + +static int ncp_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int error, length, len; + char *link, *rawlink; + char *buf = kmap(page); + + error = -ENOMEM; + rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL); + if (!rawlink) + goto fail; + + if (ncp_make_open(inode,O_RDONLY)) + goto failEIO; + + error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, + 0,NCP_MAX_SYMLINK_SIZE,rawlink,&length); + + ncp_inode_close(inode); + /* Close file handle if no other users... */ + ncp_make_closed(inode); + if (error) + goto failEIO; + + if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) { + if (lengthvolNumber)) + kludge = 0; + else +#ifdef CONFIG_NCPFS_EXTRAS + if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS) + kludge = 1; + else +#endif + /* EPERM is returned by VFS if symlink procedure does not exist */ + return -EPERM; + + rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL); + if (!rawlink) + return -ENOMEM; + + if (kludge) { + mode = 0; + attr = aSHARED | aHIDDEN; + ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0; + ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1; + hdr = 8; + } else { + mode = S_IFLNK | S_IRWXUGO; + attr = 0; + hdr = 0; + } + + length = strlen(symname); + /* map to/from server charset, do not touch upper/lower case as + symlink can point out of ncp filesystem */ + outlen = NCP_MAX_SYMLINK_SIZE - hdr; + err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0); + if (err) + goto failfree; + + outlen += hdr; + + err = -EIO; + if (ncp_create_new(dir,dentry,mode,0,attr)) { + goto failfree; + } + + inode=d_inode(dentry); + + if (ncp_make_open(inode, O_WRONLY)) + goto failfree; + + if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + 0, outlen, rawlink, &i) || i!=outlen) { + goto fail; + } + + ncp_inode_close(inode); + ncp_make_closed(inode); + kfree(rawlink); + return 0; +fail:; + ncp_inode_close(inode); + ncp_make_closed(inode); +failfree:; + kfree(rawlink); + return err; +} + +/* ----- EOF ----- */ diff --git a/fs/Kconfig b/fs/Kconfig index 7aee6d699fd6..eaf968bf9cfc 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -298,7 +298,6 @@ config NFS_COMMON source "net/sunrpc/Kconfig" source "fs/ceph/Kconfig" source "fs/cifs/Kconfig" -source "fs/ncpfs/Kconfig" source "fs/coda/Kconfig" source "fs/afs/Kconfig" source "fs/9p/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index ef772f1eaff8..add789ea270a 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -92,7 +92,6 @@ obj-$(CONFIG_LOCKD) += lockd/ obj-$(CONFIG_NLS) += nls/ obj-$(CONFIG_SYSV_FS) += sysv/ obj-$(CONFIG_CIFS) += cifs/ -obj-$(CONFIG_NCP_FS) += ncpfs/ obj-$(CONFIG_HPFS_FS) += hpfs/ obj-$(CONFIG_NTFS_FS) += ntfs/ obj-$(CONFIG_UFS_FS) += ufs/ diff --git a/fs/ncpfs/Kconfig b/fs/ncpfs/Kconfig deleted file mode 100644 index c931cf22a1f6..000000000000 --- a/fs/ncpfs/Kconfig +++ /dev/null @@ -1,108 +0,0 @@ -# -# NCP Filesystem configuration -# -config NCP_FS - tristate "NCP file system support (to mount NetWare volumes)" - depends on IPX!=n || INET - help - NCP (NetWare Core Protocol) is a protocol that runs over IPX and is - used by Novell NetWare clients to talk to file servers. It is to - IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you - to mount NetWare file server volumes and to access them just like - any other Unix directory. For details, please read the file - in the kernel source and - the IPX-HOWTO from . - - You do not have to say Y here if you want your Linux box to act as a - file *server* for Novell NetWare clients. - - General information about how to connect Linux, Windows machines and - Macs is on the WWW at . - - To compile this as a module, choose M here: the module will be called - ncpfs. Say N unless you are connected to a Novell network. - -config NCPFS_PACKET_SIGNING - bool "Packet signatures" - depends on NCP_FS - help - NCP allows packets to be signed for stronger security. If you want - security, say Y. Normal users can leave it off. To be able to use - packet signing you must use ncpfs > 2.0.12. - -config NCPFS_IOCTL_LOCKING - bool "Proprietary file locking" - depends on NCP_FS - help - Allows locking of records on remote volumes. Say N unless you have - special applications which are able to utilize this locking scheme. - -config NCPFS_STRONG - bool "Clear remove/delete inhibit when needed" - depends on NCP_FS - help - Allows manipulation of files flagged as Delete or Rename Inhibit. - To use this feature you must mount volumes with the ncpmount - parameter "-s" (ncpfs-2.0.12 and newer). Say Y unless you are not - mounting volumes with -f 444. - -config NCPFS_NFS_NS - bool "Use NFS namespace if available" - depends on NCP_FS - help - Allows you to utilize NFS namespace on NetWare servers. It brings - you case sensitive filenames. Say Y. You can disable it at - mount-time with the `-N nfs' parameter of ncpmount. - -config NCPFS_OS2_NS - bool "Use LONG (OS/2) namespace if available" - depends on NCP_FS - help - Allows you to utilize OS2/LONG namespace on NetWare servers. - Filenames in this namespace are limited to 255 characters, they are - case insensitive, and case in names is preserved. Say Y. You can - disable it at mount time with the -N os2 parameter of ncpmount. - -config NCPFS_SMALLDOS - bool "Lowercase DOS filenames" - depends on NCP_FS - ---help--- - If you say Y here, every filename on a NetWare server volume using - the OS2/LONG namespace and created under DOS or on a volume using - DOS namespace will be converted to lowercase characters. - Saying N here will give you these filenames in uppercase. - - This is only a cosmetic option since the OS2/LONG namespace is case - insensitive. The only major reason for this option is backward - compatibility when moving from DOS to OS2/LONG namespace support. - Long filenames (created by Win95) will not be affected. - - This option does not solve the problem that filenames appear - differently under Linux and under Windows, since Windows does an - additional conversions on the client side. You can achieve similar - effects by saying Y to "Allow using of Native Language Support" - below. - -config NCPFS_NLS - bool "Use Native Language Support" - depends on NCP_FS - select NLS - help - Allows you to use codepages and I/O charsets for file name - translation between the server file system and input/output. This - may be useful, if you want to access the server with other operating - systems, e.g. Windows 95. See also NLS for more Information. - - To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer. - -config NCPFS_EXTRAS - bool "Enable symbolic links and execute flags" - depends on NCP_FS - help - This enables the use of symbolic links and an execute permission - bit on NCPFS. The file server need not have long name space or NFS - name space loaded for these to work. - - To use the new attributes, it is recommended to use the flags - '-f 600 -d 755' on the ncpmount command line. - diff --git a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile deleted file mode 100644 index 66fe5f878817..000000000000 --- a/fs/ncpfs/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the linux ncp filesystem routines. -# - -obj-$(CONFIG_NCP_FS) += ncpfs.o - -ncpfs-y := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \ - ncpsign_kernel.o getopt.o - -ncpfs-$(CONFIG_NCPFS_EXTRAS) += symlink.o -ncpfs-$(CONFIG_NCPFS_NFS_NS) += symlink.o - -# If you want debugging output, please uncomment the following line -# ccflags-y := -DDEBUG_NCP=1 - -CFLAGS_ncplib_kernel.o := -finline-functions diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c deleted file mode 100644 index 0c57c5c5d40a..000000000000 --- a/fs/ncpfs/dir.c +++ /dev/null @@ -1,1232 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dir.c - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * Modified for big endian by J.F. Chadima and David S. Miller - * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache - * Modified 1998, 1999 Wolfram Pienkoss for NLS - * Modified 1999 Wolfram Pienkoss for directory caching - * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ncp_fs.h" - -static void ncp_read_volume_list(struct file *, struct dir_context *, - struct ncp_cache_control *); -static void ncp_do_readdir(struct file *, struct dir_context *, - struct ncp_cache_control *); - -static int ncp_readdir(struct file *, struct dir_context *); - -static int ncp_create(struct inode *, struct dentry *, umode_t, bool); -static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int); -static int ncp_unlink(struct inode *, struct dentry *); -static int ncp_mkdir(struct inode *, struct dentry *, umode_t); -static int ncp_rmdir(struct inode *, struct dentry *); -static int ncp_rename(struct inode *, struct dentry *, - struct inode *, struct dentry *, unsigned int); -static int ncp_mknod(struct inode * dir, struct dentry *dentry, - umode_t mode, dev_t rdev); -#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) -extern int ncp_symlink(struct inode *, struct dentry *, const char *); -#else -#define ncp_symlink NULL -#endif - -const struct file_operations ncp_dir_operations = -{ - .llseek = generic_file_llseek, - .read = generic_read_dir, - .iterate = ncp_readdir, - .unlocked_ioctl = ncp_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ncp_compat_ioctl, -#endif -}; - -const struct inode_operations ncp_dir_inode_operations = -{ - .create = ncp_create, - .lookup = ncp_lookup, - .unlink = ncp_unlink, - .symlink = ncp_symlink, - .mkdir = ncp_mkdir, - .rmdir = ncp_rmdir, - .mknod = ncp_mknod, - .rename = ncp_rename, - .setattr = ncp_notify_change, -}; - -/* - * Dentry operations routines - */ -static int ncp_lookup_validate(struct dentry *, unsigned int); -static int ncp_hash_dentry(const struct dentry *, struct qstr *); -static int ncp_compare_dentry(const struct dentry *, - unsigned int, const char *, const struct qstr *); -static int ncp_delete_dentry(const struct dentry *); -static void ncp_d_prune(struct dentry *dentry); - -const struct dentry_operations ncp_dentry_operations = -{ - .d_revalidate = ncp_lookup_validate, - .d_hash = ncp_hash_dentry, - .d_compare = ncp_compare_dentry, - .d_delete = ncp_delete_dentry, - .d_prune = ncp_d_prune, -}; - -#define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) - -static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) -{ -#ifdef CONFIG_NCPFS_SMALLDOS - int ns = ncp_namespace(i); - - if ((ns == NW_NS_DOS) -#ifdef CONFIG_NCPFS_OS2_NS - || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS)) -#endif /* CONFIG_NCPFS_OS2_NS */ - ) - return 0; -#endif /* CONFIG_NCPFS_SMALLDOS */ - return 1; -} - -#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) - -static inline int ncp_case_sensitive(const struct inode *i) -{ -#ifdef CONFIG_NCPFS_NFS_NS - return ncp_namespace(i) == NW_NS_NFS; -#else - return 0; -#endif /* CONFIG_NCPFS_NFS_NS */ -} - -/* - * Note: leave the hash unchanged if the directory - * is case-sensitive. - */ -static int -ncp_hash_dentry(const struct dentry *dentry, struct qstr *this) -{ - struct inode *inode = d_inode_rcu(dentry); - - if (!inode) - return 0; - - if (!ncp_case_sensitive(inode)) { - struct nls_table *t; - unsigned long hash; - int i; - - t = NCP_IO_TABLE(dentry->d_sb); - hash = init_name_hash(dentry); - for (i=0; ilen ; i++) - hash = partial_name_hash(ncp_tolower(t, this->name[i]), - hash); - this->hash = end_name_hash(hash); - } - return 0; -} - -static int -ncp_compare_dentry(const struct dentry *dentry, - unsigned int len, const char *str, const struct qstr *name) -{ - struct inode *pinode; - - if (len != name->len) - return 1; - - pinode = d_inode_rcu(dentry->d_parent); - if (!pinode) - return 1; - - if (ncp_case_sensitive(pinode)) - return strncmp(str, name->name, len); - - return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len); -} - -/* - * This is the callback from dput() when d_count is going to 0. - * We use this to unhash dentries with bad inodes. - * Closing files can be safely postponed until iput() - it's done there anyway. - */ -static int -ncp_delete_dentry(const struct dentry * dentry) -{ - struct inode *inode = d_inode(dentry); - - if (inode) { - if (is_bad_inode(inode)) - return 1; - } else - { - /* N.B. Unhash negative dentries? */ - } - return 0; -} - -static inline int -ncp_single_volume(struct ncp_server *server) -{ - return (server->m.mounted_vol[0] != '\0'); -} - -static inline int ncp_is_server_root(struct inode *inode) -{ - return !ncp_single_volume(NCP_SERVER(inode)) && - is_root_inode(inode); -} - - -/* - * This is the callback when the dcache has a lookup hit. - */ - - -#ifdef CONFIG_NCPFS_STRONG -/* try to delete a readonly file (NW R bit set) */ - -static int -ncp_force_unlink(struct inode *dir, struct dentry* dentry) -{ - int res=0x9c,res2; - struct nw_modify_dos_info info; - __le32 old_nwattr; - struct inode *inode; - - memset(&info, 0, sizeof(info)); - - /* remove the Read-Only flag on the NW server */ - inode = d_inode(dentry); - - old_nwattr = NCP_FINFO(inode)->nwattr; - info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT); - res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); - if (res2) - goto leave_me; - - /* now try again the delete operation */ - res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry); - - if (res) /* delete failed, set R bit again */ - { - info.attributes = old_nwattr; - res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); - if (res2) - goto leave_me; - } -leave_me: - return(res); -} -#endif /* CONFIG_NCPFS_STRONG */ - -#ifdef CONFIG_NCPFS_STRONG -static int -ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name, - struct inode *new_dir, struct dentry* new_dentry, char *_new_name) -{ - struct nw_modify_dos_info info; - int res=0x90,res2; - struct inode *old_inode = d_inode(old_dentry); - __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr; - __le32 new_nwattr = 0; /* shut compiler warning */ - int old_nwattr_changed = 0; - int new_nwattr_changed = 0; - - memset(&info, 0, sizeof(info)); - - /* remove the Read-Only flag on the NW server */ - - info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); - res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); - if (!res2) - old_nwattr_changed = 1; - if (new_dentry && d_really_is_positive(new_dentry)) { - new_nwattr = NCP_FINFO(d_inode(new_dentry))->nwattr; - info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); - res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); - if (!res2) - new_nwattr_changed = 1; - } - /* now try again the rename operation */ - /* but only if something really happened */ - if (new_nwattr_changed || old_nwattr_changed) { - res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), - old_dir, _old_name, - new_dir, _new_name); - } - if (res) - goto leave_me; - /* file was successfully renamed, so: - do not set attributes on old file - it no longer exists - copy attributes from old file to new */ - new_nwattr_changed = old_nwattr_changed; - new_nwattr = old_nwattr; - old_nwattr_changed = 0; - -leave_me:; - if (old_nwattr_changed) { - info.attributes = old_nwattr; - res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); - /* ignore errors */ - } - if (new_nwattr_changed) { - info.attributes = new_nwattr; - res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); - /* ignore errors */ - } - return(res); -} -#endif /* CONFIG_NCPFS_STRONG */ - - -static int -ncp_lookup_validate(struct dentry *dentry, unsigned int flags) -{ - struct ncp_server *server; - struct dentry *parent; - struct inode *dir; - struct ncp_entry_info finfo; - int res, val = 0, len; - __u8 __name[NCP_MAXPATHLEN + 1]; - - if (dentry == dentry->d_sb->s_root) - return 1; - - if (flags & LOOKUP_RCU) - return -ECHILD; - - parent = dget_parent(dentry); - dir = d_inode(parent); - - if (d_really_is_negative(dentry)) - goto finished; - - server = NCP_SERVER(dir); - - /* - * Inspired by smbfs: - * The default validation is based on dentry age: - * We set the max age at mount time. (But each - * successful server lookup renews the timestamp.) - */ - val = NCP_TEST_AGE(server, dentry); - if (val) - goto finished; - - ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n", - dentry, NCP_GET_AGE(dentry)); - - len = sizeof(__name); - if (ncp_is_server_root(dir)) { - res = ncp_io2vol(server, __name, &len, dentry->d_name.name, - dentry->d_name.len, 1); - if (!res) { - res = ncp_lookup_volume(server, __name, &(finfo.i)); - if (!res) - ncp_update_known_namespace(server, finfo.i.volNumber, NULL); - } - } else { - res = ncp_io2vol(server, __name, &len, dentry->d_name.name, - dentry->d_name.len, !ncp_preserve_case(dir)); - if (!res) - res = ncp_obtain_info(server, dir, __name, &(finfo.i)); - } - finfo.volume = finfo.i.volNumber; - ncp_dbg(2, "looked for %pd/%s, res=%d\n", - dentry->d_parent, __name, res); - /* - * If we didn't find it, or if it has a different dirEntNum to - * what we remember, it's not valid any more. - */ - if (!res) { - struct inode *inode = d_inode(dentry); - - inode_lock(inode); - if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) { - ncp_new_dentry(dentry); - val=1; - } else - ncp_dbg(2, "found, but dirEntNum changed\n"); - - ncp_update_inode2(inode, &finfo); - inode_unlock(inode); - } - -finished: - ncp_dbg(2, "result=%d\n", val); - dput(parent); - return val; -} - -static time_t ncp_obtain_mtime(struct dentry *dentry) -{ - struct inode *inode = d_inode(dentry); - struct ncp_server *server = NCP_SERVER(inode); - struct nw_info_struct i; - - if (!ncp_conn_valid(server) || ncp_is_server_root(inode)) - return 0; - - if (ncp_obtain_info(server, inode, NULL, &i)) - return 0; - - return ncp_date_dos2unix(i.modifyTime, i.modifyDate); -} - -static inline void -ncp_invalidate_dircache_entries(struct dentry *parent) -{ - struct ncp_server *server = NCP_SERVER(d_inode(parent)); - struct dentry *dentry; - - spin_lock(&parent->d_lock); - list_for_each_entry(dentry, &parent->d_subdirs, d_child) { - dentry->d_fsdata = NULL; - ncp_age_dentry(server, dentry); - } - spin_unlock(&parent->d_lock); -} - -static int ncp_readdir(struct file *file, struct dir_context *ctx) -{ - struct dentry *dentry = file->f_path.dentry; - struct inode *inode = d_inode(dentry); - struct page *page = NULL; - struct ncp_server *server = NCP_SERVER(inode); - union ncp_dir_cache *cache = NULL; - struct ncp_cache_control ctl; - int result, mtime_valid = 0; - time_t mtime = 0; - - ctl.page = NULL; - ctl.cache = NULL; - - ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos); - - result = -EIO; - /* Do not generate '.' and '..' when server is dead. */ - if (!ncp_conn_valid(server)) - goto out; - - result = 0; - if (!dir_emit_dots(file, ctx)) - goto out; - - page = grab_cache_page(&inode->i_data, 0); - if (!page) - goto read_really; - - ctl.cache = cache = kmap(page); - ctl.head = cache->head; - - if (!PageUptodate(page) || !ctl.head.eof) - goto init_cache; - - if (ctx->pos == 2) { - if (jiffies - ctl.head.time >= NCP_MAX_AGE(server)) - goto init_cache; - - mtime = ncp_obtain_mtime(dentry); - mtime_valid = 1; - if ((!mtime) || (mtime != ctl.head.mtime)) - goto init_cache; - } - - if (ctx->pos > ctl.head.end) - goto finished; - - ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2); - ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE; - ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE; - - for (;;) { - if (ctl.ofs != 0) { - ctl.page = find_lock_page(&inode->i_data, ctl.ofs); - if (!ctl.page) - goto invalid_cache; - ctl.cache = kmap(ctl.page); - if (!PageUptodate(ctl.page)) - goto invalid_cache; - } - while (ctl.idx < NCP_DIRCACHE_SIZE) { - struct dentry *dent; - bool over; - - spin_lock(&dentry->d_lock); - if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) { - spin_unlock(&dentry->d_lock); - goto invalid_cache; - } - dent = ctl.cache->dentry[ctl.idx]; - if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) { - spin_unlock(&dentry->d_lock); - goto invalid_cache; - } - spin_unlock(&dentry->d_lock); - if (d_really_is_negative(dent)) { - dput(dent); - goto invalid_cache; - } - over = !dir_emit(ctx, dent->d_name.name, - dent->d_name.len, - d_inode(dent)->i_ino, DT_UNKNOWN); - dput(dent); - if (over) - goto finished; - ctx->pos += 1; - ctl.idx += 1; - if (ctx->pos > ctl.head.end) - goto finished; - } - if (ctl.page) { - kunmap(ctl.page); - SetPageUptodate(ctl.page); - unlock_page(ctl.page); - put_page(ctl.page); - ctl.page = NULL; - } - ctl.idx = 0; - ctl.ofs += 1; - } -invalid_cache: - if (ctl.page) { - kunmap(ctl.page); - unlock_page(ctl.page); - put_page(ctl.page); - ctl.page = NULL; - } - ctl.cache = cache; -init_cache: - ncp_invalidate_dircache_entries(dentry); - if (!mtime_valid) { - mtime = ncp_obtain_mtime(dentry); - mtime_valid = 1; - } - ctl.head.mtime = mtime; - ctl.head.time = jiffies; - ctl.head.eof = 0; - ctl.fpos = 2; - ctl.ofs = 0; - ctl.idx = NCP_DIRCACHE_START; - ctl.filled = 0; - ctl.valid = 1; -read_really: - spin_lock(&dentry->d_lock); - NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE; - spin_unlock(&dentry->d_lock); - if (ncp_is_server_root(inode)) { - ncp_read_volume_list(file, ctx, &ctl); - } else { - ncp_do_readdir(file, ctx, &ctl); - } - ctl.head.end = ctl.fpos - 1; - ctl.head.eof = ctl.valid; -finished: - if (ctl.page) { - kunmap(ctl.page); - SetPageUptodate(ctl.page); - unlock_page(ctl.page); - put_page(ctl.page); - } - if (page) { - cache->head = ctl.head; - kunmap(page); - SetPageUptodate(page); - unlock_page(page); - put_page(page); - } -out: - return result; -} - -static void ncp_d_prune(struct dentry *dentry) -{ - if (!dentry->d_fsdata) /* not referenced from page cache */ - return; - NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE; -} - -static int -ncp_fill_cache(struct file *file, struct dir_context *ctx, - struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, - int inval_childs) -{ - struct dentry *newdent, *dentry = file->f_path.dentry; - struct inode *dir = d_inode(dentry); - struct ncp_cache_control ctl = *ctrl; - struct qstr qname; - int valid = 0; - int hashed = 0; - ino_t ino = 0; - __u8 __name[NCP_MAXPATHLEN + 1]; - - qname.len = sizeof(__name); - if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len, - entry->i.entryName, entry->i.nameLen, - !ncp_preserve_entry_case(dir, entry->i.NSCreator))) - return 1; /* I'm not sure */ - - qname.name = __name; - - newdent = d_hash_and_lookup(dentry, &qname); - if (IS_ERR(newdent)) - goto end_advance; - if (!newdent) { - newdent = d_alloc(dentry, &qname); - if (!newdent) - goto end_advance; - } else { - hashed = 1; - - /* If case sensitivity changed for this volume, all entries below this one - should be thrown away. This entry itself is not affected, as its case - sensitivity is controlled by its own parent. */ - if (inval_childs) - shrink_dcache_parent(newdent); - - /* - * NetWare's OS2 namespace is case preserving yet case - * insensitive. So we update dentry's name as received from - * server. Parent dir's i_mutex is locked because we're in - * readdir. - */ - dentry_update_name_case(newdent, &qname); - } - - if (d_really_is_negative(newdent)) { - struct inode *inode; - - entry->opened = 0; - entry->ino = iunique(dir->i_sb, 2); - inode = ncp_iget(dir->i_sb, entry); - if (inode) { - d_instantiate(newdent, inode); - if (!hashed) - d_rehash(newdent); - } else { - spin_lock(&dentry->d_lock); - NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE; - spin_unlock(&dentry->d_lock); - } - } else { - struct inode *inode = d_inode(newdent); - - inode_lock_nested(inode, I_MUTEX_CHILD); - ncp_update_inode2(inode, entry); - inode_unlock(inode); - } - - if (ctl.idx >= NCP_DIRCACHE_SIZE) { - if (ctl.page) { - kunmap(ctl.page); - SetPageUptodate(ctl.page); - unlock_page(ctl.page); - put_page(ctl.page); - } - ctl.cache = NULL; - ctl.idx -= NCP_DIRCACHE_SIZE; - ctl.ofs += 1; - ctl.page = grab_cache_page(&dir->i_data, ctl.ofs); - if (ctl.page) - ctl.cache = kmap(ctl.page); - } - if (ctl.cache) { - if (d_really_is_positive(newdent)) { - newdent->d_fsdata = newdent; - ctl.cache->dentry[ctl.idx] = newdent; - ino = d_inode(newdent)->i_ino; - ncp_new_dentry(newdent); - } - valid = 1; - } - dput(newdent); -end_advance: - if (!valid) - ctl.valid = 0; - if (!ctl.filled && (ctl.fpos == ctx->pos)) { - if (!ino) - ino = iunique(dir->i_sb, 2); - ctl.filled = !dir_emit(ctx, qname.name, qname.len, - ino, DT_UNKNOWN); - if (!ctl.filled) - ctx->pos += 1; - } - ctl.fpos += 1; - ctl.idx += 1; - *ctrl = ctl; - return (ctl.valid || !ctl.filled); -} - -static void -ncp_read_volume_list(struct file *file, struct dir_context *ctx, - struct ncp_cache_control *ctl) -{ - struct inode *inode = file_inode(file); - struct ncp_server *server = NCP_SERVER(inode); - struct ncp_volume_info info; - struct ncp_entry_info entry; - int i; - - ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos); - - for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { - int inval_dentry; - - if (ncp_get_volume_info_with_number(server, i, &info) != 0) - return; - if (!strlen(info.volume_name)) - continue; - - ncp_dbg(1, "found vol: %s\n", info.volume_name); - - if (ncp_lookup_volume(server, info.volume_name, - &entry.i)) { - ncp_dbg(1, "could not lookup vol %s\n", - info.volume_name); - continue; - } - inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL); - entry.volume = entry.i.volNumber; - if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry)) - return; - } -} - -static void -ncp_do_readdir(struct file *file, struct dir_context *ctx, - struct ncp_cache_control *ctl) -{ - struct inode *dir = file_inode(file); - struct ncp_server *server = NCP_SERVER(dir); - struct nw_search_sequence seq; - struct ncp_entry_info entry; - int err; - void* buf; - int more; - size_t bufsize; - - ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos); - ncp_vdbg("init %pD, volnum=%d, dirent=%u\n", - file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum); - - err = ncp_initialize_search(server, dir, &seq); - if (err) { - ncp_dbg(1, "init failed, err=%d\n", err); - return; - } - /* We MUST NOT use server->buffer_size handshaked with server if we are - using UDP, as for UDP server uses max. buffer size determined by - MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). - So we use 128KB, just to be sure, as there is no way how to know - this value in advance. */ - bufsize = 131072; - buf = vmalloc(bufsize); - if (!buf) - return; - do { - int cnt; - char* rpl; - size_t rpls; - - err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls); - if (err) /* Error */ - break; - if (!cnt) /* prevent endless loop */ - break; - while (cnt--) { - size_t onerpl; - - if (rpls < offsetof(struct nw_info_struct, entryName)) - break; /* short packet */ - ncp_extract_file_info(rpl, &entry.i); - onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen; - if (rpls < onerpl) - break; /* short packet */ - (void)ncp_obtain_nfs_info(server, &entry.i); - rpl += onerpl; - rpls -= onerpl; - entry.volume = entry.i.volNumber; - if (!ncp_fill_cache(file, ctx, ctl, &entry, 0)) - break; - } - } while (more); - vfree(buf); - return; -} - -int ncp_conn_logged_in(struct super_block *sb) -{ - struct ncp_server* server = NCP_SBP(sb); - int result; - - if (ncp_single_volume(server)) { - int len; - struct dentry* dent; - __u32 volNumber; - __le32 dirEntNum; - __le32 DosDirNum; - __u8 __name[NCP_MAXPATHLEN + 1]; - - len = sizeof(__name); - result = ncp_io2vol(server, __name, &len, server->m.mounted_vol, - strlen(server->m.mounted_vol), 1); - if (result) - goto out; - result = -ENOENT; - if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) { - ncp_vdbg("%s not found\n", server->m.mounted_vol); - goto out; - } - dent = sb->s_root; - if (dent) { - struct inode* ino = d_inode(dent); - if (ino) { - ncp_update_known_namespace(server, volNumber, NULL); - NCP_FINFO(ino)->volNumber = volNumber; - NCP_FINFO(ino)->dirEntNum = dirEntNum; - NCP_FINFO(ino)->DosDirNum = DosDirNum; - result = 0; - } else { - ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n"); - } - } else { - ncp_dbg(1, "sb->s_root == NULL!\n"); - } - } else - result = 0; - -out: - return result; -} - -static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) -{ - struct ncp_server *server = NCP_SERVER(dir); - struct inode *inode = NULL; - struct ncp_entry_info finfo; - int error, res, len; - __u8 __name[NCP_MAXPATHLEN + 1]; - - error = -EIO; - if (!ncp_conn_valid(server)) - goto finished; - - ncp_vdbg("server lookup for %pd2\n", dentry); - - len = sizeof(__name); - if (ncp_is_server_root(dir)) { - res = ncp_io2vol(server, __name, &len, dentry->d_name.name, - dentry->d_name.len, 1); - if (!res) - res = ncp_lookup_volume(server, __name, &(finfo.i)); - if (!res) - ncp_update_known_namespace(server, finfo.i.volNumber, NULL); - } else { - res = ncp_io2vol(server, __name, &len, dentry->d_name.name, - dentry->d_name.len, !ncp_preserve_case(dir)); - if (!res) - res = ncp_obtain_info(server, dir, __name, &(finfo.i)); - } - ncp_vdbg("looked for %pd2, res=%d\n", dentry, res); - /* - * If we didn't find an entry, make a negative dentry. - */ - if (res) - goto add_entry; - - /* - * Create an inode for the entry. - */ - finfo.opened = 0; - finfo.ino = iunique(dir->i_sb, 2); - finfo.volume = finfo.i.volNumber; - error = -EACCES; - inode = ncp_iget(dir->i_sb, &finfo); - - if (inode) { - ncp_new_dentry(dentry); -add_entry: - d_add(dentry, inode); - error = 0; - } - -finished: - ncp_vdbg("result=%d\n", error); - return ERR_PTR(error); -} - -/* - * This code is common to create, mkdir, and mknod. - */ -static int ncp_instantiate(struct inode *dir, struct dentry *dentry, - struct ncp_entry_info *finfo) -{ - struct inode *inode; - int error = -EINVAL; - - finfo->ino = iunique(dir->i_sb, 2); - inode = ncp_iget(dir->i_sb, finfo); - if (!inode) - goto out_close; - d_instantiate(dentry,inode); - error = 0; -out: - return error; - -out_close: - ncp_vdbg("%pd2 failed, closing file\n", dentry); - ncp_close_file(NCP_SERVER(dir), finfo->file_handle); - goto out; -} - -int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t rdev, __le32 attributes) -{ - struct ncp_server *server = NCP_SERVER(dir); - struct ncp_entry_info finfo; - int error, result, len; - int opmode; - __u8 __name[NCP_MAXPATHLEN + 1]; - - ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode); - - ncp_age_dentry(server, dentry); - len = sizeof(__name); - error = ncp_io2vol(server, __name, &len, dentry->d_name.name, - dentry->d_name.len, !ncp_preserve_case(dir)); - if (error) - goto out; - - error = -EACCES; - - if (S_ISREG(mode) && - (server->m.flags & NCP_MOUNT_EXTRAS) && - (mode & S_IXUGO)) - attributes |= aSYSTEM | aSHARED; - - result = ncp_open_create_file_or_subdir(server, dir, __name, - OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, - attributes, AR_READ | AR_WRITE, &finfo); - opmode = O_RDWR; - if (result) { - result = ncp_open_create_file_or_subdir(server, dir, __name, - OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, - attributes, AR_WRITE, &finfo); - if (result) { - if (result == 0x87) - error = -ENAMETOOLONG; - else if (result < 0) - error = result; - ncp_dbg(1, "%pd2 failed\n", dentry); - goto out; - } - opmode = O_WRONLY; - } - finfo.access = opmode; - if (ncp_is_nfs_extras(server, finfo.volume)) { - finfo.i.nfs.mode = mode; - finfo.i.nfs.rdev = new_encode_dev(rdev); - if (ncp_modify_nfs_info(server, finfo.volume, - finfo.i.dirEntNum, - mode, new_encode_dev(rdev)) != 0) - goto out; - } - - error = ncp_instantiate(dir, dentry, &finfo); -out: - return error; -} - -static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode, - bool excl) -{ - return ncp_create_new(dir, dentry, mode, 0, 0); -} - -static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - struct ncp_entry_info finfo; - struct ncp_server *server = NCP_SERVER(dir); - int error, len; - __u8 __name[NCP_MAXPATHLEN + 1]; - - ncp_dbg(1, "making %pd2\n", dentry); - - ncp_age_dentry(server, dentry); - len = sizeof(__name); - error = ncp_io2vol(server, __name, &len, dentry->d_name.name, - dentry->d_name.len, !ncp_preserve_case(dir)); - if (error) - goto out; - - error = ncp_open_create_file_or_subdir(server, dir, __name, - OC_MODE_CREATE, aDIR, - cpu_to_le16(0xffff), - &finfo); - if (error == 0) { - if (ncp_is_nfs_extras(server, finfo.volume)) { - mode |= S_IFDIR; - finfo.i.nfs.mode = mode; - if (ncp_modify_nfs_info(server, - finfo.volume, - finfo.i.dirEntNum, - mode, 0) != 0) - goto out; - } - error = ncp_instantiate(dir, dentry, &finfo); - } else if (error > 0) { - error = -EACCES; - } -out: - return error; -} - -static int ncp_rmdir(struct inode *dir, struct dentry *dentry) -{ - struct ncp_server *server = NCP_SERVER(dir); - int error, result, len; - __u8 __name[NCP_MAXPATHLEN + 1]; - - ncp_dbg(1, "removing %pd2\n", dentry); - - len = sizeof(__name); - error = ncp_io2vol(server, __name, &len, dentry->d_name.name, - dentry->d_name.len, !ncp_preserve_case(dir)); - if (error) - goto out; - - result = ncp_del_file_or_subdir(server, dir, __name); - switch (result) { - case 0x00: - error = 0; - break; - case 0x85: /* unauthorized to delete file */ - case 0x8A: /* unauthorized to delete file */ - error = -EACCES; - break; - case 0x8F: - case 0x90: /* read only */ - error = -EPERM; - break; - case 0x9F: /* in use by another client */ - error = -EBUSY; - break; - case 0xA0: /* directory not empty */ - error = -ENOTEMPTY; - break; - case 0xFF: /* someone deleted file */ - error = -ENOENT; - break; - default: - error = result < 0 ? result : -EACCES; - break; - } -out: - return error; -} - -static int ncp_unlink(struct inode *dir, struct dentry *dentry) -{ - struct inode *inode = d_inode(dentry); - struct ncp_server *server; - int error; - - server = NCP_SERVER(dir); - ncp_dbg(1, "unlinking %pd2\n", dentry); - - /* - * Check whether to close the file ... - */ - if (inode) { - ncp_vdbg("closing file\n"); - ncp_make_closed(inode); - } - - error = ncp_del_file_or_subdir2(server, dentry); -#ifdef CONFIG_NCPFS_STRONG - /* 9C is Invalid path.. It should be 8F, 90 - read only, but - it is not :-( */ - if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */ - error = ncp_force_unlink(dir, dentry); - } -#endif - switch (error) { - case 0x00: - ncp_dbg(1, "removed %pd2\n", dentry); - break; - case 0x85: - case 0x8A: - error = -EACCES; - break; - case 0x8D: /* some files in use */ - case 0x8E: /* all files in use */ - error = -EBUSY; - break; - case 0x8F: /* some read only */ - case 0x90: /* all read only */ - case 0x9C: /* !!! returned when in-use or read-only by NW4 */ - error = -EPERM; - break; - case 0xFF: - error = -ENOENT; - break; - default: - error = error < 0 ? error : -EACCES; - break; - } - return error; -} - -static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry, - unsigned int flags) -{ - struct ncp_server *server = NCP_SERVER(old_dir); - int error; - int old_len, new_len; - __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1]; - - if (flags) - return -EINVAL; - - ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry); - - ncp_age_dentry(server, old_dentry); - ncp_age_dentry(server, new_dentry); - - old_len = sizeof(__old_name); - error = ncp_io2vol(server, __old_name, &old_len, - old_dentry->d_name.name, old_dentry->d_name.len, - !ncp_preserve_case(old_dir)); - if (error) - goto out; - - new_len = sizeof(__new_name); - error = ncp_io2vol(server, __new_name, &new_len, - new_dentry->d_name.name, new_dentry->d_name.len, - !ncp_preserve_case(new_dir)); - if (error) - goto out; - - error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name, - new_dir, __new_name); -#ifdef CONFIG_NCPFS_STRONG - if ((error == 0x90 || error == 0x8B || error == -EACCES) && - server->m.flags & NCP_MOUNT_STRONG) { /* RO */ - error = ncp_force_rename(old_dir, old_dentry, __old_name, - new_dir, new_dentry, __new_name); - } -#endif - switch (error) { - case 0x00: - ncp_dbg(1, "renamed %pd -> %pd\n", - old_dentry, new_dentry); - ncp_d_prune(old_dentry); - ncp_d_prune(new_dentry); - break; - case 0x9E: - error = -ENAMETOOLONG; - break; - case 0xFF: - error = -ENOENT; - break; - default: - error = error < 0 ? error : -EACCES; - break; - } -out: - return error; -} - -static int ncp_mknod(struct inode * dir, struct dentry *dentry, - umode_t mode, dev_t rdev) -{ - if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { - ncp_dbg(1, "mode = 0%ho\n", mode); - return ncp_create_new(dir, dentry, mode, rdev, 0); - } - return -EPERM; /* Strange, but true */ -} - -/* The following routines are taken directly from msdos-fs */ - -/* Linear day numbers of the respective 1sts in non-leap years. */ - -static int day_n[] = -{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0}; -/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ - -static int utc2local(int time) -{ - return time - sys_tz.tz_minuteswest * 60; -} - -static int local2utc(int time) -{ - return time + sys_tz.tz_minuteswest * 60; -} - -/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ -int -ncp_date_dos2unix(__le16 t, __le16 d) -{ - unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d); - int month, year, secs; - - /* first subtract and mask after that... Otherwise, if - date == 0, bad things happen */ - month = ((date >> 5) - 1) & 15; - year = date >> 9; - secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + - 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + - year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653); - /* days since 1.1.70 plus 80's leap day */ - return local2utc(secs); -} - - -/* Convert linear UNIX date to a MS-DOS time/date pair. */ -void -ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date) -{ - int day, year, nl_day, month; - - unix_date = utc2local(unix_date); - *time = cpu_to_le16( - (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) + - (((unix_date / 3600) % 24) << 11)); - day = unix_date / 86400 - 3652; - year = day / 365; - if ((year + 3) / 4 + 365 * year > day) - year--; - day -= (year + 3) / 4 + 365 * year; - if (day == 59 && !(year & 3)) { - nl_day = day; - month = 2; - } else { - nl_day = (year & 3) || day <= 59 ? day : day - 1; - for (month = 1; month < 12; month++) - if (day_n[month] > nl_day) - break; - } - *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9)); -} diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c deleted file mode 100644 index 8f8cc0334ddd..000000000000 --- a/fs/ncpfs/file.c +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * file.c - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ncp_fs.h" - -static int ncp_fsync(struct file *file, loff_t start, loff_t end, int datasync) -{ - return file_write_and_wait_range(file, start, end); -} - -/* - * Open a file with the specified read/write mode. - */ -int ncp_make_open(struct inode *inode, int right) -{ - int error; - int access; - - error = -EINVAL; - if (!inode) { - pr_err("%s: got NULL inode\n", __func__); - goto out; - } - - ncp_dbg(1, "opened=%d, volume # %u, dir entry # %u\n", - atomic_read(&NCP_FINFO(inode)->opened), - NCP_FINFO(inode)->volNumber, - NCP_FINFO(inode)->dirEntNum); - error = -EACCES; - mutex_lock(&NCP_FINFO(inode)->open_mutex); - if (!atomic_read(&NCP_FINFO(inode)->opened)) { - struct ncp_entry_info finfo; - int result; - - /* tries max. rights */ - finfo.access = O_RDWR; - result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), - inode, NULL, OC_MODE_OPEN, - 0, AR_READ | AR_WRITE, &finfo); - if (!result) - goto update; - /* RDWR did not succeeded, try readonly or writeonly as requested */ - switch (right) { - case O_RDONLY: - finfo.access = O_RDONLY; - result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), - inode, NULL, OC_MODE_OPEN, - 0, AR_READ, &finfo); - break; - case O_WRONLY: - finfo.access = O_WRONLY; - result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), - inode, NULL, OC_MODE_OPEN, - 0, AR_WRITE, &finfo); - break; - } - if (result) { - ncp_vdbg("failed, result=%d\n", result); - goto out_unlock; - } - /* - * Update the inode information. - */ - update: - ncp_update_inode(inode, &finfo); - atomic_set(&NCP_FINFO(inode)->opened, 1); - } - - access = NCP_FINFO(inode)->access; - ncp_vdbg("file open, access=%x\n", access); - if (access == right || access == O_RDWR) { - atomic_inc(&NCP_FINFO(inode)->opened); - error = 0; - } - -out_unlock: - mutex_unlock(&NCP_FINFO(inode)->open_mutex); -out: - return error; -} - -static ssize_t -ncp_file_read_iter(struct kiocb *iocb, struct iov_iter *to) -{ - struct file *file = iocb->ki_filp; - struct inode *inode = file_inode(file); - size_t already_read = 0; - off_t pos = iocb->ki_pos; - size_t bufsize; - int error; - void *freepage; - size_t freelen; - - ncp_dbg(1, "enter %pD2\n", file); - - if (!iov_iter_count(to)) - return 0; - if (pos > inode->i_sb->s_maxbytes) - return 0; - iov_iter_truncate(to, inode->i_sb->s_maxbytes - pos); - - error = ncp_make_open(inode, O_RDONLY); - if (error) { - ncp_dbg(1, "open failed, error=%d\n", error); - return error; - } - - bufsize = NCP_SERVER(inode)->buffer_size; - - error = -EIO; - freelen = ncp_read_bounce_size(bufsize); - freepage = vmalloc(freelen); - if (!freepage) - goto outrel; - error = 0; - /* First read in as much as possible for each bufsize. */ - while (iov_iter_count(to)) { - int read_this_time; - size_t to_read = min_t(size_t, - bufsize - (pos % bufsize), - iov_iter_count(to)); - - error = ncp_read_bounce(NCP_SERVER(inode), - NCP_FINFO(inode)->file_handle, - pos, to_read, to, &read_this_time, - freepage, freelen); - if (error) { - error = -EIO; /* NW errno -> Linux errno */ - break; - } - pos += read_this_time; - already_read += read_this_time; - - if (read_this_time != to_read) - break; - } - vfree(freepage); - - iocb->ki_pos = pos; - - file_accessed(file); - - ncp_dbg(1, "exit %pD2\n", file); -outrel: - ncp_inode_close(inode); - return already_read ? already_read : error; -} - -static ssize_t -ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from) -{ - struct file *file = iocb->ki_filp; - struct inode *inode = file_inode(file); - size_t already_written = 0; - size_t bufsize; - int errno; - void *bouncebuffer; - off_t pos; - - ncp_dbg(1, "enter %pD2\n", file); - errno = generic_write_checks(iocb, from); - if (errno <= 0) - return errno; - - errno = ncp_make_open(inode, O_WRONLY); - if (errno) { - ncp_dbg(1, "open failed, error=%d\n", errno); - return errno; - } - bufsize = NCP_SERVER(inode)->buffer_size; - - errno = file_update_time(file); - if (errno) - goto outrel; - - bouncebuffer = vmalloc(bufsize); - if (!bouncebuffer) { - errno = -EIO; /* -ENOMEM */ - goto outrel; - } - pos = iocb->ki_pos; - while (iov_iter_count(from)) { - int written_this_time; - size_t to_write = min_t(size_t, - bufsize - (pos % bufsize), - iov_iter_count(from)); - - if (!copy_from_iter_full(bouncebuffer, to_write, from)) { - errno = -EFAULT; - break; - } - if (ncp_write_kernel(NCP_SERVER(inode), - NCP_FINFO(inode)->file_handle, - pos, to_write, bouncebuffer, &written_this_time) != 0) { - errno = -EIO; - break; - } - pos += written_this_time; - already_written += written_this_time; - - if (written_this_time != to_write) - break; - } - vfree(bouncebuffer); - - iocb->ki_pos = pos; - - if (pos > i_size_read(inode)) { - inode_lock(inode); - if (pos > i_size_read(inode)) - i_size_write(inode, pos); - inode_unlock(inode); - } - ncp_dbg(1, "exit %pD2\n", file); -outrel: - ncp_inode_close(inode); - return already_written ? already_written : errno; -} - -static int ncp_release(struct inode *inode, struct file *file) { - if (ncp_make_closed(inode)) { - ncp_dbg(1, "failed to close\n"); - } - return 0; -} - -const struct file_operations ncp_file_operations = -{ - .llseek = generic_file_llseek, - .read_iter = ncp_file_read_iter, - .write_iter = ncp_file_write_iter, - .unlocked_ioctl = ncp_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ncp_compat_ioctl, -#endif - .mmap = ncp_mmap, - .release = ncp_release, - .fsync = ncp_fsync, -}; - -const struct inode_operations ncp_file_inode_operations = -{ - .setattr = ncp_notify_change, -}; diff --git a/fs/ncpfs/getopt.c b/fs/ncpfs/getopt.c deleted file mode 100644 index 5c941bef14c4..000000000000 --- a/fs/ncpfs/getopt.c +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * getopt.c - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include - -#include - -#include "getopt.h" - -/** - * ncp_getopt - option parser - * @caller: name of the caller, for error messages - * @options: the options string - * @opts: an array of &struct option entries controlling parser operations - * @optopt: output; will contain the current option - * @optarg: output; will contain the value (if one exists) - * @value: output; may be NULL; will be overwritten with the integer value - * of the current argument. - * - * Helper to parse options on the format used by mount ("a=b,c=d,e,f"). - * Returns opts->val if a matching entry in the 'opts' array is found, - * 0 when no more tokens are found, -1 if an error is encountered. - */ -int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, - char **optopt, char **optarg, unsigned long *value) -{ - char *token; - char *val; - - do { - if ((token = strsep(options, ",")) == NULL) - return 0; - } while (*token == '\0'); - if (optopt) - *optopt = token; - - if ((val = strchr (token, '=')) != NULL) { - *val++ = 0; - } - *optarg = val; - for (; opts->name; opts++) { - if (!strcmp(opts->name, token)) { - if (!val) { - if (opts->has_arg & OPT_NOPARAM) { - return opts->val; - } - pr_info("%s: the %s option requires an argument\n", - caller, token); - return -EINVAL; - } - if (opts->has_arg & OPT_INT) { - int rc = kstrtoul(val, 0, value); - - if (rc) { - pr_info("%s: invalid numeric value in %s=%s\n", - caller, token, val); - return rc; - } - return opts->val; - } - if (opts->has_arg & OPT_STRING) { - return opts->val; - } - pr_info("%s: unexpected argument %s to the %s option\n", - caller, val, token); - return -EINVAL; - } - } - pr_info("%s: Unrecognized mount option %s\n", caller, token); - return -EOPNOTSUPP; -} diff --git a/fs/ncpfs/getopt.h b/fs/ncpfs/getopt.h deleted file mode 100644 index 30f0da317670..000000000000 --- a/fs/ncpfs/getopt.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _LINUX_GETOPT_H -#define _LINUX_GETOPT_H - -#define OPT_NOPARAM 1 -#define OPT_INT 2 -#define OPT_STRING 4 -struct ncp_option { - const char *name; - unsigned int has_arg; - int val; -}; - -extern int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, - char **optopt, char **optarg, unsigned long *value); - -#endif /* _LINUX_GETOPT_H */ diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c deleted file mode 100644 index 129f1937fa2c..000000000000 --- a/fs/ncpfs/inode.c +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * inode.c - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * Modified for big endian by J.F. Chadima and David S. Miller - * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache - * Modified 1998 Wolfram Pienkoss for NLS - * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ncp_fs.h" -#include "getopt.h" - -#define NCP_DEFAULT_FILE_MODE 0600 -#define NCP_DEFAULT_DIR_MODE 0700 -#define NCP_DEFAULT_TIME_OUT 10 -#define NCP_DEFAULT_RETRY_COUNT 20 - -static void ncp_evict_inode(struct inode *); -static void ncp_put_super(struct super_block *); -static int ncp_statfs(struct dentry *, struct kstatfs *); -static int ncp_show_options(struct seq_file *, struct dentry *); - -static struct kmem_cache * ncp_inode_cachep; - -static struct inode *ncp_alloc_inode(struct super_block *sb) -{ - struct ncp_inode_info *ei; - ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL); - if (!ei) - return NULL; - return &ei->vfs_inode; -} - -static void ncp_i_callback(struct rcu_head *head) -{ - struct inode *inode = container_of(head, struct inode, i_rcu); - kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); -} - -static void ncp_destroy_inode(struct inode *inode) -{ - call_rcu(&inode->i_rcu, ncp_i_callback); -} - -static void init_once(void *foo) -{ - struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; - - mutex_init(&ei->open_mutex); - inode_init_once(&ei->vfs_inode); -} - -static int init_inodecache(void) -{ - ncp_inode_cachep = kmem_cache_create("ncp_inode_cache", - sizeof(struct ncp_inode_info), - 0, (SLAB_RECLAIM_ACCOUNT| - SLAB_MEM_SPREAD|SLAB_ACCOUNT), - init_once); - if (ncp_inode_cachep == NULL) - return -ENOMEM; - return 0; -} - -static void destroy_inodecache(void) -{ - /* - * Make sure all delayed rcu free inodes are flushed before we - * destroy cache. - */ - rcu_barrier(); - kmem_cache_destroy(ncp_inode_cachep); -} - -static int ncp_remount(struct super_block *sb, int *flags, char* data) -{ - sync_filesystem(sb); - *flags |= MS_NODIRATIME; - return 0; -} - -static const struct super_operations ncp_sops = -{ - .alloc_inode = ncp_alloc_inode, - .destroy_inode = ncp_destroy_inode, - .drop_inode = generic_delete_inode, - .evict_inode = ncp_evict_inode, - .put_super = ncp_put_super, - .statfs = ncp_statfs, - .remount_fs = ncp_remount, - .show_options = ncp_show_options, -}; - -/* - * Fill in the ncpfs-specific information in the inode. - */ -static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo) -{ - NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum; - NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum; - NCP_FINFO(inode)->volNumber = nwinfo->volume; -} - -void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo) -{ - ncp_update_dirent(inode, nwinfo); - NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; - NCP_FINFO(inode)->access = nwinfo->access; - memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, - sizeof(nwinfo->file_handle)); - ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n", - nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, - NCP_FINFO(inode)->dirEntNum); -} - -static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) -{ - /* NFS namespace mode overrides others if it's set. */ - ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode); - if (nwi->nfs.mode) { - /* XXX Security? */ - inode->i_mode = nwi->nfs.mode; - } - - inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; - - inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); - inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); - inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate); - inode->i_atime.tv_nsec = 0; - inode->i_mtime.tv_nsec = 0; - inode->i_ctime.tv_nsec = 0; -} - -static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo) -{ - struct nw_info_struct *nwi = &nwinfo->i; - struct ncp_server *server = NCP_SERVER(inode); - - if (nwi->attributes & aDIR) { - inode->i_mode = server->m.dir_mode; - /* for directories dataStreamSize seems to be some - Object ID ??? */ - i_size_write(inode, NCP_BLOCK_SIZE); - } else { - u32 size; - - inode->i_mode = server->m.file_mode; - size = le32_to_cpu(nwi->dataStreamSize); - i_size_write(inode, size); -#ifdef CONFIG_NCPFS_EXTRAS - if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) - && (nwi->attributes & aSHARED)) { - switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { - case aHIDDEN: - if (server->m.flags & NCP_MOUNT_SYMLINKS) { - if (/* (size >= NCP_MIN_SYMLINK_SIZE) - && */ (size <= NCP_MAX_SYMLINK_SIZE)) { - inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; - NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; - break; - } - } - /* FALLTHROUGH */ - case 0: - if (server->m.flags & NCP_MOUNT_EXTRAS) - inode->i_mode |= S_IRUGO; - break; - case aSYSTEM: - if (server->m.flags & NCP_MOUNT_EXTRAS) - inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO; - break; - /* case aSYSTEM|aHIDDEN: */ - default: - /* reserved combination */ - break; - } - } -#endif - } - if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO; -} - -void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo) -{ - NCP_FINFO(inode)->flags = 0; - if (!atomic_read(&NCP_FINFO(inode)->opened)) { - NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; - ncp_update_attrs(inode, nwinfo); - } - - ncp_update_dates(inode, &nwinfo->i); - ncp_update_dirent(inode, nwinfo); -} - -/* - * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes. - */ -static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) -{ - struct ncp_server *server = NCP_SERVER(inode); - - NCP_FINFO(inode)->flags = 0; - - ncp_update_attrs(inode, nwinfo); - - ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode); - - set_nlink(inode, 1); - inode->i_uid = server->m.uid; - inode->i_gid = server->m.gid; - - ncp_update_dates(inode, &nwinfo->i); - ncp_update_inode(inode, nwinfo); -} - -#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) -static const struct inode_operations ncp_symlink_inode_operations = { - .get_link = page_get_link, - .setattr = ncp_notify_change, -}; -#endif - -/* - * Get a new inode. - */ -struct inode * -ncp_iget(struct super_block *sb, struct ncp_entry_info *info) -{ - struct inode *inode; - - if (info == NULL) { - pr_err("%s: info is NULL\n", __func__); - return NULL; - } - - inode = new_inode(sb); - if (inode) { - atomic_set(&NCP_FINFO(inode)->opened, info->opened); - - inode->i_ino = info->ino; - ncp_set_attr(inode, info); - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ncp_file_inode_operations; - inode->i_fop = &ncp_file_operations; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &ncp_dir_inode_operations; - inode->i_fop = &ncp_dir_operations; -#ifdef CONFIG_NCPFS_NFS_NS - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - init_special_inode(inode, inode->i_mode, - new_decode_dev(info->i.nfs.rdev)); -#endif -#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) - } else if (S_ISLNK(inode->i_mode)) { - inode->i_op = &ncp_symlink_inode_operations; - inode_nohighmem(inode); - inode->i_data.a_ops = &ncp_symlink_aops; -#endif - } else { - make_bad_inode(inode); - } - insert_inode_hash(inode); - } else - pr_err("%s: iget failed!\n", __func__); - return inode; -} - -static void -ncp_evict_inode(struct inode *inode) -{ - truncate_inode_pages_final(&inode->i_data); - clear_inode(inode); - - if (S_ISDIR(inode->i_mode)) { - ncp_dbg(2, "put directory %ld\n", inode->i_ino); - } - - if (ncp_make_closed(inode) != 0) { - /* We can't do anything but complain. */ - pr_err("%s: could not close\n", __func__); - } -} - -static void ncp_stop_tasks(struct ncp_server *server) { - struct sock* sk = server->ncp_sock->sk; - - lock_sock(sk); - sk->sk_error_report = server->error_report; - sk->sk_data_ready = server->data_ready; - sk->sk_write_space = server->write_space; - release_sock(sk); - del_timer_sync(&server->timeout_tm); - - flush_work(&server->rcv.tq); - if (sk->sk_socket->type == SOCK_STREAM) - flush_work(&server->tx.tq); - else - flush_work(&server->timeout_tq); -} - -static int ncp_show_options(struct seq_file *seq, struct dentry *root) -{ - struct ncp_server *server = NCP_SBP(root->d_sb); - unsigned int tmp; - - if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID)) - seq_printf(seq, ",uid=%u", - from_kuid_munged(&init_user_ns, server->m.uid)); - if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID)) - seq_printf(seq, ",gid=%u", - from_kgid_munged(&init_user_ns, server->m.gid)); - if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID)) - seq_printf(seq, ",owner=%u", - from_kuid_munged(&init_user_ns, server->m.mounted_uid)); - tmp = server->m.file_mode & S_IALLUGO; - if (tmp != NCP_DEFAULT_FILE_MODE) - seq_printf(seq, ",mode=0%o", tmp); - tmp = server->m.dir_mode & S_IALLUGO; - if (tmp != NCP_DEFAULT_DIR_MODE) - seq_printf(seq, ",dirmode=0%o", tmp); - if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) { - tmp = server->m.time_out * 100 / HZ; - seq_printf(seq, ",timeout=%u", tmp); - } - if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT) - seq_printf(seq, ",retry=%u", server->m.retry_count); - if (server->m.flags != 0) - seq_printf(seq, ",flags=%lu", server->m.flags); - if (server->m.wdog_pid != NULL) - seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid)); - - return 0; -} - -static const struct ncp_option ncp_opts[] = { - { "uid", OPT_INT, 'u' }, - { "gid", OPT_INT, 'g' }, - { "owner", OPT_INT, 'o' }, - { "mode", OPT_INT, 'm' }, - { "dirmode", OPT_INT, 'd' }, - { "timeout", OPT_INT, 't' }, - { "retry", OPT_INT, 'r' }, - { "flags", OPT_INT, 'f' }, - { "wdogpid", OPT_INT, 'w' }, - { "ncpfd", OPT_INT, 'n' }, - { "infofd", OPT_INT, 'i' }, /* v5 */ - { "version", OPT_INT, 'v' }, - { NULL, 0, 0 } }; - -static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) { - int optval; - char *optarg; - unsigned long optint; - int version = 0; - int ret; - - data->flags = 0; - data->int_flags = 0; - data->mounted_uid = GLOBAL_ROOT_UID; - data->wdog_pid = NULL; - data->ncp_fd = ~0; - data->time_out = NCP_DEFAULT_TIME_OUT; - data->retry_count = NCP_DEFAULT_RETRY_COUNT; - data->uid = GLOBAL_ROOT_UID; - data->gid = GLOBAL_ROOT_GID; - data->file_mode = NCP_DEFAULT_FILE_MODE; - data->dir_mode = NCP_DEFAULT_DIR_MODE; - data->info_fd = -1; - data->mounted_vol[0] = 0; - - while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) { - ret = optval; - if (ret < 0) - goto err; - switch (optval) { - case 'u': - data->uid = make_kuid(current_user_ns(), optint); - if (!uid_valid(data->uid)) { - ret = -EINVAL; - goto err; - } - break; - case 'g': - data->gid = make_kgid(current_user_ns(), optint); - if (!gid_valid(data->gid)) { - ret = -EINVAL; - goto err; - } - break; - case 'o': - data->mounted_uid = make_kuid(current_user_ns(), optint); - if (!uid_valid(data->mounted_uid)) { - ret = -EINVAL; - goto err; - } - break; - case 'm': - data->file_mode = optint; - break; - case 'd': - data->dir_mode = optint; - break; - case 't': - data->time_out = optint; - break; - case 'r': - data->retry_count = optint; - break; - case 'f': - data->flags = optint; - break; - case 'w': - data->wdog_pid = find_get_pid(optint); - break; - case 'n': - data->ncp_fd = optint; - break; - case 'i': - data->info_fd = optint; - break; - case 'v': - ret = -ECHRNG; - if (optint < NCP_MOUNT_VERSION_V4) - goto err; - if (optint > NCP_MOUNT_VERSION_V5) - goto err; - version = optint; - break; - - } - } - return 0; -err: - put_pid(data->wdog_pid); - data->wdog_pid = NULL; - return ret; -} - -static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) -{ - struct ncp_mount_data_kernel data; - struct ncp_server *server; - struct inode *root_inode; - struct socket *sock; - int error; - int default_bufsize; -#ifdef CONFIG_NCPFS_PACKET_SIGNING - int options; -#endif - struct ncp_entry_info finfo; - - memset(&data, 0, sizeof(data)); - server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); - if (!server) - return -ENOMEM; - sb->s_fs_info = server; - - error = -EFAULT; - if (raw_data == NULL) - goto out; - switch (*(int*)raw_data) { - case NCP_MOUNT_VERSION: - { - struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; - - data.flags = md->flags; - data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; - data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); - data.wdog_pid = find_get_pid(md->wdog_pid); - data.ncp_fd = md->ncp_fd; - data.time_out = md->time_out; - data.retry_count = md->retry_count; - data.uid = make_kuid(current_user_ns(), md->uid); - data.gid = make_kgid(current_user_ns(), md->gid); - data.file_mode = md->file_mode; - data.dir_mode = md->dir_mode; - data.info_fd = -1; - memcpy(data.mounted_vol, md->mounted_vol, - NCP_VOLNAME_LEN+1); - } - break; - case NCP_MOUNT_VERSION_V4: - { - struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; - - data.flags = md->flags; - data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); - data.wdog_pid = find_get_pid(md->wdog_pid); - data.ncp_fd = md->ncp_fd; - data.time_out = md->time_out; - data.retry_count = md->retry_count; - data.uid = make_kuid(current_user_ns(), md->uid); - data.gid = make_kgid(current_user_ns(), md->gid); - data.file_mode = md->file_mode; - data.dir_mode = md->dir_mode; - data.info_fd = -1; - } - break; - default: - error = -ECHRNG; - if (memcmp(raw_data, "vers", 4) == 0) { - error = ncp_parse_options(&data, raw_data); - } - if (error) - goto out; - break; - } - error = -EINVAL; - if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) || - !gid_valid(data.gid)) - goto out; - sock = sockfd_lookup(data.ncp_fd, &error); - if (!sock) - goto out; - - if (sock->type == SOCK_STREAM) - default_bufsize = 0xF000; - else - default_bufsize = 1024; - - sb->s_flags |= MS_NODIRATIME; /* probably even noatime */ - sb->s_maxbytes = 0xFFFFFFFFU; - sb->s_blocksize = 1024; /* Eh... Is this correct? */ - sb->s_blocksize_bits = 10; - sb->s_magic = NCP_SUPER_MAGIC; - sb->s_op = &ncp_sops; - sb->s_d_op = &ncp_dentry_operations; - - server = NCP_SBP(sb); - memset(server, 0, sizeof(*server)); - - error = super_setup_bdi(sb); - if (error) - goto out_fput; - - server->ncp_sock = sock; - - if (data.info_fd != -1) { - struct socket *info_sock = sockfd_lookup(data.info_fd, &error); - if (!info_sock) - goto out_fput; - server->info_sock = info_sock; - error = -EBADFD; - if (info_sock->type != SOCK_STREAM) - goto out_fput2; - } - -/* server->lock = 0; */ - mutex_init(&server->mutex); - server->packet = NULL; -/* server->buffer_size = 0; */ -/* server->conn_status = 0; */ -/* server->root_dentry = NULL; */ -/* server->root_setuped = 0; */ - mutex_init(&server->root_setup_lock); -#ifdef CONFIG_NCPFS_PACKET_SIGNING -/* server->sign_wanted = 0; */ -/* server->sign_active = 0; */ -#endif - init_rwsem(&server->auth_rwsem); - server->auth.auth_type = NCP_AUTH_NONE; -/* server->auth.object_name_len = 0; */ -/* server->auth.object_name = NULL; */ -/* server->auth.object_type = 0; */ -/* server->priv.len = 0; */ -/* server->priv.data = NULL; */ - - server->m = data; - /* Although anything producing this is buggy, it happens - now because of PATH_MAX changes.. */ - if (server->m.time_out < 1) { - server->m.time_out = 10; - pr_info("You need to recompile your ncpfs utils..\n"); - } - server->m.time_out = server->m.time_out * HZ / 100; - server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; - server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR; - -#ifdef CONFIG_NCPFS_NLS - /* load the default NLS charsets */ - server->nls_vol = load_nls_default(); - server->nls_io = load_nls_default(); -#endif /* CONFIG_NCPFS_NLS */ - - atomic_set(&server->dentry_ttl, 0); /* no caching */ - - INIT_LIST_HEAD(&server->tx.requests); - mutex_init(&server->rcv.creq_mutex); - server->tx.creq = NULL; - server->rcv.creq = NULL; - - timer_setup(&server->timeout_tm, ncpdgram_timeout_call, 0); -#undef NCP_PACKET_SIZE -#define NCP_PACKET_SIZE 131072 - error = -ENOMEM; - server->packet_size = NCP_PACKET_SIZE; - server->packet = vmalloc(NCP_PACKET_SIZE); - if (server->packet == NULL) - goto out_nls; - server->txbuf = vmalloc(NCP_PACKET_SIZE); - if (server->txbuf == NULL) - goto out_packet; - server->rxbuf = vmalloc(NCP_PACKET_SIZE); - if (server->rxbuf == NULL) - goto out_txbuf; - - lock_sock(sock->sk); - server->data_ready = sock->sk->sk_data_ready; - server->write_space = sock->sk->sk_write_space; - server->error_report = sock->sk->sk_error_report; - sock->sk->sk_user_data = server; - sock->sk->sk_data_ready = ncp_tcp_data_ready; - sock->sk->sk_error_report = ncp_tcp_error_report; - if (sock->type == SOCK_STREAM) { - server->rcv.ptr = (unsigned char*)&server->rcv.buf; - server->rcv.len = 10; - server->rcv.state = 0; - INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); - INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); - sock->sk->sk_write_space = ncp_tcp_write_space; - } else { - INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); - INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); - } - release_sock(sock->sk); - - ncp_lock_server(server); - error = ncp_connect(server); - ncp_unlock_server(server); - if (error < 0) - goto out_rxbuf; - ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb)); - - error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ -#ifdef CONFIG_NCPFS_PACKET_SIGNING - if (ncp_negotiate_size_and_options(server, default_bufsize, - NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) - { - if (options != NCP_DEFAULT_OPTIONS) - { - if (ncp_negotiate_size_and_options(server, - default_bufsize, - options & 2, - &(server->buffer_size), &options) != 0) - - { - goto out_disconnect; - } - } - ncp_lock_server(server); - if (options & 2) - server->sign_wanted = 1; - ncp_unlock_server(server); - } - else -#endif /* CONFIG_NCPFS_PACKET_SIGNING */ - if (ncp_negotiate_buffersize(server, default_bufsize, - &(server->buffer_size)) != 0) - goto out_disconnect; - ncp_dbg(1, "bufsize = %d\n", server->buffer_size); - - memset(&finfo, 0, sizeof(finfo)); - finfo.i.attributes = aDIR; - finfo.i.dataStreamSize = 0; /* ignored */ - finfo.i.dirEntNum = 0; - finfo.i.DosDirNum = 0; -#ifdef CONFIG_NCPFS_SMALLDOS - finfo.i.NSCreator = NW_NS_DOS; -#endif - finfo.volume = NCP_NUMBER_OF_VOLUMES; - /* set dates of mountpoint to Jan 1, 1986; 00:00 */ - finfo.i.creationTime = finfo.i.modifyTime - = cpu_to_le16(0x0000); - finfo.i.creationDate = finfo.i.modifyDate - = finfo.i.lastAccessDate - = cpu_to_le16(0x0C21); - finfo.i.nameLen = 0; - finfo.i.entryName[0] = '\0'; - - finfo.opened = 0; - finfo.ino = 2; /* tradition */ - - server->name_space[finfo.volume] = NW_NS_DOS; - - error = -ENOMEM; - root_inode = ncp_iget(sb, &finfo); - if (!root_inode) - goto out_disconnect; - ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber); - sb->s_root = d_make_root(root_inode); - if (!sb->s_root) - goto out_disconnect; - return 0; - -out_disconnect: - ncp_lock_server(server); - ncp_disconnect(server); - ncp_unlock_server(server); -out_rxbuf: - ncp_stop_tasks(server); - vfree(server->rxbuf); -out_txbuf: - vfree(server->txbuf); -out_packet: - vfree(server->packet); -out_nls: -#ifdef CONFIG_NCPFS_NLS - unload_nls(server->nls_io); - unload_nls(server->nls_vol); -#endif - mutex_destroy(&server->rcv.creq_mutex); - mutex_destroy(&server->root_setup_lock); - mutex_destroy(&server->mutex); -out_fput2: - if (server->info_sock) - sockfd_put(server->info_sock); -out_fput: - sockfd_put(sock); -out: - put_pid(data.wdog_pid); - sb->s_fs_info = NULL; - kfree(server); - return error; -} - -static void delayed_free(struct rcu_head *p) -{ - struct ncp_server *server = container_of(p, struct ncp_server, rcu); -#ifdef CONFIG_NCPFS_NLS - /* unload the NLS charsets */ - unload_nls(server->nls_vol); - unload_nls(server->nls_io); -#endif /* CONFIG_NCPFS_NLS */ - kfree(server); -} - -static void ncp_put_super(struct super_block *sb) -{ - struct ncp_server *server = NCP_SBP(sb); - - ncp_lock_server(server); - ncp_disconnect(server); - ncp_unlock_server(server); - - ncp_stop_tasks(server); - - mutex_destroy(&server->rcv.creq_mutex); - mutex_destroy(&server->root_setup_lock); - mutex_destroy(&server->mutex); - - if (server->info_sock) - sockfd_put(server->info_sock); - sockfd_put(server->ncp_sock); - kill_pid(server->m.wdog_pid, SIGTERM, 1); - put_pid(server->m.wdog_pid); - - kfree(server->priv.data); - kfree(server->auth.object_name); - vfree(server->rxbuf); - vfree(server->txbuf); - vfree(server->packet); - call_rcu(&server->rcu, delayed_free); -} - -static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct dentry* d; - struct inode* i; - struct ncp_inode_info* ni; - struct ncp_server* s; - struct ncp_volume_info vi; - struct super_block *sb = dentry->d_sb; - int err; - __u8 dh; - - d = sb->s_root; - if (!d) { - goto dflt; - } - i = d_inode(d); - if (!i) { - goto dflt; - } - ni = NCP_FINFO(i); - if (!ni) { - goto dflt; - } - s = NCP_SBP(sb); - if (!s) { - goto dflt; - } - if (!s->m.mounted_vol[0]) { - goto dflt; - } - - err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh); - if (err) { - goto dflt; - } - err = ncp_get_directory_info(s, dh, &vi); - ncp_dirhandle_free(s, dh); - if (err) { - goto dflt; - } - buf->f_type = NCP_SUPER_MAGIC; - buf->f_bsize = vi.sectors_per_block * 512; - buf->f_blocks = vi.total_blocks; - buf->f_bfree = vi.free_blocks; - buf->f_bavail = vi.free_blocks; - buf->f_files = vi.total_dir_entries; - buf->f_ffree = vi.available_dir_entries; - buf->f_namelen = 12; - return 0; - - /* We cannot say how much disk space is left on a mounted - NetWare Server, because free space is distributed over - volumes, and the current user might have disk quotas. So - free space is not that simple to determine. Our decision - here is to err conservatively. */ - -dflt:; - buf->f_type = NCP_SUPER_MAGIC; - buf->f_bsize = NCP_BLOCK_SIZE; - buf->f_blocks = 0; - buf->f_bfree = 0; - buf->f_bavail = 0; - buf->f_namelen = 12; - return 0; -} - -int ncp_notify_change(struct dentry *dentry, struct iattr *attr) -{ - struct inode *inode = d_inode(dentry); - int result = 0; - __le32 info_mask; - struct nw_modify_dos_info info; - struct ncp_server *server; - - result = -EIO; - - server = NCP_SERVER(inode); - if (!server) /* How this could happen? */ - goto out; - - result = -EPERM; - if (IS_DEADDIR(d_inode(dentry))) - goto out; - - /* ageing the dentry to force validation */ - ncp_age_dentry(server, dentry); - - result = setattr_prepare(dentry, attr); - if (result < 0) - goto out; - - result = -EPERM; - if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid)) - goto out; - - if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid)) - goto out; - - if (((attr->ia_valid & ATTR_MODE) && - (attr->ia_mode & - ~(S_IFREG | S_IFDIR | S_IRWXUGO)))) - goto out; - - info_mask = 0; - memset(&info, 0, sizeof(info)); - -#if 1 - if ((attr->ia_valid & ATTR_MODE) != 0) - { - umode_t newmode = attr->ia_mode; - - info_mask |= DM_ATTRIBUTES; - - if (S_ISDIR(inode->i_mode)) { - newmode &= server->m.dir_mode; - } else { -#ifdef CONFIG_NCPFS_EXTRAS - if (server->m.flags & NCP_MOUNT_EXTRAS) { - /* any non-default execute bit set */ - if (newmode & ~server->m.file_mode & S_IXUGO) - info.attributes |= aSHARED | aSYSTEM; - /* read for group/world and not in default file_mode */ - else if (newmode & ~server->m.file_mode & S_IRUGO) - info.attributes |= aSHARED; - } else -#endif - newmode &= server->m.file_mode; - } - if (newmode & S_IWUGO) - info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); - else - info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); - -#ifdef CONFIG_NCPFS_NFS_NS - if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) { - result = ncp_modify_nfs_info(server, - NCP_FINFO(inode)->volNumber, - NCP_FINFO(inode)->dirEntNum, - attr->ia_mode, 0); - if (result != 0) - goto out; - info.attributes &= ~(aSHARED | aSYSTEM); - { - /* mark partial success */ - struct iattr tmpattr; - - tmpattr.ia_valid = ATTR_MODE; - tmpattr.ia_mode = attr->ia_mode; - - setattr_copy(inode, &tmpattr); - mark_inode_dirty(inode); - } - } -#endif - } -#endif - - /* Do SIZE before attributes, otherwise mtime together with size does not work... - */ - if ((attr->ia_valid & ATTR_SIZE) != 0) { - int written; - - ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size); - - if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { - result = -EACCES; - goto out; - } - ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, - attr->ia_size, 0, "", &written); - - /* According to ndir, the changes only take effect after - closing the file */ - ncp_inode_close(inode); - result = ncp_make_closed(inode); - if (result) - goto out; - - if (attr->ia_size != i_size_read(inode)) { - truncate_setsize(inode, attr->ia_size); - mark_inode_dirty(inode); - } - } - if ((attr->ia_valid & ATTR_CTIME) != 0) { - info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE); - ncp_date_unix2dos(attr->ia_ctime.tv_sec, - &info.creationTime, &info.creationDate); - } - if ((attr->ia_valid & ATTR_MTIME) != 0) { - info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); - ncp_date_unix2dos(attr->ia_mtime.tv_sec, - &info.modifyTime, &info.modifyDate); - } - if ((attr->ia_valid & ATTR_ATIME) != 0) { - __le16 dummy; - info_mask |= (DM_LAST_ACCESS_DATE); - ncp_date_unix2dos(attr->ia_atime.tv_sec, - &dummy, &info.lastAccessDate); - } - if (info_mask != 0) { - result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), - inode, info_mask, &info); - if (result != 0) { - if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { - /* NetWare seems not to allow this. I - do not know why. So, just tell the - user everything went fine. This is - a terrible hack, but I do not know - how to do this correctly. */ - result = 0; - } else - goto out; - } -#ifdef CONFIG_NCPFS_STRONG - if ((!result) && (info_mask & DM_ATTRIBUTES)) - NCP_FINFO(inode)->nwattr = info.attributes; -#endif - } - if (result) - goto out; - - setattr_copy(inode, attr); - mark_inode_dirty(inode); - -out: - if (result > 0) - result = -EACCES; - return result; -} - -static struct dentry *ncp_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - return mount_nodev(fs_type, flags, data, ncp_fill_super); -} - -static struct file_system_type ncp_fs_type = { - .owner = THIS_MODULE, - .name = "ncpfs", - .mount = ncp_mount, - .kill_sb = kill_anon_super, - .fs_flags = FS_BINARY_MOUNTDATA, -}; -MODULE_ALIAS_FS("ncpfs"); - -static int __init init_ncp_fs(void) -{ - int err; - ncp_dbg(1, "called\n"); - - err = init_inodecache(); - if (err) - goto out1; - err = register_filesystem(&ncp_fs_type); - if (err) - goto out; - return 0; -out: - destroy_inodecache(); -out1: - return err; -} - -static void __exit exit_ncp_fs(void) -{ - ncp_dbg(1, "called\n"); - unregister_filesystem(&ncp_fs_type); - destroy_inodecache(); -} - -module_init(init_ncp_fs) -module_exit(exit_ncp_fs) -MODULE_LICENSE("GPL"); diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c deleted file mode 100644 index d378b98cd7b6..000000000000 --- a/fs/ncpfs/ioctl.c +++ /dev/null @@ -1,923 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ioctl.c - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache - * Modified 1998, 1999 Wolfram Pienkoss for NLS - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ncp_fs.h" - -/* maximum limit for ncp_objectname_ioctl */ -#define NCP_OBJECT_NAME_MAX_LEN 4096 -/* maximum limit for ncp_privatedata_ioctl */ -#define NCP_PRIVATE_DATA_MAX_LEN 8192 -/* maximum negotiable packet size */ -#define NCP_PACKET_SIZE_INTERNAL 65536 - -static int -ncp_get_fs_info(struct ncp_server * server, struct inode *inode, - struct ncp_fs_info __user *arg) -{ - struct ncp_fs_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (info.version != NCP_GET_FS_INFO_VERSION) { - ncp_dbg(1, "info.version invalid: %d\n", info.version); - return -EINVAL; - } - /* TODO: info.addr = server->m.serv_addr; */ - SET_UID(info.mounted_uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid)); - info.connection = server->connection; - info.buffer_size = server->buffer_size; - info.volume_number = NCP_FINFO(inode)->volNumber; - info.directory_id = NCP_FINFO(inode)->DosDirNum; - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int -ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode, - struct ncp_fs_info_v2 __user * arg) -{ - struct ncp_fs_info_v2 info2; - - if (copy_from_user(&info2, arg, sizeof(info2))) - return -EFAULT; - - if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { - ncp_dbg(1, "info.version invalid: %d\n", info2.version); - return -EINVAL; - } - info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); - info2.connection = server->connection; - info2.buffer_size = server->buffer_size; - info2.volume_number = NCP_FINFO(inode)->volNumber; - info2.directory_id = NCP_FINFO(inode)->DosDirNum; - info2.dummy1 = info2.dummy2 = info2.dummy3 = 0; - - if (copy_to_user(arg, &info2, sizeof(info2))) - return -EFAULT; - return 0; -} - -#ifdef CONFIG_COMPAT -struct compat_ncp_objectname_ioctl -{ - s32 auth_type; - u32 object_name_len; - compat_caddr_t object_name; /* a userspace data, in most cases user name */ -}; - -struct compat_ncp_fs_info_v2 { - s32 version; - u32 mounted_uid; - u32 connection; - u32 buffer_size; - - u32 volume_number; - u32 directory_id; - - u32 dummy1; - u32 dummy2; - u32 dummy3; -}; - -struct compat_ncp_ioctl_request { - u32 function; - u32 size; - compat_caddr_t data; -}; - -struct compat_ncp_privatedata_ioctl -{ - u32 len; - compat_caddr_t data; /* ~1000 for NDS */ -}; - -#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct compat_ncp_fs_info_v2) -#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct compat_ncp_ioctl_request) -#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct compat_ncp_objectname_ioctl) -#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct compat_ncp_objectname_ioctl) -#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct compat_ncp_privatedata_ioctl) -#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl) - -static int -ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode, - struct compat_ncp_fs_info_v2 __user * arg) -{ - struct compat_ncp_fs_info_v2 info2; - - if (copy_from_user(&info2, arg, sizeof(info2))) - return -EFAULT; - - if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { - ncp_dbg(1, "info.version invalid: %d\n", info2.version); - return -EINVAL; - } - info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); - info2.connection = server->connection; - info2.buffer_size = server->buffer_size; - info2.volume_number = NCP_FINFO(inode)->volNumber; - info2.directory_id = NCP_FINFO(inode)->DosDirNum; - info2.dummy1 = info2.dummy2 = info2.dummy3 = 0; - - if (copy_to_user(arg, &info2, sizeof(info2))) - return -EFAULT; - return 0; -} -#endif - -#define NCP_IOC_GETMOUNTUID16 _IOW('n', 2, u16) -#define NCP_IOC_GETMOUNTUID32 _IOW('n', 2, u32) -#define NCP_IOC_GETMOUNTUID64 _IOW('n', 2, u64) - -#ifdef CONFIG_NCPFS_NLS -/* Here we are select the iocharset and the codepage for NLS. - * Thanks Petr Vandrovec for idea and many hints. - */ -static int -ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) -{ - struct ncp_nls_ioctl user; - struct nls_table *codepage; - struct nls_table *iocharset; - struct nls_table *oldset_io; - struct nls_table *oldset_cp; - int utf8; - int err; - - if (copy_from_user(&user, arg, sizeof(user))) - return -EFAULT; - - codepage = NULL; - user.codepage[NCP_IOCSNAME_LEN] = 0; - if (!user.codepage[0] || !strcmp(user.codepage, "default")) - codepage = load_nls_default(); - else { - codepage = load_nls(user.codepage); - if (!codepage) { - return -EBADRQC; - } - } - - iocharset = NULL; - user.iocharset[NCP_IOCSNAME_LEN] = 0; - if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) { - iocharset = load_nls_default(); - utf8 = 0; - } else if (!strcmp(user.iocharset, "utf8")) { - iocharset = load_nls_default(); - utf8 = 1; - } else { - iocharset = load_nls(user.iocharset); - if (!iocharset) { - unload_nls(codepage); - return -EBADRQC; - } - utf8 = 0; - } - - mutex_lock(&server->root_setup_lock); - if (server->root_setuped) { - oldset_cp = codepage; - oldset_io = iocharset; - err = -EBUSY; - } else { - if (utf8) - NCP_SET_FLAG(server, NCP_FLAG_UTF8); - else - NCP_CLR_FLAG(server, NCP_FLAG_UTF8); - oldset_cp = server->nls_vol; - server->nls_vol = codepage; - oldset_io = server->nls_io; - server->nls_io = iocharset; - err = 0; - } - mutex_unlock(&server->root_setup_lock); - unload_nls(oldset_cp); - unload_nls(oldset_io); - - return err; -} - -static int -ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) -{ - struct ncp_nls_ioctl user; - int len; - - memset(&user, 0, sizeof(user)); - mutex_lock(&server->root_setup_lock); - if (server->nls_vol && server->nls_vol->charset) { - len = strlen(server->nls_vol->charset); - if (len > NCP_IOCSNAME_LEN) - len = NCP_IOCSNAME_LEN; - strncpy(user.codepage, server->nls_vol->charset, len); - user.codepage[len] = 0; - } - - if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) - strcpy(user.iocharset, "utf8"); - else if (server->nls_io && server->nls_io->charset) { - len = strlen(server->nls_io->charset); - if (len > NCP_IOCSNAME_LEN) - len = NCP_IOCSNAME_LEN; - strncpy(user.iocharset, server->nls_io->charset, len); - user.iocharset[len] = 0; - } - mutex_unlock(&server->root_setup_lock); - - if (copy_to_user(arg, &user, sizeof(user))) - return -EFAULT; - return 0; -} -#endif /* CONFIG_NCPFS_NLS */ - -static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg) -{ - struct ncp_server *server = NCP_SERVER(inode); - int result; - struct ncp_ioctl_request request; - char* bouncebuffer; - void __user *argp = (void __user *)arg; - - switch (cmd) { -#ifdef CONFIG_COMPAT - case NCP_IOC_NCPREQUEST_32: -#endif - case NCP_IOC_NCPREQUEST: -#ifdef CONFIG_COMPAT - if (cmd == NCP_IOC_NCPREQUEST_32) { - struct compat_ncp_ioctl_request request32; - if (copy_from_user(&request32, argp, sizeof(request32))) - return -EFAULT; - request.function = request32.function; - request.size = request32.size; - request.data = compat_ptr(request32.data); - } else -#endif - if (copy_from_user(&request, argp, sizeof(request))) - return -EFAULT; - - if ((request.function > 255) - || (request.size > - NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) { - return -EINVAL; - } - bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL); - if (!bouncebuffer) - return -ENOMEM; - if (copy_from_user(bouncebuffer, request.data, request.size)) { - vfree(bouncebuffer); - return -EFAULT; - } - ncp_lock_server(server); - - /* FIXME: We hack around in the server's structures - here to be able to use ncp_request */ - - server->has_subfunction = 0; - server->current_size = request.size; - memcpy(server->packet, bouncebuffer, request.size); - - result = ncp_request2(server, request.function, - bouncebuffer, NCP_PACKET_SIZE_INTERNAL); - if (result < 0) - result = -EIO; - else - result = server->reply_size; - ncp_unlock_server(server); - ncp_dbg(1, "copy %d bytes\n", result); - if (result >= 0) - if (copy_to_user(request.data, bouncebuffer, result)) - result = -EFAULT; - vfree(bouncebuffer); - return result; - - case NCP_IOC_CONN_LOGGED_IN: - - if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE)) - return -EINVAL; - mutex_lock(&server->root_setup_lock); - if (server->root_setuped) - result = -EBUSY; - else { - result = ncp_conn_logged_in(inode->i_sb); - if (result == 0) - server->root_setuped = 1; - } - mutex_unlock(&server->root_setup_lock); - return result; - - case NCP_IOC_GET_FS_INFO: - return ncp_get_fs_info(server, inode, argp); - - case NCP_IOC_GET_FS_INFO_V2: - return ncp_get_fs_info_v2(server, inode, argp); - -#ifdef CONFIG_COMPAT - case NCP_IOC_GET_FS_INFO_V2_32: - return ncp_get_compat_fs_info_v2(server, inode, argp); -#endif - /* we have too many combinations of CONFIG_COMPAT, - * CONFIG_64BIT and CONFIG_UID16, so just handle - * any of the possible ioctls */ - case NCP_IOC_GETMOUNTUID16: - { - u16 uid; - - SET_UID(uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid)); - if (put_user(uid, (u16 __user *)argp)) - return -EFAULT; - return 0; - } - case NCP_IOC_GETMOUNTUID32: - { - uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); - if (put_user(uid, (u32 __user *)argp)) - return -EFAULT; - return 0; - } - case NCP_IOC_GETMOUNTUID64: - { - uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); - if (put_user(uid, (u64 __user *)argp)) - return -EFAULT; - return 0; - } - case NCP_IOC_GETROOT: - { - struct ncp_setroot_ioctl sr; - - result = -EACCES; - mutex_lock(&server->root_setup_lock); - if (server->m.mounted_vol[0]) { - struct dentry* dentry = inode->i_sb->s_root; - - if (dentry) { - struct inode* s_inode = d_inode(dentry); - - if (s_inode) { - sr.volNumber = NCP_FINFO(s_inode)->volNumber; - sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum; - sr.namespace = server->name_space[sr.volNumber]; - result = 0; - } else - ncp_dbg(1, "d_inode(s_root)==NULL\n"); - } else - ncp_dbg(1, "s_root==NULL\n"); - } else { - sr.volNumber = -1; - sr.namespace = 0; - sr.dirEntNum = 0; - result = 0; - } - mutex_unlock(&server->root_setup_lock); - if (!result && copy_to_user(argp, &sr, sizeof(sr))) - result = -EFAULT; - return result; - } - - case NCP_IOC_SETROOT: - { - struct ncp_setroot_ioctl sr; - __u32 vnum; - __le32 de; - __le32 dosde; - struct dentry* dentry; - - if (copy_from_user(&sr, argp, sizeof(sr))) - return -EFAULT; - mutex_lock(&server->root_setup_lock); - if (server->root_setuped) - result = -EBUSY; - else { - if (sr.volNumber < 0) { - server->m.mounted_vol[0] = 0; - vnum = NCP_NUMBER_OF_VOLUMES; - de = 0; - dosde = 0; - result = 0; - } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) { - result = -EINVAL; - } else if (ncp_mount_subdir(server, sr.volNumber, - sr.namespace, sr.dirEntNum, - &vnum, &de, &dosde)) { - result = -ENOENT; - } else - result = 0; - - if (result == 0) { - dentry = inode->i_sb->s_root; - if (dentry) { - struct inode* s_inode = d_inode(dentry); - - if (s_inode) { - NCP_FINFO(s_inode)->volNumber = vnum; - NCP_FINFO(s_inode)->dirEntNum = de; - NCP_FINFO(s_inode)->DosDirNum = dosde; - server->root_setuped = 1; - } else { - ncp_dbg(1, "d_inode(s_root)==NULL\n"); - result = -EIO; - } - } else { - ncp_dbg(1, "s_root==NULL\n"); - result = -EIO; - } - } - } - mutex_unlock(&server->root_setup_lock); - - return result; - } - -#ifdef CONFIG_NCPFS_PACKET_SIGNING - case NCP_IOC_SIGN_INIT: - { - struct ncp_sign_init sign; - - if (argp) - if (copy_from_user(&sign, argp, sizeof(sign))) - return -EFAULT; - ncp_lock_server(server); - mutex_lock(&server->rcv.creq_mutex); - if (argp) { - if (server->sign_wanted) { - memcpy(server->sign_root,sign.sign_root,8); - memcpy(server->sign_last,sign.sign_last,16); - server->sign_active = 1; - } - /* ignore when signatures not wanted */ - } else { - server->sign_active = 0; - } - mutex_unlock(&server->rcv.creq_mutex); - ncp_unlock_server(server); - return 0; - } - - case NCP_IOC_SIGN_WANTED: - { - int state; - - ncp_lock_server(server); - state = server->sign_wanted; - ncp_unlock_server(server); - if (put_user(state, (int __user *)argp)) - return -EFAULT; - return 0; - } - - case NCP_IOC_SET_SIGN_WANTED: - { - int newstate; - - /* get only low 8 bits... */ - if (get_user(newstate, (unsigned char __user *)argp)) - return -EFAULT; - result = 0; - ncp_lock_server(server); - if (server->sign_active) { - /* cannot turn signatures OFF when active */ - if (!newstate) - result = -EINVAL; - } else { - server->sign_wanted = newstate != 0; - } - ncp_unlock_server(server); - return result; - } - -#endif /* CONFIG_NCPFS_PACKET_SIGNING */ - -#ifdef CONFIG_NCPFS_IOCTL_LOCKING - case NCP_IOC_LOCKUNLOCK: - { - struct ncp_lock_ioctl rqdata; - - if (copy_from_user(&rqdata, argp, sizeof(rqdata))) - return -EFAULT; - if (rqdata.origin != 0) - return -EINVAL; - /* check for cmd */ - switch (rqdata.cmd) { - case NCP_LOCK_EX: - case NCP_LOCK_SH: - if (rqdata.timeout < 0) - return -EINVAL; - if (rqdata.timeout == 0) - rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; - else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT) - rqdata.timeout = NCP_LOCK_MAX_TIMEOUT; - break; - case NCP_LOCK_LOG: - rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; /* has no effect */ - case NCP_LOCK_CLEAR: - break; - default: - return -EINVAL; - } - /* locking needs both read and write access */ - if ((result = ncp_make_open(inode, O_RDWR)) != 0) - { - return result; - } - result = -EISDIR; - if (!S_ISREG(inode->i_mode)) - goto outrel; - if (rqdata.cmd == NCP_LOCK_CLEAR) - { - result = ncp_ClearPhysicalRecord(NCP_SERVER(inode), - NCP_FINFO(inode)->file_handle, - rqdata.offset, - rqdata.length); - if (result > 0) result = 0; /* no such lock */ - } - else - { - int lockcmd; - - switch (rqdata.cmd) - { - case NCP_LOCK_EX: lockcmd=1; break; - case NCP_LOCK_SH: lockcmd=3; break; - default: lockcmd=0; break; - } - result = ncp_LogPhysicalRecord(NCP_SERVER(inode), - NCP_FINFO(inode)->file_handle, - lockcmd, - rqdata.offset, - rqdata.length, - rqdata.timeout); - if (result > 0) result = -EAGAIN; - } -outrel: - ncp_inode_close(inode); - return result; - } -#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ - -#ifdef CONFIG_COMPAT - case NCP_IOC_GETOBJECTNAME_32: - { - struct compat_ncp_objectname_ioctl user; - size_t outl; - - if (copy_from_user(&user, argp, sizeof(user))) - return -EFAULT; - down_read(&server->auth_rwsem); - user.auth_type = server->auth.auth_type; - outl = user.object_name_len; - user.object_name_len = server->auth.object_name_len; - if (outl > user.object_name_len) - outl = user.object_name_len; - result = 0; - if (outl) { - if (copy_to_user(compat_ptr(user.object_name), - server->auth.object_name, - outl)) - result = -EFAULT; - } - up_read(&server->auth_rwsem); - if (!result && copy_to_user(argp, &user, sizeof(user))) - result = -EFAULT; - return result; - } -#endif - - case NCP_IOC_GETOBJECTNAME: - { - struct ncp_objectname_ioctl user; - size_t outl; - - if (copy_from_user(&user, argp, sizeof(user))) - return -EFAULT; - down_read(&server->auth_rwsem); - user.auth_type = server->auth.auth_type; - outl = user.object_name_len; - user.object_name_len = server->auth.object_name_len; - if (outl > user.object_name_len) - outl = user.object_name_len; - result = 0; - if (outl) { - if (copy_to_user(user.object_name, - server->auth.object_name, - outl)) - result = -EFAULT; - } - up_read(&server->auth_rwsem); - if (!result && copy_to_user(argp, &user, sizeof(user))) - result = -EFAULT; - return result; - } - -#ifdef CONFIG_COMPAT - case NCP_IOC_SETOBJECTNAME_32: -#endif - case NCP_IOC_SETOBJECTNAME: - { - struct ncp_objectname_ioctl user; - void* newname; - void* oldname; - size_t oldnamelen; - void* oldprivate; - size_t oldprivatelen; - -#ifdef CONFIG_COMPAT - if (cmd == NCP_IOC_SETOBJECTNAME_32) { - struct compat_ncp_objectname_ioctl user32; - if (copy_from_user(&user32, argp, sizeof(user32))) - return -EFAULT; - user.auth_type = user32.auth_type; - user.object_name_len = user32.object_name_len; - user.object_name = compat_ptr(user32.object_name); - } else -#endif - if (copy_from_user(&user, argp, sizeof(user))) - return -EFAULT; - - if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) - return -ENOMEM; - if (user.object_name_len) { - newname = memdup_user(user.object_name, - user.object_name_len); - if (IS_ERR(newname)) - return PTR_ERR(newname); - } else { - newname = NULL; - } - down_write(&server->auth_rwsem); - oldname = server->auth.object_name; - oldnamelen = server->auth.object_name_len; - oldprivate = server->priv.data; - oldprivatelen = server->priv.len; - server->auth.auth_type = user.auth_type; - server->auth.object_name_len = user.object_name_len; - server->auth.object_name = newname; - server->priv.len = 0; - server->priv.data = NULL; - up_write(&server->auth_rwsem); - kfree(oldprivate); - kfree(oldname); - return 0; - } - -#ifdef CONFIG_COMPAT - case NCP_IOC_GETPRIVATEDATA_32: -#endif - case NCP_IOC_GETPRIVATEDATA: - { - struct ncp_privatedata_ioctl user; - size_t outl; - -#ifdef CONFIG_COMPAT - if (cmd == NCP_IOC_GETPRIVATEDATA_32) { - struct compat_ncp_privatedata_ioctl user32; - if (copy_from_user(&user32, argp, sizeof(user32))) - return -EFAULT; - user.len = user32.len; - user.data = compat_ptr(user32.data); - } else -#endif - if (copy_from_user(&user, argp, sizeof(user))) - return -EFAULT; - - down_read(&server->auth_rwsem); - outl = user.len; - user.len = server->priv.len; - if (outl > user.len) outl = user.len; - result = 0; - if (outl) { - if (copy_to_user(user.data, - server->priv.data, - outl)) - result = -EFAULT; - } - up_read(&server->auth_rwsem); - if (result) - return result; -#ifdef CONFIG_COMPAT - if (cmd == NCP_IOC_GETPRIVATEDATA_32) { - struct compat_ncp_privatedata_ioctl user32; - user32.len = user.len; - user32.data = (unsigned long) user.data; - if (copy_to_user(argp, &user32, sizeof(user32))) - return -EFAULT; - } else -#endif - if (copy_to_user(argp, &user, sizeof(user))) - return -EFAULT; - - return 0; - } - -#ifdef CONFIG_COMPAT - case NCP_IOC_SETPRIVATEDATA_32: -#endif - case NCP_IOC_SETPRIVATEDATA: - { - struct ncp_privatedata_ioctl user; - void* new; - void* old; - size_t oldlen; - -#ifdef CONFIG_COMPAT - if (cmd == NCP_IOC_SETPRIVATEDATA_32) { - struct compat_ncp_privatedata_ioctl user32; - if (copy_from_user(&user32, argp, sizeof(user32))) - return -EFAULT; - user.len = user32.len; - user.data = compat_ptr(user32.data); - } else -#endif - if (copy_from_user(&user, argp, sizeof(user))) - return -EFAULT; - - if (user.len > NCP_PRIVATE_DATA_MAX_LEN) - return -ENOMEM; - if (user.len) { - new = memdup_user(user.data, user.len); - if (IS_ERR(new)) - return PTR_ERR(new); - } else { - new = NULL; - } - down_write(&server->auth_rwsem); - old = server->priv.data; - oldlen = server->priv.len; - server->priv.len = user.len; - server->priv.data = new; - up_write(&server->auth_rwsem); - kfree(old); - return 0; - } - -#ifdef CONFIG_NCPFS_NLS - case NCP_IOC_SETCHARSETS: - return ncp_set_charsets(server, argp); - - case NCP_IOC_GETCHARSETS: - return ncp_get_charsets(server, argp); - -#endif /* CONFIG_NCPFS_NLS */ - - case NCP_IOC_SETDENTRYTTL: - { - u_int32_t user; - - if (copy_from_user(&user, argp, sizeof(user))) - return -EFAULT; - /* 20 secs at most... */ - if (user > 20000) - return -EINVAL; - user = (user * HZ) / 1000; - atomic_set(&server->dentry_ttl, user); - return 0; - } - - case NCP_IOC_GETDENTRYTTL: - { - u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ; - if (copy_to_user(argp, &user, sizeof(user))) - return -EFAULT; - return 0; - } - - } - return -EINVAL; -} - -long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct inode *inode = file_inode(filp); - struct ncp_server *server = NCP_SERVER(inode); - kuid_t uid = current_uid(); - int need_drop_write = 0; - long ret; - - switch (cmd) { - case NCP_IOC_SETCHARSETS: - case NCP_IOC_CONN_LOGGED_IN: - case NCP_IOC_SETROOT: - if (!capable(CAP_SYS_ADMIN)) { - ret = -EPERM; - goto out; - } - break; - } - if (!uid_eq(server->m.mounted_uid, uid)) { - switch (cmd) { - /* - * Only mount owner can issue these ioctls. Information - * necessary to authenticate to other NDS servers are - * stored here. - */ - case NCP_IOC_GETOBJECTNAME: - case NCP_IOC_SETOBJECTNAME: - case NCP_IOC_GETPRIVATEDATA: - case NCP_IOC_SETPRIVATEDATA: -#ifdef CONFIG_COMPAT - case NCP_IOC_GETOBJECTNAME_32: - case NCP_IOC_SETOBJECTNAME_32: - case NCP_IOC_GETPRIVATEDATA_32: - case NCP_IOC_SETPRIVATEDATA_32: -#endif - ret = -EACCES; - goto out; - /* - * These require write access on the inode if user id - * does not match. Note that they do not write to the - * file... But old code did mnt_want_write, so I keep - * it as is. Of course not for mountpoint owner, as - * that breaks read-only mounts altogether as ncpmount - * needs working NCP_IOC_NCPREQUEST and - * NCP_IOC_GET_FS_INFO. Some of these codes (setdentryttl, - * signinit, setsignwanted) should be probably restricted - * to owner only, or even more to CAP_SYS_ADMIN). - */ - case NCP_IOC_GET_FS_INFO: - case NCP_IOC_GET_FS_INFO_V2: - case NCP_IOC_NCPREQUEST: - case NCP_IOC_SETDENTRYTTL: - case NCP_IOC_SIGN_INIT: - case NCP_IOC_LOCKUNLOCK: - case NCP_IOC_SET_SIGN_WANTED: -#ifdef CONFIG_COMPAT - case NCP_IOC_GET_FS_INFO_V2_32: - case NCP_IOC_NCPREQUEST_32: -#endif - ret = mnt_want_write_file(filp); - if (ret) - goto out; - need_drop_write = 1; - ret = inode_permission(inode, MAY_WRITE); - if (ret) - goto outDropWrite; - break; - /* - * Read access required. - */ - case NCP_IOC_GETMOUNTUID16: - case NCP_IOC_GETMOUNTUID32: - case NCP_IOC_GETMOUNTUID64: - case NCP_IOC_GETROOT: - case NCP_IOC_SIGN_WANTED: - ret = inode_permission(inode, MAY_READ); - if (ret) - goto out; - break; - /* - * Anybody can read these. - */ - case NCP_IOC_GETCHARSETS: - case NCP_IOC_GETDENTRYTTL: - default: - /* Three codes below are protected by CAP_SYS_ADMIN above. */ - case NCP_IOC_SETCHARSETS: - case NCP_IOC_CONN_LOGGED_IN: - case NCP_IOC_SETROOT: - break; - } - } - ret = __ncp_ioctl(inode, cmd, arg); -outDropWrite: - if (need_drop_write) - mnt_drop_write_file(filp); -out: - return ret; -} - -#ifdef CONFIG_COMPAT -long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret; - - arg = (unsigned long) compat_ptr(arg); - ret = ncp_ioctl(file, cmd, arg); - return ret; -} -#endif diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c deleted file mode 100644 index a5c5cf2ff007..000000000000 --- a/fs/ncpfs/mmap.c +++ /dev/null @@ -1,125 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * mmap.c - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ncp_fs.h" - -/* - * Fill in the supplied page for mmap - * XXX: how are we excluding truncate/invalidate here? Maybe need to lock - * page? - */ -static int ncp_file_mmap_fault(struct vm_fault *vmf) -{ - struct inode *inode = file_inode(vmf->vma->vm_file); - char *pg_addr; - unsigned int already_read; - unsigned int count; - int bufsize; - int pos; /* XXX: loff_t ? */ - - /* - * ncpfs has nothing against high pages as long - * as recvmsg and memset works on it - */ - vmf->page = alloc_page(GFP_HIGHUSER); - if (!vmf->page) - return VM_FAULT_OOM; - pg_addr = kmap(vmf->page); - pos = vmf->pgoff << PAGE_SHIFT; - - count = PAGE_SIZE; - /* what we can read in one go */ - bufsize = NCP_SERVER(inode)->buffer_size; - - already_read = 0; - if (ncp_make_open(inode, O_RDONLY) >= 0) { - while (already_read < count) { - int read_this_time; - int to_read; - - to_read = bufsize - (pos % bufsize); - - to_read = min_t(unsigned int, to_read, count - already_read); - - if (ncp_read_kernel(NCP_SERVER(inode), - NCP_FINFO(inode)->file_handle, - pos, to_read, - pg_addr + already_read, - &read_this_time) != 0) { - read_this_time = 0; - } - pos += read_this_time; - already_read += read_this_time; - - if (read_this_time < to_read) { - break; - } - } - ncp_inode_close(inode); - - } - - if (already_read < PAGE_SIZE) - memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); - flush_dcache_page(vmf->page); - kunmap(vmf->page); - - /* - * If I understand ncp_read_kernel() properly, the above always - * fetches from the network, here the analogue of disk. - * -- nyc - */ - count_vm_event(PGMAJFAULT); - count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT); - return VM_FAULT_MAJOR; -} - -static const struct vm_operations_struct ncp_file_mmap = -{ - .fault = ncp_file_mmap_fault, -}; - - -/* This is used for a general mmap of a ncp file */ -int ncp_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct inode *inode = file_inode(file); - - ncp_dbg(1, "called\n"); - - if (!ncp_conn_valid(NCP_SERVER(inode))) - return -EIO; - - /* only PAGE_COW or read-only supported now */ - if (vma->vm_flags & VM_SHARED) - return -EINVAL; - /* we do not support files bigger than 4GB... We eventually - supports just 4GB... */ - if (vma_pages(vma) + vma->vm_pgoff - > (1U << (32 - PAGE_SHIFT))) - return -EFBIG; - - vma->vm_ops = &ncp_file_mmap; - file_accessed(file); - return 0; -} diff --git a/fs/ncpfs/ncp_fs.h b/fs/ncpfs/ncp_fs.h deleted file mode 100644 index bdd262b6c198..000000000000 --- a/fs/ncpfs/ncp_fs.h +++ /dev/null @@ -1,101 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include -#include "ncp_fs_i.h" -#include "ncp_fs_sb.h" - -#undef NCPFS_PARANOIA -#ifdef NCPFS_PARANOIA -#define ncp_vdbg(fmt, ...) \ - pr_debug(fmt, ##__VA_ARGS__) -#else -#define ncp_vdbg(fmt, ...) \ -do { \ - if (0) \ - pr_debug(fmt, ##__VA_ARGS__); \ -} while (0) -#endif - -#ifndef DEBUG_NCP -#define DEBUG_NCP 0 -#endif - -#if DEBUG_NCP > 0 && !defined(DEBUG) -#define DEBUG -#endif - -#define ncp_dbg(level, fmt, ...) \ -do { \ - if (level <= DEBUG_NCP) \ - pr_debug(fmt, ##__VA_ARGS__); \ -} while (0) - -#define NCP_MAX_RPC_TIMEOUT (6*HZ) - - -struct ncp_entry_info { - struct nw_info_struct i; - ino_t ino; - int opened; - int access; - unsigned int volume; - __u8 file_handle[6]; -}; - -static inline struct ncp_server *NCP_SBP(const struct super_block *sb) -{ - return sb->s_fs_info; -} - -#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) -static inline struct ncp_inode_info *NCP_FINFO(const struct inode *inode) -{ - return container_of(inode, struct ncp_inode_info, vfs_inode); -} - -/* linux/fs/ncpfs/inode.c */ -int ncp_notify_change(struct dentry *, struct iattr *); -struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *); -void ncp_update_inode(struct inode *, struct ncp_entry_info *); -void ncp_update_inode2(struct inode *, struct ncp_entry_info *); - -/* linux/fs/ncpfs/dir.c */ -extern const struct inode_operations ncp_dir_inode_operations; -extern const struct file_operations ncp_dir_operations; -extern const struct dentry_operations ncp_dentry_operations; -int ncp_conn_logged_in(struct super_block *); -int ncp_date_dos2unix(__le16 time, __le16 date); -void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date); - -/* linux/fs/ncpfs/ioctl.c */ -long ncp_ioctl(struct file *, unsigned int, unsigned long); -long ncp_compat_ioctl(struct file *, unsigned int, unsigned long); - -/* linux/fs/ncpfs/sock.c */ -int ncp_request2(struct ncp_server *server, int function, - void* reply, int max_reply_size); -static inline int ncp_request(struct ncp_server *server, int function) { - return ncp_request2(server, function, server->packet, server->packet_size); -} -int ncp_connect(struct ncp_server *server); -int ncp_disconnect(struct ncp_server *server); -void ncp_lock_server(struct ncp_server *server); -void ncp_unlock_server(struct ncp_server *server); - -/* linux/fs/ncpfs/symlink.c */ -#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) -extern const struct address_space_operations ncp_symlink_aops; -int ncp_symlink(struct inode*, struct dentry*, const char*); -#endif - -/* linux/fs/ncpfs/file.c */ -extern const struct inode_operations ncp_file_inode_operations; -extern const struct file_operations ncp_file_operations; -int ncp_make_open(struct inode *, int); - -/* linux/fs/ncpfs/mmap.c */ -int ncp_mmap(struct file *, struct vm_area_struct *); - -/* linux/fs/ncpfs/ncplib_kernel.c */ -int ncp_make_closed(struct inode *); - -#include "ncplib_kernel.h" diff --git a/fs/ncpfs/ncp_fs_i.h b/fs/ncpfs/ncp_fs_i.h deleted file mode 100644 index 3432bafb53a5..000000000000 --- a/fs/ncpfs/ncp_fs_i.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * ncp_fs_i.h - * - * Copyright (C) 1995 Volker Lendecke - * - */ - -#ifndef _LINUX_NCP_FS_I -#define _LINUX_NCP_FS_I - -/* - * This is the ncpfs part of the inode structure. This must contain - * all the information we need to work with an inode after creation. - */ -struct ncp_inode_info { - __le32 dirEntNum; - __le32 DosDirNum; - __u8 volNumber; - __le32 nwattr; - struct mutex open_mutex; - atomic_t opened; - int access; - int flags; -#define NCPI_KLUDGE_SYMLINK 0x0001 -#define NCPI_DIR_CACHE 0x0002 - __u8 file_handle[6]; - struct inode vfs_inode; -}; - -#endif /* _LINUX_NCP_FS_I */ diff --git a/fs/ncpfs/ncp_fs_sb.h b/fs/ncpfs/ncp_fs_sb.h deleted file mode 100644 index f06cde4adf71..000000000000 --- a/fs/ncpfs/ncp_fs_sb.h +++ /dev/null @@ -1,174 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * ncp_fs_sb.h - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * - */ - -#ifndef _NCP_FS_SB -#define _NCP_FS_SB - -#include -#include -#include -#include -#include -#include - -#define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */ - -struct sock; - -struct ncp_mount_data_kernel { - unsigned long flags; /* NCP_MOUNT_* flags */ - unsigned int int_flags; /* internal flags */ -#define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001 - kuid_t mounted_uid; /* Who may umount() this filesystem? */ - struct pid *wdog_pid; /* Who cares for our watchdog packets? */ - unsigned int ncp_fd; /* The socket to the ncp port */ - unsigned int time_out; /* How long should I wait after - sending a NCP request? */ - unsigned int retry_count; /* And how often should I retry? */ - unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; - kuid_t uid; - kgid_t gid; - umode_t file_mode; - umode_t dir_mode; - int info_fd; -}; - -struct ncp_server { - struct rcu_head rcu; - struct ncp_mount_data_kernel m; /* Nearly all of the mount data is of - interest for us later, so we store - it completely. */ - - __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2]; - - struct socket *ncp_sock;/* ncp socket */ - struct socket *info_sock; - - u8 sequence; - u8 task; - u16 connection; /* Remote connection number */ - - u8 completion; /* Status message from server */ - u8 conn_status; /* Bit 4 = 1 ==> Server going down, no - requests allowed anymore. - Bit 0 = 1 ==> Server is down. */ - - int buffer_size; /* Negotiated bufsize */ - - int reply_size; /* Size of last reply */ - - int packet_size; - unsigned char *packet; /* Here we prepare requests and - receive replies */ - unsigned char *txbuf; /* Storage for current request */ - unsigned char *rxbuf; /* Storage for reply to current request */ - - int lock; /* To prevent mismatch in protocols. */ - struct mutex mutex; - - int current_size; /* for packet preparation */ - int has_subfunction; - int ncp_reply_size; - - int root_setuped; - struct mutex root_setup_lock; - - /* info for packet signing */ - int sign_wanted; /* 1=Server needs signed packets */ - int sign_active; /* 0=don't do signing, 1=do */ - char sign_root[8]; /* generated from password and encr. key */ - char sign_last[16]; - - /* Authentication info: NDS or BINDERY, username */ - struct { - int auth_type; - size_t object_name_len; - void* object_name; - int object_type; - } auth; - /* Password info */ - struct { - size_t len; - void* data; - } priv; - struct rw_semaphore auth_rwsem; - - /* nls info: codepage for volume and charset for I/O */ - struct nls_table *nls_vol; - struct nls_table *nls_io; - - /* maximum age in jiffies */ - atomic_t dentry_ttl; - - /* miscellaneous */ - unsigned int flags; - - spinlock_t requests_lock; /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */ - - void (*data_ready)(struct sock* sk); - void (*error_report)(struct sock* sk); - void (*write_space)(struct sock* sk); /* STREAM mode only */ - struct { - struct work_struct tq; /* STREAM/DGRAM: data/error ready */ - struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */ - struct mutex creq_mutex; /* DGRAM only: lock accesses to rcv.creq */ - - unsigned int state; /* STREAM only: receiver state */ - struct { - __u32 magic __packed; - __u32 len __packed; - __u16 type __packed; - __u16 p1 __packed; - __u16 p2 __packed; - __u16 p3 __packed; - __u16 type2 __packed; - } buf; /* STREAM only: temporary buffer */ - unsigned char* ptr; /* STREAM only: pointer to data */ - size_t len; /* STREAM only: length of data to receive */ - } rcv; - struct { - struct list_head requests; /* STREAM only: queued requests */ - struct work_struct tq; /* STREAM only: transmitter ready */ - struct ncp_request_reply* creq; /* STREAM only: currently transmitted entry */ - } tx; - struct timer_list timeout_tm; /* DGRAM only: timeout timer */ - struct work_struct timeout_tq; /* DGRAM only: associated queue, we run timers from process context */ - int timeout_last; /* DGRAM only: current timeout length */ - int timeout_retries; /* DGRAM only: retries left */ - struct { - size_t len; - __u8 data[128]; - } unexpected_packet; -}; - -extern void ncp_tcp_rcv_proc(struct work_struct *work); -extern void ncp_tcp_tx_proc(struct work_struct *work); -extern void ncpdgram_rcv_proc(struct work_struct *work); -extern void ncpdgram_timeout_proc(struct work_struct *work); -extern void ncpdgram_timeout_call(struct timer_list *t); -extern void ncp_tcp_data_ready(struct sock* sk); -extern void ncp_tcp_write_space(struct sock* sk); -extern void ncp_tcp_error_report(struct sock* sk); - -#define NCP_FLAG_UTF8 1 - -#define NCP_CLR_FLAG(server, flag) ((server)->flags &= ~(flag)) -#define NCP_SET_FLAG(server, flag) ((server)->flags |= (flag)) -#define NCP_IS_FLAG(server, flag) ((server)->flags & (flag)) - -static inline int ncp_conn_valid(struct ncp_server *server) -{ - return ((server->conn_status & 0x11) == 0); -} - -static inline void ncp_invalidate_conn(struct ncp_server *server) -{ - server->conn_status |= 0x01; -} - -#endif diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c deleted file mode 100644 index 804adfebba2f..000000000000 --- a/fs/ncpfs/ncplib_kernel.c +++ /dev/null @@ -1,1322 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ncplib_kernel.c - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * Modified for big endian by J.F. Chadima and David S. Miller - * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache - * Modified 1999 Wolfram Pienkoss for NLS - * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "ncp_fs.h" - -static inline void assert_server_locked(struct ncp_server *server) -{ - if (server->lock == 0) { - ncp_dbg(1, "server not locked!\n"); - } -} - -static void ncp_add_byte(struct ncp_server *server, __u8 x) -{ - assert_server_locked(server); - *(__u8 *) (&(server->packet[server->current_size])) = x; - server->current_size += 1; - return; -} - -static void ncp_add_word(struct ncp_server *server, __le16 x) -{ - assert_server_locked(server); - put_unaligned(x, (__le16 *) (&(server->packet[server->current_size]))); - server->current_size += 2; - return; -} - -static void ncp_add_be16(struct ncp_server *server, __u16 x) -{ - assert_server_locked(server); - put_unaligned(cpu_to_be16(x), (__be16 *) (&(server->packet[server->current_size]))); - server->current_size += 2; -} - -static void ncp_add_dword(struct ncp_server *server, __le32 x) -{ - assert_server_locked(server); - put_unaligned(x, (__le32 *) (&(server->packet[server->current_size]))); - server->current_size += 4; - return; -} - -static void ncp_add_be32(struct ncp_server *server, __u32 x) -{ - assert_server_locked(server); - put_unaligned(cpu_to_be32(x), (__be32 *)(&(server->packet[server->current_size]))); - server->current_size += 4; -} - -static inline void ncp_add_dword_lh(struct ncp_server *server, __u32 x) { - ncp_add_dword(server, cpu_to_le32(x)); -} - -static void ncp_add_mem(struct ncp_server *server, const void *source, int size) -{ - assert_server_locked(server); - memcpy(&(server->packet[server->current_size]), source, size); - server->current_size += size; - return; -} - -static void ncp_add_pstring(struct ncp_server *server, const char *s) -{ - int len = strlen(s); - assert_server_locked(server); - if (len > 255) { - ncp_dbg(1, "string too long: %s\n", s); - len = 255; - } - ncp_add_byte(server, len); - ncp_add_mem(server, s, len); - return; -} - -static inline void ncp_init_request(struct ncp_server *server) -{ - ncp_lock_server(server); - - server->current_size = sizeof(struct ncp_request_header); - server->has_subfunction = 0; -} - -static inline void ncp_init_request_s(struct ncp_server *server, int subfunction) -{ - ncp_lock_server(server); - - server->current_size = sizeof(struct ncp_request_header) + 2; - ncp_add_byte(server, subfunction); - - server->has_subfunction = 1; -} - -static inline char * -ncp_reply_data(struct ncp_server *server, int offset) -{ - return &(server->packet[sizeof(struct ncp_reply_header) + offset]); -} - -static inline u8 BVAL(const void *data) -{ - return *(const u8 *)data; -} - -static u8 ncp_reply_byte(struct ncp_server *server, int offset) -{ - return *(const u8 *)ncp_reply_data(server, offset); -} - -static inline u16 WVAL_LH(const void *data) -{ - return get_unaligned_le16(data); -} - -static u16 -ncp_reply_le16(struct ncp_server *server, int offset) -{ - return get_unaligned_le16(ncp_reply_data(server, offset)); -} - -static u16 -ncp_reply_be16(struct ncp_server *server, int offset) -{ - return get_unaligned_be16(ncp_reply_data(server, offset)); -} - -static inline u32 DVAL_LH(const void *data) -{ - return get_unaligned_le32(data); -} - -static __le32 -ncp_reply_dword(struct ncp_server *server, int offset) -{ - return get_unaligned((__le32 *)ncp_reply_data(server, offset)); -} - -static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) { - return le32_to_cpu(ncp_reply_dword(server, offset)); -} - -int -ncp_negotiate_buffersize(struct ncp_server *server, int size, int *target) -{ - int result; - - ncp_init_request(server); - ncp_add_be16(server, size); - - if ((result = ncp_request(server, 33)) != 0) { - ncp_unlock_server(server); - return result; - } - *target = min_t(unsigned int, ncp_reply_be16(server, 0), size); - - ncp_unlock_server(server); - return 0; -} - - -/* options: - * bit 0 ipx checksum - * bit 1 packet signing - */ -int -ncp_negotiate_size_and_options(struct ncp_server *server, - int size, int options, int *ret_size, int *ret_options) { - int result; - - /* there is minimum */ - if (size < NCP_BLOCK_SIZE) size = NCP_BLOCK_SIZE; - - ncp_init_request(server); - ncp_add_be16(server, size); - ncp_add_byte(server, options); - - if ((result = ncp_request(server, 0x61)) != 0) - { - ncp_unlock_server(server); - return result; - } - - /* NCP over UDP returns 0 (!!!) */ - result = ncp_reply_be16(server, 0); - if (result >= NCP_BLOCK_SIZE) - size = min(result, size); - *ret_size = size; - *ret_options = ncp_reply_byte(server, 4); - - ncp_unlock_server(server); - return 0; -} - -int ncp_get_volume_info_with_number(struct ncp_server* server, - int n, struct ncp_volume_info* target) { - int result; - int len; - - ncp_init_request_s(server, 44); - ncp_add_byte(server, n); - - if ((result = ncp_request(server, 22)) != 0) { - goto out; - } - target->total_blocks = ncp_reply_dword_lh(server, 0); - target->free_blocks = ncp_reply_dword_lh(server, 4); - target->purgeable_blocks = ncp_reply_dword_lh(server, 8); - target->not_yet_purgeable_blocks = ncp_reply_dword_lh(server, 12); - target->total_dir_entries = ncp_reply_dword_lh(server, 16); - target->available_dir_entries = ncp_reply_dword_lh(server, 20); - target->sectors_per_block = ncp_reply_byte(server, 28); - - memset(&(target->volume_name), 0, sizeof(target->volume_name)); - - result = -EIO; - len = ncp_reply_byte(server, 29); - if (len > NCP_VOLNAME_LEN) { - ncp_dbg(1, "volume name too long: %d\n", len); - goto out; - } - memcpy(&(target->volume_name), ncp_reply_data(server, 30), len); - result = 0; -out: - ncp_unlock_server(server); - return result; -} - -int ncp_get_directory_info(struct ncp_server* server, __u8 n, - struct ncp_volume_info* target) { - int result; - int len; - - ncp_init_request_s(server, 45); - ncp_add_byte(server, n); - - if ((result = ncp_request(server, 22)) != 0) { - goto out; - } - target->total_blocks = ncp_reply_dword_lh(server, 0); - target->free_blocks = ncp_reply_dword_lh(server, 4); - target->purgeable_blocks = 0; - target->not_yet_purgeable_blocks = 0; - target->total_dir_entries = ncp_reply_dword_lh(server, 8); - target->available_dir_entries = ncp_reply_dword_lh(server, 12); - target->sectors_per_block = ncp_reply_byte(server, 20); - - memset(&(target->volume_name), 0, sizeof(target->volume_name)); - - result = -EIO; - len = ncp_reply_byte(server, 21); - if (len > NCP_VOLNAME_LEN) { - ncp_dbg(1, "volume name too long: %d\n", len); - goto out; - } - memcpy(&(target->volume_name), ncp_reply_data(server, 22), len); - result = 0; -out: - ncp_unlock_server(server); - return result; -} - -int -ncp_close_file(struct ncp_server *server, const char *file_id) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, 0); - ncp_add_mem(server, file_id, 6); - - result = ncp_request(server, 66); - ncp_unlock_server(server); - return result; -} - -int -ncp_make_closed(struct inode *inode) -{ - int err; - - err = 0; - mutex_lock(&NCP_FINFO(inode)->open_mutex); - if (atomic_read(&NCP_FINFO(inode)->opened) == 1) { - atomic_set(&NCP_FINFO(inode)->opened, 0); - err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle); - - if (!err) - ncp_vdbg("volnum=%d, dirent=%u, error=%d\n", - NCP_FINFO(inode)->volNumber, - NCP_FINFO(inode)->dirEntNum, err); - } - mutex_unlock(&NCP_FINFO(inode)->open_mutex); - return err; -} - -static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num, - __le32 dir_base, int have_dir_base, - const char *path) -{ - ncp_add_byte(server, vol_num); - ncp_add_dword(server, dir_base); - if (have_dir_base != 0) { - ncp_add_byte(server, 1); /* dir_base */ - } else { - ncp_add_byte(server, 0xff); /* no handle */ - } - if (path != NULL) { - ncp_add_byte(server, 1); /* 1 component */ - ncp_add_pstring(server, path); - } else { - ncp_add_byte(server, 0); - } -} - -int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __le32 dirent, - __u8* dirhandle) { - int result; - - ncp_init_request(server); - ncp_add_byte(server, 12); /* subfunction */ - ncp_add_byte(server, NW_NS_DOS); - ncp_add_byte(server, 0); - ncp_add_word(server, 0); - ncp_add_handle_path(server, volnum, dirent, 1, NULL); - if ((result = ncp_request(server, 87)) == 0) { - *dirhandle = ncp_reply_byte(server, 0); - } - ncp_unlock_server(server); - return result; -} - -int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) { - int result; - - ncp_init_request_s(server, 20); - ncp_add_byte(server, dirhandle); - result = ncp_request(server, 22); - ncp_unlock_server(server); - return result; -} - -void ncp_extract_file_info(const void *structure, struct nw_info_struct *target) -{ - const __u8 *name_len; - const int info_struct_size = offsetof(struct nw_info_struct, nameLen); - - memcpy(target, structure, info_struct_size); - name_len = structure + info_struct_size; - target->nameLen = *name_len; - memcpy(target->entryName, name_len + 1, *name_len); - target->entryName[*name_len] = '\0'; - target->volNumber = le32_to_cpu(target->volNumber); - return; -} - -#ifdef CONFIG_NCPFS_NFS_NS -static inline void ncp_extract_nfs_info(const unsigned char *structure, - struct nw_nfs_info *target) -{ - target->mode = DVAL_LH(structure); - target->rdev = DVAL_LH(structure + 8); -} -#endif - -int ncp_obtain_nfs_info(struct ncp_server *server, - struct nw_info_struct *target) - -{ - int result = 0; -#ifdef CONFIG_NCPFS_NFS_NS - __u32 volnum = target->volNumber; - - if (ncp_is_nfs_extras(server, volnum)) { - ncp_init_request(server); - ncp_add_byte(server, 19); /* subfunction */ - ncp_add_byte(server, server->name_space[volnum]); - ncp_add_byte(server, NW_NS_NFS); - ncp_add_byte(server, 0); - ncp_add_byte(server, volnum); - ncp_add_dword(server, target->dirEntNum); - /* We must retrieve both nlinks and rdev, otherwise some server versions - report zeroes instead of valid data */ - ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV); - - if ((result = ncp_request(server, 87)) == 0) { - ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs); - ncp_dbg(1, "(%s) mode=0%o, rdev=0x%x\n", - target->entryName, target->nfs.mode, - target->nfs.rdev); - } else { - target->nfs.mode = 0; - target->nfs.rdev = 0; - } - ncp_unlock_server(server); - - } else -#endif - { - target->nfs.mode = 0; - target->nfs.rdev = 0; - } - return result; -} - -/* - * Returns information for a (one-component) name relative to - * the specified directory. - */ -int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path, - struct nw_info_struct *target) -{ - __u8 volnum = NCP_FINFO(dir)->volNumber; - __le32 dirent = NCP_FINFO(dir)->dirEntNum; - int result; - - if (target == NULL) { - pr_err("%s: invalid call\n", __func__); - return -EINVAL; - } - ncp_init_request(server); - ncp_add_byte(server, 6); /* subfunction */ - ncp_add_byte(server, server->name_space[volnum]); - ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */ - ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ - ncp_add_dword(server, RIM_ALL); - ncp_add_handle_path(server, volnum, dirent, 1, path); - - if ((result = ncp_request(server, 87)) != 0) - goto out; - ncp_extract_file_info(ncp_reply_data(server, 0), target); - ncp_unlock_server(server); - - result = ncp_obtain_nfs_info(server, target); - return result; - -out: - ncp_unlock_server(server); - return result; -} - -#ifdef CONFIG_NCPFS_NFS_NS -static int -ncp_obtain_DOS_dir_base(struct ncp_server *server, - __u8 ns, __u8 volnum, __le32 dirent, - const char *path, /* At most 1 component */ - __le32 *DOS_dir_base) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, 6); /* subfunction */ - ncp_add_byte(server, ns); - ncp_add_byte(server, ns); - ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ - ncp_add_dword(server, RIM_DIRECTORY); - ncp_add_handle_path(server, volnum, dirent, 1, path); - - if ((result = ncp_request(server, 87)) == 0) - { - if (DOS_dir_base) *DOS_dir_base=ncp_reply_dword(server, 0x34); - } - ncp_unlock_server(server); - return result; -} -#endif /* CONFIG_NCPFS_NFS_NS */ - -static inline int -ncp_get_known_namespace(struct ncp_server *server, __u8 volume) -{ -#if defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) - int result; - __u8 *namespace; - __u16 no_namespaces; - - ncp_init_request(server); - ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */ - ncp_add_word(server, 0); - ncp_add_byte(server, volume); - - if ((result = ncp_request(server, 87)) != 0) { - ncp_unlock_server(server); - return NW_NS_DOS; /* not result ?? */ - } - - result = NW_NS_DOS; - no_namespaces = ncp_reply_le16(server, 0); - namespace = ncp_reply_data(server, 2); - - while (no_namespaces > 0) { - ncp_dbg(1, "found %d on %d\n", *namespace, volume); - -#ifdef CONFIG_NCPFS_NFS_NS - if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) - { - result = NW_NS_NFS; - break; - } -#endif /* CONFIG_NCPFS_NFS_NS */ -#ifdef CONFIG_NCPFS_OS2_NS - if ((*namespace == NW_NS_OS2) && !(server->m.flags&NCP_MOUNT_NO_OS2)) - { - result = NW_NS_OS2; - } -#endif /* CONFIG_NCPFS_OS2_NS */ - namespace += 1; - no_namespaces -= 1; - } - ncp_unlock_server(server); - return result; -#else /* neither OS2 nor NFS - only DOS */ - return NW_NS_DOS; -#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */ -} - -int -ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns) -{ - int ns = ncp_get_known_namespace(server, volume); - - if (ret_ns) - *ret_ns = ns; - - ncp_dbg(1, "namespace[%d] = %d\n", volume, server->name_space[volume]); - - if (server->name_space[volume] == ns) - return 0; - server->name_space[volume] = ns; - return 1; -} - -static int -ncp_ObtainSpecificDirBase(struct ncp_server *server, - __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base, - const char *path, /* At most 1 component */ - __le32 *dirEntNum, __le32 *DosDirNum) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, 6); /* subfunction */ - ncp_add_byte(server, nsSrc); - ncp_add_byte(server, nsDst); - ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ - ncp_add_dword(server, RIM_ALL); - ncp_add_handle_path(server, vol_num, dir_base, 1, path); - - if ((result = ncp_request(server, 87)) != 0) - { - ncp_unlock_server(server); - return result; - } - - if (dirEntNum) - *dirEntNum = ncp_reply_dword(server, 0x30); - if (DosDirNum) - *DosDirNum = ncp_reply_dword(server, 0x34); - ncp_unlock_server(server); - return 0; -} - -int -ncp_mount_subdir(struct ncp_server *server, - __u8 volNumber, __u8 srcNS, __le32 dirEntNum, - __u32* volume, __le32* newDirEnt, __le32* newDosEnt) -{ - int dstNS; - int result; - - ncp_update_known_namespace(server, volNumber, &dstNS); - if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, - dirEntNum, NULL, newDirEnt, newDosEnt)) != 0) - { - return result; - } - *volume = volNumber; - server->m.mounted_vol[1] = 0; - server->m.mounted_vol[0] = 'X'; - return 0; -} - -int -ncp_get_volume_root(struct ncp_server *server, - const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent) -{ - int result; - - ncp_dbg(1, "looking up vol %s\n", volname); - - ncp_init_request(server); - ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */ - ncp_add_byte(server, 0); /* DOS namespace */ - ncp_add_byte(server, 0); /* reserved */ - ncp_add_byte(server, 0); /* reserved */ - ncp_add_byte(server, 0); /* reserved */ - - ncp_add_byte(server, 0); /* faked volume number */ - ncp_add_dword(server, 0); /* faked dir_base */ - ncp_add_byte(server, 0xff); /* Don't have a dir_base */ - ncp_add_byte(server, 1); /* 1 path component */ - ncp_add_pstring(server, volname); - - if ((result = ncp_request(server, 87)) != 0) { - ncp_unlock_server(server); - return result; - } - *dirent = *dosdirent = ncp_reply_dword(server, 4); - *volume = ncp_reply_byte(server, 8); - ncp_unlock_server(server); - return 0; -} - -int -ncp_lookup_volume(struct ncp_server *server, - const char *volname, struct nw_info_struct *target) -{ - int result; - - memset(target, 0, sizeof(*target)); - result = ncp_get_volume_root(server, volname, - &target->volNumber, &target->dirEntNum, &target->DosDirNum); - if (result) { - return result; - } - ncp_update_known_namespace(server, target->volNumber, NULL); - target->nameLen = strlen(volname); - memcpy(target->entryName, volname, target->nameLen+1); - target->attributes = aDIR; - /* set dates to Jan 1, 1986 00:00 */ - target->creationTime = target->modifyTime = cpu_to_le16(0x0000); - target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21); - target->nfs.mode = 0; - return 0; -} - -int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server, - struct inode *dir, - const char *path, - __le32 info_mask, - const struct nw_modify_dos_info *info) -{ - __u8 volnum = NCP_FINFO(dir)->volNumber; - __le32 dirent = NCP_FINFO(dir)->dirEntNum; - int result; - - ncp_init_request(server); - ncp_add_byte(server, 7); /* subfunction */ - ncp_add_byte(server, server->name_space[volnum]); - ncp_add_byte(server, 0); /* reserved */ - ncp_add_word(server, cpu_to_le16(0x8006)); /* search attribs: all */ - - ncp_add_dword(server, info_mask); - ncp_add_mem(server, info, sizeof(*info)); - ncp_add_handle_path(server, volnum, dirent, 1, path); - - result = ncp_request(server, 87); - ncp_unlock_server(server); - return result; -} - -int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, - struct inode *dir, - __le32 info_mask, - const struct nw_modify_dos_info *info) -{ - return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL, - info_mask, info); -} - -#ifdef CONFIG_NCPFS_NFS_NS -int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent, - __u32 mode, __u32 rdev) - -{ - int result = 0; - - ncp_init_request(server); - if (server->name_space[volnum] == NW_NS_NFS) { - ncp_add_byte(server, 25); /* subfunction */ - ncp_add_byte(server, server->name_space[volnum]); - ncp_add_byte(server, NW_NS_NFS); - ncp_add_byte(server, volnum); - ncp_add_dword(server, dirent); - /* we must always operate on both nlinks and rdev, otherwise - rdev is not set */ - ncp_add_dword_lh(server, NSIBM_NFS_MODE | NSIBM_NFS_NLINKS | NSIBM_NFS_RDEV); - ncp_add_dword_lh(server, mode); - ncp_add_dword_lh(server, 1); /* nlinks */ - ncp_add_dword_lh(server, rdev); - result = ncp_request(server, 87); - } - ncp_unlock_server(server); - return result; -} -#endif - - -static int -ncp_DeleteNSEntry(struct ncp_server *server, - __u8 have_dir_base, __u8 volnum, __le32 dirent, - const char* name, __u8 ns, __le16 attr) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, 8); /* subfunction */ - ncp_add_byte(server, ns); - ncp_add_byte(server, 0); /* reserved */ - ncp_add_word(server, attr); /* search attribs: all */ - ncp_add_handle_path(server, volnum, dirent, have_dir_base, name); - - result = ncp_request(server, 87); - ncp_unlock_server(server); - return result; -} - -int -ncp_del_file_or_subdir2(struct ncp_server *server, - struct dentry *dentry) -{ - struct inode *inode = d_inode(dentry); - __u8 volnum; - __le32 dirent; - - if (!inode) { - return 0xFF; /* Any error */ - } - volnum = NCP_FINFO(inode)->volNumber; - dirent = NCP_FINFO(inode)->DosDirNum; - return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006)); -} - -int -ncp_del_file_or_subdir(struct ncp_server *server, - struct inode *dir, const char *name) -{ - __u8 volnum = NCP_FINFO(dir)->volNumber; - __le32 dirent = NCP_FINFO(dir)->dirEntNum; - int name_space; - - name_space = server->name_space[volnum]; -#ifdef CONFIG_NCPFS_NFS_NS - if (name_space == NW_NS_NFS) - { - int result; - - result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent); - if (result) return result; - name = NULL; - name_space = NW_NS_DOS; - } -#endif /* CONFIG_NCPFS_NFS_NS */ - return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006)); -} - -static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6]) -{ - __le16 *dest = (__le16 *) ret; - dest[1] = cpu_to_le16(v0); - dest[2] = cpu_to_le16(v1); - dest[0] = cpu_to_le16(v0 + 1); - return; -} - -/* If both dir and name are NULL, then in target there's already a - looked-up entry that wants to be opened. */ -int ncp_open_create_file_or_subdir(struct ncp_server *server, - struct inode *dir, const char *name, - int open_create_mode, - __le32 create_attributes, - __le16 desired_acc_rights, - struct ncp_entry_info *target) -{ - __le16 search_attribs = cpu_to_le16(0x0006); - __u8 volnum; - __le32 dirent; - int result; - - volnum = NCP_FINFO(dir)->volNumber; - dirent = NCP_FINFO(dir)->dirEntNum; - - if ((create_attributes & aDIR) != 0) { - search_attribs |= cpu_to_le16(0x8000); - } - ncp_init_request(server); - ncp_add_byte(server, 1); /* subfunction */ - ncp_add_byte(server, server->name_space[volnum]); - ncp_add_byte(server, open_create_mode); - ncp_add_word(server, search_attribs); - ncp_add_dword(server, RIM_ALL); - ncp_add_dword(server, create_attributes); - /* The desired acc rights seem to be the inherited rights mask - for directories */ - ncp_add_word(server, desired_acc_rights); - ncp_add_handle_path(server, volnum, dirent, 1, name); - - if ((result = ncp_request(server, 87)) != 0) - goto out; - if (!(create_attributes & aDIR)) - target->opened = 1; - - /* in target there's a new finfo to fill */ - ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i)); - target->volume = target->i.volNumber; - ConvertToNWfromDWORD(ncp_reply_le16(server, 0), - ncp_reply_le16(server, 2), - target->file_handle); - - ncp_unlock_server(server); - - (void)ncp_obtain_nfs_info(server, &(target->i)); - return 0; - -out: - ncp_unlock_server(server); - return result; -} - -int -ncp_initialize_search(struct ncp_server *server, struct inode *dir, - struct nw_search_sequence *target) -{ - __u8 volnum = NCP_FINFO(dir)->volNumber; - __le32 dirent = NCP_FINFO(dir)->dirEntNum; - int result; - - ncp_init_request(server); - ncp_add_byte(server, 2); /* subfunction */ - ncp_add_byte(server, server->name_space[volnum]); - ncp_add_byte(server, 0); /* reserved */ - ncp_add_handle_path(server, volnum, dirent, 1, NULL); - - result = ncp_request(server, 87); - if (result) - goto out; - memcpy(target, ncp_reply_data(server, 0), sizeof(*target)); - -out: - ncp_unlock_server(server); - return result; -} - -int ncp_search_for_fileset(struct ncp_server *server, - struct nw_search_sequence *seq, - int* more, - int* cnt, - char* buffer, - size_t bufsize, - char** rbuf, - size_t* rsize) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, 20); - ncp_add_byte(server, server->name_space[seq->volNumber]); - ncp_add_byte(server, 0); /* datastream */ - ncp_add_word(server, cpu_to_le16(0x8006)); - ncp_add_dword(server, RIM_ALL); - ncp_add_word(server, cpu_to_le16(32767)); /* max returned items */ - ncp_add_mem(server, seq, 9); -#ifdef CONFIG_NCPFS_NFS_NS - if (server->name_space[seq->volNumber] == NW_NS_NFS) { - ncp_add_byte(server, 0); /* 0 byte pattern */ - } else -#endif - { - ncp_add_byte(server, 2); /* 2 byte pattern */ - ncp_add_byte(server, 0xff); /* following is a wildcard */ - ncp_add_byte(server, '*'); - } - result = ncp_request2(server, 87, buffer, bufsize); - if (result) { - ncp_unlock_server(server); - return result; - } - if (server->ncp_reply_size < 12) { - ncp_unlock_server(server); - return 0xFF; - } - *rsize = server->ncp_reply_size - 12; - ncp_unlock_server(server); - buffer = buffer + sizeof(struct ncp_reply_header); - *rbuf = buffer + 12; - *cnt = WVAL_LH(buffer + 10); - *more = BVAL(buffer + 9); - memcpy(seq, buffer, 9); - return 0; -} - -static int -ncp_RenameNSEntry(struct ncp_server *server, - struct inode *old_dir, const char *old_name, __le16 old_type, - struct inode *new_dir, const char *new_name) -{ - int result = -EINVAL; - - if ((old_dir == NULL) || (old_name == NULL) || - (new_dir == NULL) || (new_name == NULL)) - goto out; - - ncp_init_request(server); - ncp_add_byte(server, 4); /* subfunction */ - ncp_add_byte(server, server->name_space[NCP_FINFO(old_dir)->volNumber]); - ncp_add_byte(server, 1); /* rename flag */ - ncp_add_word(server, old_type); /* search attributes */ - - /* source Handle Path */ - ncp_add_byte(server, NCP_FINFO(old_dir)->volNumber); - ncp_add_dword(server, NCP_FINFO(old_dir)->dirEntNum); - ncp_add_byte(server, 1); - ncp_add_byte(server, 1); /* 1 source component */ - - /* dest Handle Path */ - ncp_add_byte(server, NCP_FINFO(new_dir)->volNumber); - ncp_add_dword(server, NCP_FINFO(new_dir)->dirEntNum); - ncp_add_byte(server, 1); - ncp_add_byte(server, 1); /* 1 destination component */ - - /* source path string */ - ncp_add_pstring(server, old_name); - /* dest path string */ - ncp_add_pstring(server, new_name); - - result = ncp_request(server, 87); - ncp_unlock_server(server); -out: - return result; -} - -int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, - struct inode *old_dir, const char *old_name, - struct inode *new_dir, const char *new_name) -{ - int result; - __le16 old_type = cpu_to_le16(0x06); - -/* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */ - result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, - new_dir, new_name); - if (result == 0xFF) /* File Not Found, try directory */ - { - old_type = cpu_to_le16(0x16); - result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, - new_dir, new_name); - } - if (result != 0x92) return result; /* All except NO_FILES_RENAMED */ - result = ncp_del_file_or_subdir(server, new_dir, new_name); - if (result != 0) return -EACCES; - result = ncp_RenameNSEntry(server, old_dir, old_name, old_type, - new_dir, new_name); - return result; -} - - -/* We have to transfer to/from user space */ -int -ncp_read_kernel(struct ncp_server *server, const char *file_id, - __u32 offset, __u16 to_read, char *target, int *bytes_read) -{ - const char *source; - int result; - - ncp_init_request(server); - ncp_add_byte(server, 0); - ncp_add_mem(server, file_id, 6); - ncp_add_be32(server, offset); - ncp_add_be16(server, to_read); - - if ((result = ncp_request(server, 72)) != 0) { - goto out; - } - *bytes_read = ncp_reply_be16(server, 0); - source = ncp_reply_data(server, 2 + (offset & 1)); - - memcpy(target, source, *bytes_read); -out: - ncp_unlock_server(server); - return result; -} - -/* There is a problem... egrep and some other silly tools do: - x = mmap(NULL, MAP_PRIVATE, PROT_READ|PROT_WRITE, , 32768); - read(, x, 32768); - Now copying read result by copy_to_user causes pagefault. This pagefault - could not be handled because of server was locked due to read. So we have - to use temporary buffer. So ncp_unlock_server must be done before - copy_to_user (and for write, copy_from_user must be done before - ncp_init_request... same applies for send raw packet ioctl). Because of - file is normally read in bigger chunks, caller provides kmalloced - (vmalloced) chunk of memory with size >= to_read... - */ -int -ncp_read_bounce(struct ncp_server *server, const char *file_id, - __u32 offset, __u16 to_read, struct iov_iter *to, - int *bytes_read, void *bounce, __u32 bufsize) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, 0); - ncp_add_mem(server, file_id, 6); - ncp_add_be32(server, offset); - ncp_add_be16(server, to_read); - result = ncp_request2(server, 72, bounce, bufsize); - ncp_unlock_server(server); - if (!result) { - int len = get_unaligned_be16((char *)bounce + - sizeof(struct ncp_reply_header)); - result = -EIO; - if (len <= to_read) { - char* source; - - source = (char*)bounce + - sizeof(struct ncp_reply_header) + 2 + - (offset & 1); - *bytes_read = len; - result = 0; - if (copy_to_iter(source, len, to) != len) - result = -EFAULT; - } - } - return result; -} - -int -ncp_write_kernel(struct ncp_server *server, const char *file_id, - __u32 offset, __u16 to_write, - const char *source, int *bytes_written) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, 0); - ncp_add_mem(server, file_id, 6); - ncp_add_be32(server, offset); - ncp_add_be16(server, to_write); - ncp_add_mem(server, source, to_write); - - if ((result = ncp_request(server, 73)) == 0) - *bytes_written = to_write; - ncp_unlock_server(server); - return result; -} - -#ifdef CONFIG_NCPFS_IOCTL_LOCKING -int -ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id, - __u8 locktype, __u32 offset, __u32 length, __u16 timeout) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, locktype); - ncp_add_mem(server, file_id, 6); - ncp_add_be32(server, offset); - ncp_add_be32(server, length); - ncp_add_be16(server, timeout); - - if ((result = ncp_request(server, 0x1A)) != 0) - { - ncp_unlock_server(server); - return result; - } - ncp_unlock_server(server); - return 0; -} - -int -ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id, - __u32 offset, __u32 length) -{ - int result; - - ncp_init_request(server); - ncp_add_byte(server, 0); /* who knows... lanalyzer says that */ - ncp_add_mem(server, file_id, 6); - ncp_add_be32(server, offset); - ncp_add_be32(server, length); - - if ((result = ncp_request(server, 0x1E)) != 0) - { - ncp_unlock_server(server); - return result; - } - ncp_unlock_server(server); - return 0; -} -#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ - -#ifdef CONFIG_NCPFS_NLS -/* This are the NLS conversion routines with inspirations and code parts - * from the vfat file system and hints from Petr Vandrovec. - */ - -int -ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen, - const unsigned char *iname, unsigned int ilen, int cc) -{ - struct nls_table *in = server->nls_io; - struct nls_table *out = server->nls_vol; - unsigned char *vname_start; - unsigned char *vname_end; - const unsigned char *iname_end; - - iname_end = iname + ilen; - vname_start = vname; - vname_end = vname + *vlen - 1; - - while (iname < iname_end) { - int chl; - wchar_t ec; - - if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { - int k; - unicode_t u; - - k = utf8_to_utf32(iname, iname_end - iname, &u); - if (k < 0 || u > MAX_WCHAR_T) - return -EINVAL; - iname += k; - ec = u; - } else { - if (*iname == NCP_ESC) { - int k; - - if (iname_end - iname < 5) - goto nospec; - - ec = 0; - for (k = 1; k < 5; k++) { - unsigned char nc; - - nc = iname[k] - '0'; - if (nc >= 10) { - nc -= 'A' - '0' - 10; - if ((nc < 10) || (nc > 15)) { - goto nospec; - } - } - ec = (ec << 4) | nc; - } - iname += 5; - } else { -nospec:; - if ( (chl = in->char2uni(iname, iname_end - iname, &ec)) < 0) - return chl; - iname += chl; - } - } - - /* unitoupper should be here! */ - - chl = out->uni2char(ec, vname, vname_end - vname); - if (chl < 0) - return chl; - - /* this is wrong... */ - if (cc) { - int chi; - - for (chi = 0; chi < chl; chi++){ - vname[chi] = ncp_toupper(out, vname[chi]); - } - } - vname += chl; - } - - *vname = 0; - *vlen = vname - vname_start; - return 0; -} - -int -ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen, - const unsigned char *vname, unsigned int vlen, int cc) -{ - struct nls_table *in = server->nls_vol; - struct nls_table *out = server->nls_io; - const unsigned char *vname_end; - unsigned char *iname_start; - unsigned char *iname_end; - unsigned char *vname_cc; - int err; - - vname_cc = NULL; - - if (cc) { - int i; - - /* this is wrong! */ - vname_cc = kmalloc(vlen, GFP_KERNEL); - if (!vname_cc) - return -ENOMEM; - for (i = 0; i < vlen; i++) - vname_cc[i] = ncp_tolower(in, vname[i]); - vname = vname_cc; - } - - iname_start = iname; - iname_end = iname + *ilen - 1; - vname_end = vname + vlen; - - while (vname < vname_end) { - wchar_t ec; - int chl; - - if ( (chl = in->char2uni(vname, vname_end - vname, &ec)) < 0) { - err = chl; - goto quit; - } - vname += chl; - - /* unitolower should be here! */ - - if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { - int k; - - k = utf32_to_utf8(ec, iname, iname_end - iname); - if (k < 0) { - err = -ENAMETOOLONG; - goto quit; - } - iname += k; - } else { - if ( (chl = out->uni2char(ec, iname, iname_end - iname)) >= 0) { - iname += chl; - } else { - int k; - - if (iname_end - iname < 5) { - err = -ENAMETOOLONG; - goto quit; - } - *iname = NCP_ESC; - for (k = 4; k > 0; k--) { - unsigned char v; - - v = (ec & 0xF) + '0'; - if (v > '9') { - v += 'A' - '9' - 1; - } - iname[k] = v; - ec >>= 4; - } - iname += 5; - } - } - } - - *iname = 0; - *ilen = iname - iname_start; - err = 0; -quit:; - if (cc) - kfree(vname_cc); - return err; -} - -#else - -int -ncp__io2vol(unsigned char *vname, unsigned int *vlen, - const unsigned char *iname, unsigned int ilen, int cc) -{ - int i; - - if (*vlen <= ilen) - return -ENAMETOOLONG; - - if (cc) - for (i = 0; i < ilen; i++) { - *vname = toupper(*iname); - vname++; - iname++; - } - else { - memmove(vname, iname, ilen); - vname += ilen; - } - - *vlen = ilen; - *vname = 0; - return 0; -} - -int -ncp__vol2io(unsigned char *iname, unsigned int *ilen, - const unsigned char *vname, unsigned int vlen, int cc) -{ - int i; - - if (*ilen <= vlen) - return -ENAMETOOLONG; - - if (cc) - for (i = 0; i < vlen; i++) { - *iname = tolower(*vname); - iname++; - vname++; - } - else { - memmove(iname, vname, vlen); - iname += vlen; - } - - *ilen = vlen; - *iname = 0; - return 0; -} - -#endif diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h deleted file mode 100644 index aaae8aa9bf7d..000000000000 --- a/fs/ncpfs/ncplib_kernel.h +++ /dev/null @@ -1,215 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * ncplib_kernel.h - * - * Copyright (C) 1995, 1996 by Volker Lendecke - * Modified for big endian by J.F. Chadima and David S. Miller - * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache - * Modified 1998, 1999 Wolfram Pienkoss for NLS - * Modified 1999 Wolfram Pienkoss for directory caching - * - */ - -#ifndef _NCPLIB_H -#define _NCPLIB_H - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef CONFIG_NCPFS_NLS -#include -#else -#include -#endif /* CONFIG_NCPFS_NLS */ - -#define NCP_MIN_SYMLINK_SIZE 8 -#define NCP_MAX_SYMLINK_SIZE 512 - -#define NCP_BLOCK_SHIFT 9 -#define NCP_BLOCK_SIZE (1 << (NCP_BLOCK_SHIFT)) - -int ncp_negotiate_buffersize(struct ncp_server *, int, int *); -int ncp_negotiate_size_and_options(struct ncp_server *server, int size, - int options, int *ret_size, int *ret_options); - -int ncp_get_volume_info_with_number(struct ncp_server* server, int n, - struct ncp_volume_info *target); - -int ncp_get_directory_info(struct ncp_server* server, __u8 dirhandle, - struct ncp_volume_info* target); - -int ncp_close_file(struct ncp_server *, const char *); -static inline int ncp_read_bounce_size(__u32 size) { - return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8; -}; -int ncp_read_bounce(struct ncp_server *, const char *, __u32, __u16, - struct iov_iter *, int *, void *bounce, __u32 bouncelen); -int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, - char *, int *); -int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16, - const char *, int *); - -static inline void ncp_inode_close(struct inode *inode) { - atomic_dec(&NCP_FINFO(inode)->opened); -} - -void ncp_extract_file_info(const void* src, struct nw_info_struct* target); -int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *, - struct nw_info_struct *target); -int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target); -int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns); -int ncp_get_volume_root(struct ncp_server *server, const char *volname, - __u32 *volume, __le32 *dirent, __le32 *dosdirent); -int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *); -int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *, - __le32, const struct nw_modify_dos_info *info); -int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *, - const char* path, __le32, const struct nw_modify_dos_info *info); -int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent, - __u32 mode, __u32 rdev); - -int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*); -int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *); -int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *, - int, __le32, __le16, struct ncp_entry_info *); - -int ncp_initialize_search(struct ncp_server *, struct inode *, - struct nw_search_sequence *target); -int ncp_search_for_fileset(struct ncp_server *server, - struct nw_search_sequence *seq, - int* more, int* cnt, - char* buffer, size_t bufsize, - char** rbuf, size_t* rsize); - -int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, - struct inode *, const char *, struct inode *, const char *); - - -int -ncp_LogPhysicalRecord(struct ncp_server *server, - const char *file_id, __u8 locktype, - __u32 offset, __u32 length, __u16 timeout); - -#ifdef CONFIG_NCPFS_IOCTL_LOCKING -int -ncp_ClearPhysicalRecord(struct ncp_server *server, - const char *file_id, - __u32 offset, __u32 length); -#endif /* CONFIG_NCPFS_IOCTL_LOCKING */ - -int -ncp_mount_subdir(struct ncp_server *, __u8, __u8, __le32, - __u32* volume, __le32* dirent, __le32* dosdirent); -int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __le32 dirent, __u8 *dirhandle); -int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle); - -int ncp_create_new(struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t rdev, __le32 attributes); - -static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) { -#ifdef CONFIG_NCPFS_NFS_NS - return (server->m.flags & NCP_MOUNT_NFS_EXTRAS) && - (server->name_space[volnum] == NW_NS_NFS); -#else - return 0; -#endif -} - -#ifdef CONFIG_NCPFS_NLS - -int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *, - const unsigned char *, unsigned int, int); -int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *, - const unsigned char *, unsigned int, int); - -#define NCP_ESC ':' -#define NCP_IO_TABLE(sb) (NCP_SBP(sb)->nls_io) -#define ncp_tolower(t, c) nls_tolower(t, c) -#define ncp_toupper(t, c) nls_toupper(t, c) -#define ncp_strnicmp(t, s1, s2, len) \ - nls_strnicmp(t, s1, s2, len) -#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(S,m,i,n,k,U) -#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(S,m,i,n,k,U) - -#else - -int ncp__io2vol(unsigned char *, unsigned int *, - const unsigned char *, unsigned int, int); -int ncp__vol2io(unsigned char *, unsigned int *, - const unsigned char *, unsigned int, int); - -#define NCP_IO_TABLE(sb) NULL -#define ncp_tolower(t, c) tolower(c) -#define ncp_toupper(t, c) toupper(c) -#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(m,i,n,k,U) -#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(m,i,n,k,U) - - -static inline int ncp_strnicmp(const struct nls_table *t, - const unsigned char *s1, const unsigned char *s2, int len) -{ - while (len--) { - if (tolower(*s1++) != tolower(*s2++)) - return 1; - } - - return 0; -} - -#endif /* CONFIG_NCPFS_NLS */ - -#define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time) -#define NCP_MAX_AGE(server) atomic_read(&(server)->dentry_ttl) -#define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server)) - -static inline void -ncp_age_dentry(struct ncp_server* server, struct dentry* dentry) -{ - dentry->d_time = jiffies - NCP_MAX_AGE(server); -} - -static inline void -ncp_new_dentry(struct dentry* dentry) -{ - dentry->d_time = jiffies; -} - -struct ncp_cache_head { - time_t mtime; - unsigned long time; /* cache age */ - unsigned long end; /* last valid fpos in cache */ - int eof; -}; - -#define NCP_DIRCACHE_SIZE ((int)(PAGE_SIZE/sizeof(struct dentry *))) -union ncp_dir_cache { - struct ncp_cache_head head; - struct dentry *dentry[NCP_DIRCACHE_SIZE]; -}; - -#define NCP_FIRSTCACHE_SIZE ((int)((NCP_DIRCACHE_SIZE * \ - sizeof(struct dentry *) - sizeof(struct ncp_cache_head)) / \ - sizeof(struct dentry *))) - -#define NCP_DIRCACHE_START (NCP_DIRCACHE_SIZE - NCP_FIRSTCACHE_SIZE) - -struct ncp_cache_control { - struct ncp_cache_head head; - struct page *page; - union ncp_dir_cache *cache; - unsigned long fpos, ofs; - int filled, valid, idx; -}; - -#endif /* _NCPLIB_H */ diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c deleted file mode 100644 index 8085b1a3ba47..000000000000 --- a/fs/ncpfs/ncpsign_kernel.c +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ncpsign_kernel.c - * - * Arne de Bruijn (arne@knoware.nl), 1997 - * - */ - - -#ifdef CONFIG_NCPFS_PACKET_SIGNING - -#include -#include -#include -#include "ncp_fs.h" -#include "ncpsign_kernel.h" - -/* i386: 32-bit, little endian, handles mis-alignment */ -#ifdef __i386__ -#define GET_LE32(p) (*(const int *)(p)) -#define PUT_LE32(p,v) { *(int *)(p)=v; } -#else -/* from include/ncplib.h */ -#define BVAL(buf,pos) (((const __u8 *)(buf))[pos]) -#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) -#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val)) - -static inline __u16 -WVAL_LH(const __u8 * buf, int pos) -{ - return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8; -} -static inline __u32 -DVAL_LH(const __u8 * buf, int pos) -{ - return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16; -} -static inline void -WSET_LH(__u8 * buf, int pos, __u16 val) -{ - BSET(buf, pos, val & 0xff); - BSET(buf, pos + 1, val >> 8); -} -static inline void -DSET_LH(__u8 * buf, int pos, __u32 val) -{ - WSET_LH(buf, pos, val & 0xffff); - WSET_LH(buf, pos + 2, val >> 16); -} - -#define GET_LE32(p) DVAL_LH(p,0) -#define PUT_LE32(p,v) DSET_LH(p,0,v) -#endif - -static void nwsign(char *r_data1, char *r_data2, char *outdata) { - int i; - unsigned int w0,w1,w2,w3; - static int rbit[4]={0, 2, 1, 3}; -#ifdef __i386__ - unsigned int *data2=(unsigned int *)r_data2; -#else - unsigned int data2[16]; - for (i=0;i<16;i++) - data2[i]=GET_LE32(r_data2+(i<<2)); -#endif - w0=GET_LE32(r_data1); - w1=GET_LE32(r_data1+4); - w2=GET_LE32(r_data1+8); - w3=GET_LE32(r_data1+12); - for (i=0;i<16;i+=4) { - w0=rol32(w0 + ((w1 & w2) | ((~w1) & w3)) + data2[i+0],3); - w3=rol32(w3 + ((w0 & w1) | ((~w0) & w2)) + data2[i+1],7); - w2=rol32(w2 + ((w3 & w0) | ((~w3) & w1)) + data2[i+2],11); - w1=rol32(w1 + ((w2 & w3) | ((~w2) & w0)) + data2[i+3],19); - } - for (i=0;i<4;i++) { - w0=rol32(w0 + (((w2 | w3) & w1) | (w2 & w3)) + 0x5a827999 + data2[i+0],3); - w3=rol32(w3 + (((w1 | w2) & w0) | (w1 & w2)) + 0x5a827999 + data2[i+4],5); - w2=rol32(w2 + (((w0 | w1) & w3) | (w0 & w1)) + 0x5a827999 + data2[i+8],9); - w1=rol32(w1 + (((w3 | w0) & w2) | (w3 & w0)) + 0x5a827999 + data2[i+12],13); - } - for (i=0;i<4;i++) { - w0=rol32(w0 + ((w1 ^ w2) ^ w3) + 0x6ed9eba1 + data2[rbit[i]+0],3); - w3=rol32(w3 + ((w0 ^ w1) ^ w2) + 0x6ed9eba1 + data2[rbit[i]+8],9); - w2=rol32(w2 + ((w3 ^ w0) ^ w1) + 0x6ed9eba1 + data2[rbit[i]+4],11); - w1=rol32(w1 + ((w2 ^ w3) ^ w0) + 0x6ed9eba1 + data2[rbit[i]+12],15); - } - PUT_LE32(outdata,(w0+GET_LE32(r_data1)) & 0xffffffff); - PUT_LE32(outdata+4,(w1+GET_LE32(r_data1+4)) & 0xffffffff); - PUT_LE32(outdata+8,(w2+GET_LE32(r_data1+8)) & 0xffffffff); - PUT_LE32(outdata+12,(w3+GET_LE32(r_data1+12)) & 0xffffffff); -} - -/* Make a signature for the current packet and add it at the end of the */ -/* packet. */ -void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) { - unsigned char data[64]; - - memcpy(data, server->sign_root, 8); - *(__u32*)(data + 8) = totalsize; - if (size < 52) { - memcpy(data + 12, packet, size); - memset(data + 12 + size, 0, 52 - size); - } else { - memcpy(data + 12, packet, 52); - } - nwsign(server->sign_last, data, server->sign_last); - memcpy(sign_buff, server->sign_last, 8); -} - -int sign_verify_reply(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, const void *sign_buff) { - unsigned char data[64]; - unsigned char hash[16]; - - memcpy(data, server->sign_root, 8); - *(__u32*)(data + 8) = totalsize; - if (size < 52) { - memcpy(data + 12, packet, size); - memset(data + 12 + size, 0, 52 - size); - } else { - memcpy(data + 12, packet, 52); - } - nwsign(server->sign_last, data, hash); - return memcmp(sign_buff, hash, 8); -} - -#endif /* CONFIG_NCPFS_PACKET_SIGNING */ - diff --git a/fs/ncpfs/ncpsign_kernel.h b/fs/ncpfs/ncpsign_kernel.h deleted file mode 100644 index 57ff0a0650b8..000000000000 --- a/fs/ncpfs/ncpsign_kernel.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * ncpsign_kernel.h - * - * Arne de Bruijn (arne@knoware.nl), 1997 - * - */ - -#ifndef _NCPSIGN_KERNEL_H -#define _NCPSIGN_KERNEL_H - -#ifdef CONFIG_NCPFS_PACKET_SIGNING -void __sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff); -int sign_verify_reply(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, const void *sign_buff); -#endif - -static inline size_t sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff) { -#ifdef CONFIG_NCPFS_PACKET_SIGNING - if (server->sign_active) { - __sign_packet(server, data, size, totalsize, sign_buff); - return 8; - } -#endif - return 0; -} - -#endif diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c deleted file mode 100644 index efb176b1751a..000000000000 --- a/fs/ncpfs/sock.c +++ /dev/null @@ -1,854 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/fs/ncpfs/sock.c - * - * Copyright (C) 1992, 1993 Rick Sladkey - * - * Modified 1995, 1996 by Volker Lendecke to be usable for ncp - * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ncp_fs.h" - -#include "ncpsign_kernel.h" - -static int _recv(struct socket *sock, void *buf, int size, unsigned flags) -{ - struct msghdr msg = {NULL, }; - struct kvec iov = {buf, size}; - return kernel_recvmsg(sock, &msg, &iov, 1, size, flags); -} - -static int _send(struct socket *sock, const void *buff, int len) -{ - struct msghdr msg = { .msg_flags = 0 }; - struct kvec vec = {.iov_base = (void *)buff, .iov_len = len}; - iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &vec, 1, len); - return sock_sendmsg(sock, &msg); -} - -struct ncp_request_reply { - struct list_head req; - wait_queue_head_t wq; - atomic_t refs; - unsigned char* reply_buf; - size_t datalen; - int result; - enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status; - struct iov_iter from; - struct kvec tx_iov[3]; - u_int16_t tx_type; - u_int32_t sign[6]; -}; - -static inline struct ncp_request_reply* ncp_alloc_req(void) -{ - struct ncp_request_reply *req; - - req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL); - if (!req) - return NULL; - - init_waitqueue_head(&req->wq); - atomic_set(&req->refs, (1)); - req->status = RQ_IDLE; - - return req; -} - -static void ncp_req_get(struct ncp_request_reply *req) -{ - atomic_inc(&req->refs); -} - -static void ncp_req_put(struct ncp_request_reply *req) -{ - if (atomic_dec_and_test(&req->refs)) - kfree(req); -} - -void ncp_tcp_data_ready(struct sock *sk) -{ - struct ncp_server *server = sk->sk_user_data; - - server->data_ready(sk); - schedule_work(&server->rcv.tq); -} - -void ncp_tcp_error_report(struct sock *sk) -{ - struct ncp_server *server = sk->sk_user_data; - - server->error_report(sk); - schedule_work(&server->rcv.tq); -} - -void ncp_tcp_write_space(struct sock *sk) -{ - struct ncp_server *server = sk->sk_user_data; - - /* We do not need any locking: we first set tx.creq, and then we do sendmsg, - not vice versa... */ - server->write_space(sk); - if (server->tx.creq) - schedule_work(&server->tx.tq); -} - -void ncpdgram_timeout_call(struct timer_list *t) -{ - struct ncp_server *server = from_timer(server, t, timeout_tm); - - schedule_work(&server->timeout_tq); -} - -static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result) -{ - req->result = result; - if (req->status != RQ_ABANDONED) - memcpy(req->reply_buf, server->rxbuf, req->datalen); - req->status = RQ_DONE; - wake_up_all(&req->wq); - ncp_req_put(req); -} - -static void __abort_ncp_connection(struct ncp_server *server) -{ - struct ncp_request_reply *req; - - ncp_invalidate_conn(server); - del_timer(&server->timeout_tm); - while (!list_empty(&server->tx.requests)) { - req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); - - list_del_init(&req->req); - ncp_finish_request(server, req, -EIO); - } - req = server->rcv.creq; - if (req) { - server->rcv.creq = NULL; - ncp_finish_request(server, req, -EIO); - server->rcv.ptr = NULL; - server->rcv.state = 0; - } - req = server->tx.creq; - if (req) { - server->tx.creq = NULL; - ncp_finish_request(server, req, -EIO); - } -} - -static inline int get_conn_number(struct ncp_reply_header *rp) -{ - return rp->conn_low | (rp->conn_high << 8); -} - -static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) -{ - /* If req is done, we got signal, but we also received answer... */ - switch (req->status) { - case RQ_IDLE: - case RQ_DONE: - break; - case RQ_QUEUED: - list_del_init(&req->req); - ncp_finish_request(server, req, err); - break; - case RQ_INPROGRESS: - req->status = RQ_ABANDONED; - break; - case RQ_ABANDONED: - break; - } -} - -static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) -{ - mutex_lock(&server->rcv.creq_mutex); - __ncp_abort_request(server, req, err); - mutex_unlock(&server->rcv.creq_mutex); -} - -static inline void __ncptcp_abort(struct ncp_server *server) -{ - __abort_ncp_connection(server); -} - -static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) -{ - struct msghdr msg = { .msg_iter = req->from, .msg_flags = MSG_DONTWAIT }; - return sock_sendmsg(sock, &msg); -} - -static void __ncptcp_try_send(struct ncp_server *server) -{ - struct ncp_request_reply *rq; - struct msghdr msg = { .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT }; - int result; - - rq = server->tx.creq; - if (!rq) - return; - - msg.msg_iter = rq->from; - result = sock_sendmsg(server->ncp_sock, &msg); - - if (result == -EAGAIN) - return; - - if (result < 0) { - pr_err("tcp: Send failed: %d\n", result); - __ncp_abort_request(server, rq, result); - return; - } - if (!msg_data_left(&msg)) { - server->rcv.creq = rq; - server->tx.creq = NULL; - return; - } - rq->from = msg.msg_iter; -} - -static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) -{ - req->status = RQ_INPROGRESS; - h->conn_low = server->connection; - h->conn_high = server->connection >> 8; - h->sequence = ++server->sequence; -} - -static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) -{ - size_t signlen, len = req->tx_iov[1].iov_len; - struct ncp_request_header *h = req->tx_iov[1].iov_base; - - ncp_init_header(server, req, h); - signlen = sign_packet(server, - req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, - len - sizeof(struct ncp_request_header) + 1, - cpu_to_le32(len), req->sign); - if (signlen) { - /* NCP over UDP appends signature */ - req->tx_iov[2].iov_base = req->sign; - req->tx_iov[2].iov_len = signlen; - } - iov_iter_kvec(&req->from, WRITE | ITER_KVEC, - req->tx_iov + 1, signlen ? 2 : 1, len + signlen); - server->rcv.creq = req; - server->timeout_last = server->m.time_out; - server->timeout_retries = server->m.retry_count; - ncpdgram_send(server->ncp_sock, req); - mod_timer(&server->timeout_tm, jiffies + server->m.time_out); -} - -#define NCP_TCP_XMIT_MAGIC (0x446D6454) -#define NCP_TCP_XMIT_VERSION (1) -#define NCP_TCP_RCVD_MAGIC (0x744E6350) - -static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) -{ - size_t signlen, len = req->tx_iov[1].iov_len; - struct ncp_request_header *h = req->tx_iov[1].iov_base; - - ncp_init_header(server, req, h); - signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, - len - sizeof(struct ncp_request_header) + 1, - cpu_to_be32(len + 24), req->sign + 4) + 16; - - req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC); - req->sign[1] = htonl(len + signlen); - req->sign[2] = htonl(NCP_TCP_XMIT_VERSION); - req->sign[3] = htonl(req->datalen + 8); - /* NCP over TCP prepends signature */ - req->tx_iov[0].iov_base = req->sign; - req->tx_iov[0].iov_len = signlen; - iov_iter_kvec(&req->from, WRITE | ITER_KVEC, - req->tx_iov, 2, len + signlen); - - server->tx.creq = req; - __ncptcp_try_send(server); -} - -static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) -{ - /* we copy the data so that we do not depend on the caller - staying alive */ - memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len); - req->tx_iov[1].iov_base = server->txbuf; - - if (server->ncp_sock->type == SOCK_STREAM) - ncptcp_start_request(server, req); - else - ncpdgram_start_request(server, req); -} - -static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req) -{ - mutex_lock(&server->rcv.creq_mutex); - if (!ncp_conn_valid(server)) { - mutex_unlock(&server->rcv.creq_mutex); - pr_err("tcp: Server died\n"); - return -EIO; - } - ncp_req_get(req); - if (server->tx.creq || server->rcv.creq) { - req->status = RQ_QUEUED; - list_add_tail(&req->req, &server->tx.requests); - mutex_unlock(&server->rcv.creq_mutex); - return 0; - } - __ncp_start_request(server, req); - mutex_unlock(&server->rcv.creq_mutex); - return 0; -} - -static void __ncp_next_request(struct ncp_server *server) -{ - struct ncp_request_reply *req; - - server->rcv.creq = NULL; - if (list_empty(&server->tx.requests)) { - return; - } - req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); - list_del_init(&req->req); - __ncp_start_request(server, req); -} - -static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) -{ - if (server->info_sock) { - struct msghdr msg = { .msg_flags = MSG_NOSIGNAL }; - __be32 hdr[2] = {cpu_to_be32(len + 8), cpu_to_be32(id)}; - struct kvec iov[2] = { - {.iov_base = hdr, .iov_len = 8}, - {.iov_base = (void *)data, .iov_len = len}, - }; - - iov_iter_kvec(&msg.msg_iter, ITER_KVEC | WRITE, - iov, 2, len + 8); - - sock_sendmsg(server->info_sock, &msg); - } -} - -void ncpdgram_rcv_proc(struct work_struct *work) -{ - struct ncp_server *server = - container_of(work, struct ncp_server, rcv.tq); - struct socket* sock; - - sock = server->ncp_sock; - - while (1) { - struct ncp_reply_header reply; - int result; - - result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT); - if (result < 0) { - break; - } - if (result >= sizeof(reply)) { - struct ncp_request_reply *req; - - if (reply.type == NCP_WATCHDOG) { - unsigned char buf[10]; - - if (server->connection != get_conn_number(&reply)) { - goto drop; - } - result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT); - if (result < 0) { - ncp_dbg(1, "recv failed with %d\n", result); - continue; - } - if (result < 10) { - ncp_dbg(1, "too short (%u) watchdog packet\n", result); - continue; - } - if (buf[9] != '?') { - ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]); - continue; - } - buf[9] = 'Y'; - _send(sock, buf, sizeof(buf)); - continue; - } - if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) { - result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT); - if (result < 0) { - continue; - } - info_server(server, 0, server->unexpected_packet.data, result); - continue; - } - mutex_lock(&server->rcv.creq_mutex); - req = server->rcv.creq; - if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && - server->connection == get_conn_number(&reply)))) { - if (reply.type == NCP_POSITIVE_ACK) { - server->timeout_retries = server->m.retry_count; - server->timeout_last = NCP_MAX_RPC_TIMEOUT; - mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT); - } else if (reply.type == NCP_REPLY) { - result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT); -#ifdef CONFIG_NCPFS_PACKET_SIGNING - if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { - if (result < 8 + 8) { - result = -EIO; - } else { - unsigned int hdrl; - - result -= 8; - hdrl = sock->sk->sk_family == AF_INET ? 8 : 6; - if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) { - pr_info("Signature violation\n"); - result = -EIO; - } - } - } -#endif - del_timer(&server->timeout_tm); - server->rcv.creq = NULL; - ncp_finish_request(server, req, result); - __ncp_next_request(server); - mutex_unlock(&server->rcv.creq_mutex); - continue; - } - } - mutex_unlock(&server->rcv.creq_mutex); - } -drop:; - _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT); - } -} - -static void __ncpdgram_timeout_proc(struct ncp_server *server) -{ - /* If timer is pending, we are processing another request... */ - if (!timer_pending(&server->timeout_tm)) { - struct ncp_request_reply* req; - - req = server->rcv.creq; - if (req) { - int timeout; - - if (server->m.flags & NCP_MOUNT_SOFT) { - if (server->timeout_retries-- == 0) { - __ncp_abort_request(server, req, -ETIMEDOUT); - return; - } - } - /* Ignore errors */ - ncpdgram_send(server->ncp_sock, req); - timeout = server->timeout_last << 1; - if (timeout > NCP_MAX_RPC_TIMEOUT) { - timeout = NCP_MAX_RPC_TIMEOUT; - } - server->timeout_last = timeout; - mod_timer(&server->timeout_tm, jiffies + timeout); - } - } -} - -void ncpdgram_timeout_proc(struct work_struct *work) -{ - struct ncp_server *server = - container_of(work, struct ncp_server, timeout_tq); - mutex_lock(&server->rcv.creq_mutex); - __ncpdgram_timeout_proc(server); - mutex_unlock(&server->rcv.creq_mutex); -} - -static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) -{ - int result; - - if (buffer) { - result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT); - } else { - static unsigned char dummy[1024]; - - if (len > sizeof(dummy)) { - len = sizeof(dummy); - } - result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT); - } - if (result < 0) { - return result; - } - if (result > len) { - pr_err("tcp: bug in recvmsg (%u > %zu)\n", result, len); - return -EIO; - } - return result; -} - -static int __ncptcp_rcv_proc(struct ncp_server *server) -{ - /* We have to check the result, so store the complete header */ - while (1) { - int result; - struct ncp_request_reply *req; - int datalen; - int type; - - while (server->rcv.len) { - result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len); - if (result == -EAGAIN) { - return 0; - } - if (result <= 0) { - req = server->rcv.creq; - if (req) { - __ncp_abort_request(server, req, -EIO); - } else { - __ncptcp_abort(server); - } - if (result < 0) { - pr_err("tcp: error in recvmsg: %d\n", result); - } else { - ncp_dbg(1, "tcp: EOF\n"); - } - return -EIO; - } - if (server->rcv.ptr) { - server->rcv.ptr += result; - } - server->rcv.len -= result; - } - switch (server->rcv.state) { - case 0: - if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) { - pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic)); - __ncptcp_abort(server); - return -EIO; - } - datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF; - if (datalen < 10) { - pr_err("tcp: Unexpected reply len %d\n", datalen); - __ncptcp_abort(server); - return -EIO; - } -#ifdef CONFIG_NCPFS_PACKET_SIGNING - if (server->sign_active) { - if (datalen < 18) { - pr_err("tcp: Unexpected reply len %d\n", datalen); - __ncptcp_abort(server); - return -EIO; - } - server->rcv.buf.len = datalen - 8; - server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1; - server->rcv.len = 8; - server->rcv.state = 4; - break; - } -#endif - type = ntohs(server->rcv.buf.type); -#ifdef CONFIG_NCPFS_PACKET_SIGNING -cont:; -#endif - if (type != NCP_REPLY) { - if (datalen - 8 <= sizeof(server->unexpected_packet.data)) { - *(__u16*)(server->unexpected_packet.data) = htons(type); - server->unexpected_packet.len = datalen - 8; - - server->rcv.state = 5; - server->rcv.ptr = server->unexpected_packet.data + 2; - server->rcv.len = datalen - 10; - break; - } - ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type); -skipdata2:; - server->rcv.state = 2; -skipdata:; - server->rcv.ptr = NULL; - server->rcv.len = datalen - 10; - break; - } - req = server->rcv.creq; - if (!req) { - ncp_dbg(1, "Reply without appropriate request\n"); - goto skipdata2; - } - if (datalen > req->datalen + 8) { - pr_err("tcp: Unexpected reply len %d (expected at most %zd)\n", datalen, req->datalen + 8); - server->rcv.state = 3; - goto skipdata; - } - req->datalen = datalen - 8; - ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY; - server->rcv.ptr = server->rxbuf + 2; - server->rcv.len = datalen - 10; - server->rcv.state = 1; - break; -#ifdef CONFIG_NCPFS_PACKET_SIGNING - case 4: - datalen = server->rcv.buf.len; - type = ntohs(server->rcv.buf.type2); - goto cont; -#endif - case 1: - req = server->rcv.creq; - if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { - if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) { - pr_err("tcp: Bad sequence number\n"); - __ncp_abort_request(server, req, -EIO); - return -EIO; - } - if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) { - pr_err("tcp: Connection number mismatch\n"); - __ncp_abort_request(server, req, -EIO); - return -EIO; - } - } -#ifdef CONFIG_NCPFS_PACKET_SIGNING - if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { - if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { - pr_err("tcp: Signature violation\n"); - __ncp_abort_request(server, req, -EIO); - return -EIO; - } - } -#endif - ncp_finish_request(server, req, req->datalen); - nextreq:; - __ncp_next_request(server); - case 2: - next:; - server->rcv.ptr = (unsigned char*)&server->rcv.buf; - server->rcv.len = 10; - server->rcv.state = 0; - break; - case 3: - ncp_finish_request(server, server->rcv.creq, -EIO); - goto nextreq; - case 5: - info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len); - goto next; - } - } -} - -void ncp_tcp_rcv_proc(struct work_struct *work) -{ - struct ncp_server *server = - container_of(work, struct ncp_server, rcv.tq); - - mutex_lock(&server->rcv.creq_mutex); - __ncptcp_rcv_proc(server); - mutex_unlock(&server->rcv.creq_mutex); -} - -void ncp_tcp_tx_proc(struct work_struct *work) -{ - struct ncp_server *server = - container_of(work, struct ncp_server, tx.tq); - - mutex_lock(&server->rcv.creq_mutex); - __ncptcp_try_send(server); - mutex_unlock(&server->rcv.creq_mutex); -} - -static int do_ncp_rpc_call(struct ncp_server *server, int size, - unsigned char* reply_buf, int max_reply_size) -{ - int result; - struct ncp_request_reply *req; - - req = ncp_alloc_req(); - if (!req) - return -ENOMEM; - - req->reply_buf = reply_buf; - req->datalen = max_reply_size; - req->tx_iov[1].iov_base = server->packet; - req->tx_iov[1].iov_len = size; - req->tx_type = *(u_int16_t*)server->packet; - - result = ncp_add_request(server, req); - if (result < 0) - goto out; - - if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) { - ncp_abort_request(server, req, -EINTR); - result = -EINTR; - goto out; - } - - result = req->result; - -out: - ncp_req_put(req); - - return result; -} - -/* - * We need the server to be locked here, so check! - */ - -static int ncp_do_request(struct ncp_server *server, int size, - void* reply, int max_reply_size) -{ - int result; - - if (server->lock == 0) { - pr_err("Server not locked!\n"); - return -EIO; - } - if (!ncp_conn_valid(server)) { - return -EIO; - } - { - sigset_t old_set; - unsigned long mask, flags; - - spin_lock_irqsave(¤t->sighand->siglock, flags); - old_set = current->blocked; - if (current->flags & PF_EXITING) - mask = 0; - else - mask = sigmask(SIGKILL); - if (server->m.flags & NCP_MOUNT_INTR) { - /* FIXME: This doesn't seem right at all. So, like, - we can't handle SIGINT and get whatever to stop? - What if we've blocked it ourselves? What about - alarms? Why, in fact, are we mucking with the - sigmask at all? -- r~ */ - if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL) - mask |= sigmask(SIGINT); - if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL) - mask |= sigmask(SIGQUIT); - } - siginitsetinv(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - - result = do_ncp_rpc_call(server, size, reply, max_reply_size); - - spin_lock_irqsave(¤t->sighand->siglock, flags); - current->blocked = old_set; - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - } - - ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result); - - return result; -} - -/* ncp_do_request assures that at least a complete reply header is - * received. It assumes that server->current_size contains the ncp - * request size - */ -int ncp_request2(struct ncp_server *server, int function, - void* rpl, int size) -{ - struct ncp_request_header *h; - struct ncp_reply_header* reply = rpl; - int result; - - h = (struct ncp_request_header *) (server->packet); - if (server->has_subfunction != 0) { - *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2); - } - h->type = NCP_REQUEST; - /* - * The server shouldn't know or care what task is making a - * request, so we always use the same task number. - */ - h->task = 2; /* (current->pid) & 0xff; */ - h->function = function; - - result = ncp_do_request(server, server->current_size, reply, size); - if (result < 0) { - ncp_dbg(1, "ncp_request_error: %d\n", result); - goto out; - } - server->completion = reply->completion_code; - server->conn_status = reply->connection_state; - server->reply_size = result; - server->ncp_reply_size = result - sizeof(struct ncp_reply_header); - - result = reply->completion_code; - - if (result != 0) - ncp_vdbg("completion code=%x\n", result); -out: - return result; -} - -int ncp_connect(struct ncp_server *server) -{ - struct ncp_request_header *h; - int result; - - server->connection = 0xFFFF; - server->sequence = 255; - - h = (struct ncp_request_header *) (server->packet); - h->type = NCP_ALLOC_SLOT_REQUEST; - h->task = 2; /* see above */ - h->function = 0; - - result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); - if (result < 0) - goto out; - server->connection = h->conn_low + (h->conn_high * 256); - result = 0; -out: - return result; -} - -int ncp_disconnect(struct ncp_server *server) -{ - struct ncp_request_header *h; - - h = (struct ncp_request_header *) (server->packet); - h->type = NCP_DEALLOC_SLOT_REQUEST; - h->task = 2; /* see above */ - h->function = 0; - - return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); -} - -void ncp_lock_server(struct ncp_server *server) -{ - mutex_lock(&server->mutex); - if (server->lock) - pr_warn("%s: was locked!\n", __func__); - server->lock = 1; -} - -void ncp_unlock_server(struct ncp_server *server) -{ - if (!server->lock) { - pr_warn("%s: was not locked!\n", __func__); - return; - } - server->lock = 0; - mutex_unlock(&server->mutex); -} diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c deleted file mode 100644 index b6e16da4837a..000000000000 --- a/fs/ncpfs/symlink.c +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/fs/ncpfs/symlink.c - * - * Code for allowing symbolic links on NCPFS (i.e. NetWare) - * Symbolic links are not supported on native NetWare, so we use an - * infrequently-used flag (Sh) and store a two-word magic header in - * the file to make sure we don't accidentally use a non-link file - * as a link. - * - * When using the NFS namespace, we set the mode to indicate a symlink and - * don't bother with the magic numbers. - * - * from linux/fs/ext2/symlink.c - * - * Copyright (C) 1998-99, Frank A. Vorstenbosch - * - * ncpfs symlink handling code - * NLS support (c) 1999 Petr Vandrovec - * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info - * - */ - - -#include - -#include -#include -#include -#include -#include -#include -#include "ncp_fs.h" - -/* these magic numbers must appear in the symlink file -- this makes it a bit - more resilient against the magic attributes being set on random files. */ - -#define NCP_SYMLINK_MAGIC0 cpu_to_le32(0x6c6d7973) /* "symlnk->" */ -#define NCP_SYMLINK_MAGIC1 cpu_to_le32(0x3e2d6b6e) - -/* ----- read a symbolic link ------------------------------------------ */ - -static int ncp_symlink_readpage(struct file *file, struct page *page) -{ - struct inode *inode = page->mapping->host; - int error, length, len; - char *link, *rawlink; - char *buf = kmap(page); - - error = -ENOMEM; - rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL); - if (!rawlink) - goto fail; - - if (ncp_make_open(inode,O_RDONLY)) - goto failEIO; - - error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, - 0,NCP_MAX_SYMLINK_SIZE,rawlink,&length); - - ncp_inode_close(inode); - /* Close file handle if no other users... */ - ncp_make_closed(inode); - if (error) - goto failEIO; - - if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) { - if (lengthvolNumber)) - kludge = 0; - else -#ifdef CONFIG_NCPFS_EXTRAS - if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS) - kludge = 1; - else -#endif - /* EPERM is returned by VFS if symlink procedure does not exist */ - return -EPERM; - - rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL); - if (!rawlink) - return -ENOMEM; - - if (kludge) { - mode = 0; - attr = aSHARED | aHIDDEN; - ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0; - ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1; - hdr = 8; - } else { - mode = S_IFLNK | S_IRWXUGO; - attr = 0; - hdr = 0; - } - - length = strlen(symname); - /* map to/from server charset, do not touch upper/lower case as - symlink can point out of ncp filesystem */ - outlen = NCP_MAX_SYMLINK_SIZE - hdr; - err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0); - if (err) - goto failfree; - - outlen += hdr; - - err = -EIO; - if (ncp_create_new(dir,dentry,mode,0,attr)) { - goto failfree; - } - - inode=d_inode(dentry); - - if (ncp_make_open(inode, O_WRONLY)) - goto failfree; - - if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, - 0, outlen, rawlink, &i) || i!=outlen) { - goto fail; - } - - ncp_inode_close(inode); - ncp_make_closed(inode); - kfree(rawlink); - return 0; -fail:; - ncp_inode_close(inode); - ncp_make_closed(inode); -failfree:; - kfree(rawlink); - return err; -} - -/* ----- EOF ----- */ -- cgit v1.2.3 From 612b5bac4e5bd8a28e8b6e7c0b47f85ad59dae43 Mon Sep 17 00:00:00 2001 From: Bharat Bhushan Date: Wed, 22 Nov 2017 13:18:43 +0530 Subject: staging: fsl-mc: use 32bits to support 64K size mc-portals As per APIs each mc-portal is of 64K size while currently 16bits (type u16) is used to store size of mc-portal. In these cases upper bit of portal size gets truncated. Signed-off-by: Bharat Bhushan Acked-By: Laurentiu Tudor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/include/mc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index 15db93d71f82..34d79a808b99 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -325,7 +325,7 @@ static inline void mc_cmd_read_api_version(struct mc_command *cmd, struct fsl_mc_io { struct device *dev; u16 flags; - u16 portal_size; + u32 portal_size; phys_addr_t portal_phys_addr; void __iomem *portal_virt_addr; struct fsl_mc_device *dpmcp_dev; -- cgit v1.2.3 From 59cf568ec938415c5115515f6ef52ca188a06910 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 7 Nov 2017 19:48:36 +0000 Subject: staging: rtl8712: remove redundant zero assignment to val32 Variable val32 is being assigned a zero value that is never read since val32 is being updated immediately afterwards. Remove this redundant assignment, cleans up clang warning: drivers/staging/rtl8712/hal_init.c:339:2: warning: Value stored to 'val32' is never read Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/hal_init.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index de832b0b5eec..2a3f0746ee2c 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -336,7 +336,6 @@ uint rtl8712_hal_init(struct _adapter *padapter) r8712_read32(padapter, RCR)); val32 = r8712_read32(padapter, RCR); r8712_write32(padapter, RCR, (val32 | BIT(25))); /* Append PHY status */ - val32 = 0; val32 = r8712_read32(padapter, 0x10250040); r8712_write32(padapter, 0x10250040, (val32 & 0x00FFFFFF)); /* for usb rx aggregation */ -- cgit v1.2.3 From 8d05bce217de06cba6f2600ed54a69304def9ab5 Mon Sep 17 00:00:00 2001 From: Luca Söthe Date: Sun, 12 Nov 2017 18:59:11 +0100 Subject: staging: pi433: Fixed coding style issues with braces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed a few new lines after enum and struct names because of the following bracket. Signed-off-by: Luca Söthe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/pi433/pi433_if.h | 3 +-- drivers/staging/pi433/rf69_enum.h | 57 +++++++++++++-------------------------- 2 files changed, 20 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/pi433/pi433_if.h b/drivers/staging/pi433/pi433_if.h index e6ed3cd9b2e2..fc842c48c33e 100644 --- a/drivers/staging/pi433/pi433_if.h +++ b/drivers/staging/pi433/pi433_if.h @@ -58,8 +58,7 @@ * NOTE: struct layout is the same in 64bit and 32bit userspace. */ #define PI433_TX_CFG_IOCTL_NR 0 -struct pi433_tx_cfg -{ +struct pi433_tx_cfg { __u32 frequency; __u16 bit_rate; __u32 dev_frequency; diff --git a/drivers/staging/pi433/rf69_enum.h b/drivers/staging/pi433/rf69_enum.h index fbfb59bd3f3d..86429aa66ad1 100644 --- a/drivers/staging/pi433/rf69_enum.h +++ b/drivers/staging/pi433/rf69_enum.h @@ -18,14 +18,12 @@ #ifndef RF69_ENUM_H #define RF69_ENUM_H -enum optionOnOff -{ +enum optionOnOff { optionOff, optionOn }; -enum mode -{ +enum mode { mode_sleep, standby, synthesizer, @@ -33,21 +31,18 @@ enum mode receive }; -enum dataMode -{ +enum dataMode { packet, continuous, continuousNoSync }; -enum modulation -{ +enum modulation { OOK, FSK }; -enum modShaping -{ +enum modShaping { shapingOff, shaping1_0, shaping0_5, @@ -56,8 +51,7 @@ enum modShaping shaping2BR }; -enum paRamp -{ +enum paRamp { ramp3400, ramp2000, ramp1000, @@ -76,14 +70,12 @@ enum paRamp ramp10 }; -enum antennaImpedance -{ +enum antennaImpedance { fiftyOhm, twohundretOhm }; -enum lnaGain -{ +enum lnaGain { automatic, max, maxMinus6, @@ -94,8 +86,7 @@ enum lnaGain undefined }; -enum dccPercent -{ +enum dccPercent { dcc16Percent, dcc8Percent, dcc4Percent, @@ -106,22 +97,19 @@ enum dccPercent dcc0_125Percent }; -enum mantisse -{ +enum mantisse { mantisse16, mantisse20, mantisse24 }; -enum thresholdType -{ +enum thresholdType { fixed, peak, average }; -enum thresholdStep -{ +enum thresholdStep { step_0_5db, step_1_0db, step_1_5db, @@ -132,8 +120,7 @@ enum thresholdStep step_6_0db }; -enum thresholdDecrement -{ +enum thresholdDecrement { dec_every8th, dec_every4th, dec_every2nd, @@ -144,8 +131,7 @@ enum thresholdDecrement dec_16times }; -enum flag -{ +enum flag { modeSwitchCompleted, readyToReceive, readyToSend, @@ -165,33 +151,28 @@ enum flag batteryLow }; -enum fifoFillCondition -{ +enum fifoFillCondition { afterSyncInterrupt, always }; -enum packetFormat -{ +enum packetFormat { packetLengthFix, packetLengthVar }; -enum txStartCondition -{ +enum txStartCondition { fifoLevel, fifoNotEmpty }; -enum addressFiltering -{ +enum addressFiltering { filteringOff, nodeAddress, nodeOrBroadcastAddress }; -enum dagc -{ +enum dagc { normalMode, improve, improve4LowModulationIndex -- cgit v1.2.3 From 57f8965af417f97ed3f8e3d5c62c3e812e1b19e0 Mon Sep 17 00:00:00 2001 From: Stefano Manni Date: Thu, 16 Nov 2017 20:45:26 +0100 Subject: staging: pi433: fixed signedness of 4th argument to kfifo_from_user sparse warning: incorrect type in initializer (different signedness) expected unsigned int *__copied, got int * Signed-off-by: Stefano Manni Signed-off-by: Greg Kroah-Hartman --- drivers/staging/pi433/pi433_if.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index 2a205c6173dc..6f9ab3742bac 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -716,7 +716,8 @@ pi433_write(struct file *filp, const char __user *buf, { struct pi433_instance *instance; struct pi433_device *device; - int copied, retval; + int retval; + unsigned int copied; instance = filp->private_data; device = instance->device; -- cgit v1.2.3 From d2cb4845bfd1213e49a30682cec18c8825140153 Mon Sep 17 00:00:00 2001 From: Marcin Ciupak Date: Tue, 21 Nov 2017 00:03:57 +0100 Subject: staging: pi433: fix (NULL device *) in log message (NULL device *) is printed in log message in pi433_probe and pi433_get_minor functions due to device->dev being used prior to call to device_create function. Signed-off-by: Marcin Ciupak Signed-off-by: Greg Kroah-Hartman --- drivers/staging/pi433/pi433_if.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index 6f9ab3742bac..c9b5a56ee4d9 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -990,7 +990,7 @@ static int pi433_get_minor(struct pi433_device *device) device->minor = retval; retval = 0; } else if (retval == -ENOSPC) { - dev_err(device->dev, "too many pi433 devices\n"); + dev_err(&device->spi->dev, "too many pi433 devices\n"); retval = -EINVAL; } mutex_unlock(&minor_lock); @@ -1098,19 +1098,10 @@ static int pi433_probe(struct spi_device *spi) SET_CHECKED(rf69_set_output_power_level (spi, 13)); SET_CHECKED(rf69_set_antenna_impedance (spi, fiftyOhm)); - /* start tx thread */ - device->tx_task_struct = kthread_run(pi433_tx_thread, - device, - "pi433_tx_task"); - if (IS_ERR(device->tx_task_struct)) { - dev_dbg(device->dev, "start of send thread failed"); - goto send_thread_failed; - } - /* determ minor number */ retval = pi433_get_minor(device); if (retval) { - dev_dbg(device->dev, "get of minor number failed"); + dev_dbg(&spi->dev, "get of minor number failed"); goto minor_failed; } @@ -1133,6 +1124,15 @@ static int pi433_probe(struct spi_device *spi) device->minor); } + /* start tx thread */ + device->tx_task_struct = kthread_run(pi433_tx_thread, + device, + "pi433_tx_task"); + if (IS_ERR(device->tx_task_struct)) { + dev_dbg(device->dev, "start of send thread failed"); + goto send_thread_failed; + } + /* create cdev */ device->cdev = cdev_alloc(); device->cdev->owner = THIS_MODULE; @@ -1149,12 +1149,12 @@ static int pi433_probe(struct spi_device *spi) return 0; cdev_failed: + kthread_stop(device->tx_task_struct); +send_thread_failed: device_destroy(pi433_class, device->devt); device_create_failed: pi433_free_minor(device); minor_failed: - kthread_stop(device->tx_task_struct); -send_thread_failed: free_GPIOs(device); GPIO_failed: kfree(device); -- cgit v1.2.3 From 99ee477425c490d92d5824bdf7c1132c226765f4 Mon Sep 17 00:00:00 2001 From: Marcin Ciupak Date: Tue, 21 Nov 2017 00:05:50 +0100 Subject: staging: pi433: fix naming when more than one radio is used When using more than one hardware radio module pi433_probe fails as the same name is used for all modules. Create unique name by adding minor number to the device name. Signed-off-by: Marcin Ciupak Signed-off-by: Greg Kroah-Hartman --- drivers/staging/pi433/pi433_if.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index c9b5a56ee4d9..3e8e62b53603 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -1111,7 +1111,8 @@ static int pi433_probe(struct spi_device *spi) &spi->dev, device->devt, device, - "pi433"); + "pi433.%d", + device->minor); if (IS_ERR(device->dev)) { pr_err("pi433: device register failed\n"); retval = PTR_ERR(device->dev); @@ -1127,7 +1128,8 @@ static int pi433_probe(struct spi_device *spi) /* start tx thread */ device->tx_task_struct = kthread_run(pi433_tx_thread, device, - "pi433_tx_task"); + "pi433.%d_tx_task", + device->minor); if (IS_ERR(device->tx_task_struct)) { dev_dbg(device->dev, "start of send thread failed"); goto send_thread_failed; -- cgit v1.2.3 From 9be5755c4ae7ac2b5696493fcc706c7d4b81f525 Mon Sep 17 00:00:00 2001 From: Oliver Graute Date: Mon, 27 Nov 2017 18:34:01 +0100 Subject: staging: pi433: pi433_if.c fix codestyle on two long lines This patch fixes the following checkpatch.pl warning: WARNING: line over 80 characters #1233: FILE: pi433_if.c:1233: + unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); WARNING: line over 80 characters #1240: FILE: pi433_if.c:1240: + unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); Signed-off-by: Oliver Graute Signed-off-by: Greg Kroah-Hartman --- drivers/staging/pi433/pi433_if.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index 3e8e62b53603..196facc700f3 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -1233,14 +1233,16 @@ static int __init pi433_init(void) pi433_class = class_create(THIS_MODULE, "pi433"); if (IS_ERR(pi433_class)) { - unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); + unregister_chrdev(MAJOR(pi433_dev), + pi433_spi_driver.driver.name); return PTR_ERR(pi433_class); } status = spi_register_driver(&pi433_spi_driver); if (status < 0) { class_destroy(pi433_class); - unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); + unregister_chrdev(MAJOR(pi433_dev), + pi433_spi_driver.driver.name); } return status; -- cgit v1.2.3 From c976752e39988b0b8d7d4d7f06ed0f67582b4d46 Mon Sep 17 00:00:00 2001 From: Oliver Graute Date: Sun, 26 Nov 2017 21:07:10 +0100 Subject: staging: pi433: pi433_if.c codestyle fix This patch fixes the following checkpatch.pl error: ERROR: spaces required around that '>=' (ctx:VxV) #930: FILE: pi433_if.c:930: + for (i--; i>=0; i--) ERROR: spaces required around that '=' (ctx:VxV) #970: FILE: pi433_if.c:970: + for (i=0; i Signed-off-by: Greg Kroah-Hartman --- drivers/staging/pi433/pi433_if.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index 196facc700f3..3404cb9722c9 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -928,8 +928,7 @@ static int setup_GPIOs(struct pi433_device *device) { retval = PTR_ERR(device->gpiod[i]); /* release already allocated gpios */ - for (i--; i>=0; i--) - { + for (i--; i >= 0; i--) { free_irq(device->irq_num[i], device); gpiod_put(device->gpiod[i]); } @@ -968,7 +967,7 @@ static void free_GPIOs(struct pi433_device *device) { int i; - for (i=0; igpiod[i]) ) -- cgit v1.2.3 From c127e451a71b8cbe6c3d8fc946ab12b9d9c1bab1 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sat, 25 Nov 2017 12:09:29 +0530 Subject: staging: lustre: ldlm: Remove a attribute group from a kobject All attribute group created during ldlm_setup() should be removed in ldlm_cleanup(). Signed-off-by: Arvind Yadav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index 2d5a2c932ddc..ada50b69c5f6 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -1093,8 +1093,10 @@ static int ldlm_cleanup(void) kset_unregister(ldlm_ns_kset); if (ldlm_svc_kset) kset_unregister(ldlm_svc_kset); - if (ldlm_kobj) + if (ldlm_kobj) { + sysfs_remove_group(ldlm_kobj, &ldlm_attr_group); kobject_put(ldlm_kobj); + } ldlm_debugfs_cleanup(); -- cgit v1.2.3 From 4f3f073057341e02282cd500eee529522ecc8145 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sat, 25 Nov 2017 12:09:30 +0530 Subject: staging: lustre: obdclass: Remove a attribute group from a kobject All attribute group created during class_procfs_init() should be removed. if class_procfs_init() will fail and also in class_procfs_clean(). Signed-off-by: Arvind Yadav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index fc59f29a4290..57951237def2 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -501,6 +501,7 @@ int class_procfs_init(void) rc = debugfs_lustre_root ? PTR_ERR(debugfs_lustre_root) : -ENOMEM; debugfs_lustre_root = NULL; + sysfs_remove_group(lustre_kobj, &lustre_attr_group); kobject_put(lustre_kobj); goto out; } @@ -509,6 +510,7 @@ int class_procfs_init(void) &obd_device_list_fops); if (IS_ERR_OR_NULL(file)) { rc = file ? PTR_ERR(file) : -ENOMEM; + sysfs_remove_group(lustre_kobj, &lustre_attr_group); kobject_put(lustre_kobj); goto out; } @@ -522,6 +524,7 @@ int class_procfs_clean(void) debugfs_lustre_root = NULL; + sysfs_remove_group(lustre_kobj, &lustre_attr_group); kobject_put(lustre_kobj); return 0; -- cgit v1.2.3 From dcfe023858d94fc608cdec77910105ad7b8d6cce Mon Sep 17 00:00:00 2001 From: Talat Batheesh Date: Mon, 27 Nov 2017 15:36:58 +0200 Subject: staging: lustre: Fix line over 80 characters This patch fix the line over 80 characters warning that was detected using checkpatch.pl script. Signed-off-by: Talat Batheesh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/class_obd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 2985bca4dc4c..3e24b76f6301 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -377,7 +377,8 @@ static int obd_init_checks(void) char buf[64]; int len, ret = 0; - CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", "%llu", "%lld", "%#llx"); + CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", "%llu", "%lld", + "%#llx"); CDEBUG(D_INFO, "OBD_OBJECT_EOF = %#llx\n", (__u64)OBD_OBJECT_EOF); -- cgit v1.2.3 From 3eb23426e1749a0483bc4c9b18e51f657569e3ed Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 17 Nov 2017 14:50:55 +0000 Subject: staging: rtl8822be: fix missing null check on dev_alloc_skb return dev_alloc_skb can potentially return NULL, so add a null check to avoid a null pointer dereference on skb Detected by CoverityScan, CID#1454558 ("Dereference on null return") Fixes: 7e5b796cde7e ("staging: r8822be: Add the driver code") Signed-off-by: Colin Ian King Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtlwifi/rtl8822be/fw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c index f45487122517..483ea85943c3 100644 --- a/drivers/staging/rtlwifi/rtl8822be/fw.c +++ b/drivers/staging/rtlwifi/rtl8822be/fw.c @@ -464,6 +464,8 @@ bool rtl8822b_halmac_cb_write_data_rsvd_page(struct rtl_priv *rtlpriv, u8 *buf, int count; skb = dev_alloc_skb(size); + if (!skb) + return false; memcpy((u8 *)skb_put(skb, size), buf, size); if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE)) -- cgit v1.2.3 From f7de67f0876d27ef1b5d96c15e1e4870ffdf6cb5 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 22 Nov 2017 12:57:25 -0800 Subject: staging/irda/net: Drop extraneous parentheses around test Noticed during Clang builds. This drops the redundant parentheses. Cc: Samuel Ortiz Cc: Greg Kroah-Hartman Cc: devel@driverdev.osuosl.org Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/staging/irda/net/irlmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/irda/net/irlmp.c b/drivers/staging/irda/net/irlmp.c index 34355061ab0b..7af618fb66c0 100644 --- a/drivers/staging/irda/net/irlmp.c +++ b/drivers/staging/irda/net/irlmp.c @@ -1668,7 +1668,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel) IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, goto errlsap;); - if ((self->slsap_sel == slsap_sel)) { + if (self->slsap_sel == slsap_sel) { pr_debug("Source LSAP selector=%02x in use\n", self->slsap_sel); goto errlsap; @@ -1693,7 +1693,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel) self = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps); while (self != NULL) { IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, goto erruncon;); - if ((self->slsap_sel == slsap_sel)) { + if (self->slsap_sel == slsap_sel) { pr_debug("Source LSAP selector=%02x in use (unconnected)\n", self->slsap_sel); goto erruncon; -- cgit v1.2.3 From 1c0c275b11279a8305cf18a453e206d4891bbc48 Mon Sep 17 00:00:00 2001 From: Sinan Kaya Date: Mon, 27 Nov 2017 11:58:00 -0500 Subject: staging: rts5208: remove rtsx_read_pci_cfg_byte() Remove unused rtsx_read_pci_cfg_byte() function. Signed-off-by: Sinan Kaya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 17 ----------------- drivers/staging/rts5208/rtsx.h | 2 -- 2 files changed, 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 89e2cfe7d1cc..70e0b8623110 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -275,23 +275,6 @@ static int rtsx_acquire_irq(struct rtsx_dev *dev) return 0; } -int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val) -{ - struct pci_dev *pdev; - u8 data; - u8 devfn = (dev << 3) | func; - - pdev = pci_get_bus_and_slot(bus, devfn); - if (!pdev) - return -1; - - pci_read_config_byte(pdev, offset, &data); - if (val) - *val = data; - - return 0; -} - #ifdef CONFIG_PM /* * power management diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index 575e5734f2a5..62e467c5a6d7 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -174,8 +174,6 @@ static inline void get_current_time(u8 *timeval_buf, int buf_len) /* struct scsi_cmnd transfer buffer access utilities */ enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF}; -int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val); - #define _MSG_TRACE #include "trace.h" -- cgit v1.2.3 From a5eb2188f5c6cd81eede163157864484fb1d0e64 Mon Sep 17 00:00:00 2001 From: Tim Sell Date: Fri, 17 Nov 2017 12:27:38 -0500 Subject: staging: unisys: visorbus: address theoretical int overflows Add necessary casting to several places where we were doing 32-bit arithmetic (unsigned) to produce a 64-bit (unsigned long) result, to prevent the theoretical possibility of a 32-bit overflow during the arithmetic. FYI, these are unsigned long: ctx->param_bytes ctx->allocbytes These are unsigned int: bytes phdr->name_offset phdr->name_length Here is the test program demonstrating why we really need the casts: void main() { unsigned int i; unsigned long il; printf("sizeof(int) =%dn",sizeof(i)); printf("sizeof(long)=%dn",sizeof(il)); i = (unsigned int)((((unsigned long)(1)) << 32) - 1); printf("i = %un", i); il = i+1; printf("adding 1 withOUT cast = %lun", il); il = (unsigned long)i+1; printf("adding 1 WITH cast = %lun", il); } [selltc@mac tmp]$ gcc x.c -o x.out [selltc@mac tmp]$ ./x.out sizeof(int) =4 sizeof(long)=8 i = 4294967295 adding 1 withOUT cast = 0 adding 1 WITH cast = 4294967296 Signed-off-by: Tim Sell Reported-by: Dan Carpenter Signed-off-by: David Kershner Reviewed-by: David Binder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index a3fba96dd167..daff44d7a8c0 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -581,7 +581,8 @@ static void *parser_name_get(struct parser_context *ctx) struct visor_controlvm_parameters_header *phdr; phdr = &ctx->data; - if (phdr->name_offset + phdr->name_length > ctx->param_bytes) + if ((unsigned long)phdr->name_offset + + (unsigned long)phdr->name_length > ctx->param_bytes) return NULL; ctx->curr = (char *)&phdr + phdr->name_offset; ctx->bytes_remaining = phdr->name_length; @@ -1308,13 +1309,13 @@ static void parser_done(struct parser_context *ctx) static struct parser_context *parser_init_stream(u64 addr, u32 bytes, bool *retry) { - int allocbytes; + unsigned long allocbytes; struct parser_context *ctx; void *mapping; *retry = false; /* alloc an extra byte to ensure payload is \0 terminated */ - allocbytes = bytes + 1 + (sizeof(struct parser_context) - + allocbytes = (unsigned long)bytes + 1 + (sizeof(struct parser_context) - sizeof(struct visor_controlvm_parameters_header)); if ((chipset_dev->controlvm_payload_bytes_buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { -- cgit v1.2.3 From 8b075122ee84460496eef96f2099d00afab31f40 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Sat, 25 Nov 2017 12:09:28 +0530 Subject: staging: ccree: Remove a attribute group from a kobject All attribute group created during sys_init_dir() should be removed in sys_free_dir() Signed-off-by: Arvind Yadav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_sysfs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ccree/ssi_sysfs.c b/drivers/staging/ccree/ssi_sysfs.c index 656215b34231..08858a4e9d24 100644 --- a/drivers/staging/ccree/ssi_sysfs.c +++ b/drivers/staging/ccree/ssi_sysfs.c @@ -162,8 +162,11 @@ static void sys_free_dir(struct sys_dir *sys_dir) kfree(sys_dir->sys_dir_attr_list); - if (sys_dir->sys_dir_kobj) + if (sys_dir->sys_dir_kobj) { + sysfs_remove_group(sys_dir->sys_dir_kobj, + &sys_dir->sys_dir_attr_group); kobject_put(sys_dir->sys_dir_kobj); + } } int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata) -- cgit v1.2.3 From b76422771d3a3f63a111dc8f5e54a25f935d1e50 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Mon, 6 Nov 2017 16:59:44 +0100 Subject: staging: ion: reorder include Put include in alphabetic order Signed-off-by: Benjamin Gaignard Acked-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7630432a7de8..fa4b75f49859 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -5,28 +5,28 @@ * Copyright (C) 2011 Google, Inc. */ +#include +#include #include +#include #include +#include #include #include #include -#include +#include #include #include #include #include -#include #include #include #include -#include +#include #include +#include #include #include -#include -#include -#include -#include #include "ion.h" -- cgit v1.2.3 From 2124c8881eef4549d6b070a2aef3770cccaa5bd2 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Tue, 7 Nov 2017 03:58:29 -0500 Subject: usb: core: lower log level when device is not able to deal with string USB devices should work just fine when they don't support language id. Lower the log level so user won't panic in the future. BugLink: https://bugs.launchpad.net/bugs/1729618 Signed-off-by: Kai-Heng Feng Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 77001bcfc504..5a8ab77bc367 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -776,7 +776,7 @@ static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf) * deal with strings at all. Set string_langid to -1 in order to * prevent any string to be retrieved from the device */ if (err < 0) { - dev_err(&dev->dev, "string descriptor 0 read error: %d\n", + dev_info(&dev->dev, "string descriptor 0 read error: %d\n", err); dev->string_langid = -1; return -EPIPE; -- cgit v1.2.3 From 8a4821d0619ef6cf6b0fbfa466a213728d55b83b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 8 Nov 2017 13:46:36 +0000 Subject: USB: host: whci: remove redundant variable t Variable t is assigned but never read, it is redundant and therefore can be removed. Cleans up clang warning: drivers/usb/host/whci/asl.c:106:3: warning: Value stored to 't' is never read Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/whci/asl.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index c5ac9efb076a..276fb34c8efd 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c @@ -90,9 +90,7 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset) while (qset->ntds) { struct whc_qtd *td; - int t; - t = qset->td_start; td = &qset->qtd[qset->td_start]; status = le32_to_cpu(td->status); -- cgit v1.2.3 From 81d8a8eb0a975e151cdbd14f90516a8147d35ee2 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 22 Nov 2017 19:39:53 +0000 Subject: USB: usbip: fix spelling mistake: "synchronuously" -> "synchronously" Trivial fix to spelling mistake in error message text Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vhci_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c index 90577e8b2282..a9813f1d507d 100644 --- a/drivers/usb/usbip/vhci_rx.c +++ b/drivers/usb/usbip/vhci_rx.c @@ -31,7 +31,7 @@ struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum) /* fall through */ case -ECONNRESET: dev_info(&urb->dev->dev, - "urb %p was unlinked %ssynchronuously.\n", urb, + "urb %p was unlinked %ssynchronously.\n", urb, status == -ENOENT ? "" : "a"); break; case -EINPROGRESS: -- cgit v1.2.3 From cf140a3569714be6db8f3db56ba68c8554c108c9 Mon Sep 17 00:00:00 2001 From: Mats Karrman Date: Fri, 24 Nov 2017 00:03:16 +0100 Subject: typec: fusb302: Use dev_err during probe If probe fails, fusb302_debugfs_exit is called making it impossible to view any logs so use normal dev_err for any error messages during probe. Signed-off-by: Mats Karrman Reviewed-by: Guenter Roeck Acked-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/fusb302/fusb302.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 72cb060b3fca..4ce1df248c2f 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -1731,24 +1731,24 @@ static int init_gpio(struct fusb302_chip *chip) chip->gpio_int_n = of_get_named_gpio(node, "fcs,int_n", 0); if (!gpio_is_valid(chip->gpio_int_n)) { ret = chip->gpio_int_n; - fusb302_log(chip, "cannot get named GPIO Int_N, ret=%d", ret); + dev_err(chip->dev, "cannot get named GPIO Int_N, ret=%d", ret); return ret; } ret = devm_gpio_request(chip->dev, chip->gpio_int_n, "fcs,int_n"); if (ret < 0) { - fusb302_log(chip, "cannot request GPIO Int_N, ret=%d", ret); + dev_err(chip->dev, "cannot request GPIO Int_N, ret=%d", ret); return ret; } ret = gpio_direction_input(chip->gpio_int_n); if (ret < 0) { - fusb302_log(chip, - "cannot set GPIO Int_N to input, ret=%d", ret); + dev_err(chip->dev, + "cannot set GPIO Int_N to input, ret=%d", ret); return ret; } ret = gpio_to_irq(chip->gpio_int_n); if (ret < 0) { - fusb302_log(chip, - "cannot request IRQ for GPIO Int_N, ret=%d", ret); + dev_err(chip->dev, + "cannot request IRQ for GPIO Int_N, ret=%d", ret); return ret; } chip->gpio_int_n_irq = ret; @@ -1845,7 +1845,7 @@ static int fusb302_probe(struct i2c_client *client, chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); if (IS_ERR(chip->tcpm_port)) { ret = PTR_ERR(chip->tcpm_port); - fusb302_log(chip, "cannot register tcpm port, ret=%d", ret); + dev_err(dev, "cannot register tcpm port, ret=%d", ret); goto destroy_workqueue; } @@ -1854,8 +1854,7 @@ static int fusb302_probe(struct i2c_client *client, IRQF_ONESHOT | IRQF_TRIGGER_LOW, "fsc_interrupt_int_n", chip); if (ret < 0) { - fusb302_log(chip, - "cannot request IRQ for GPIO Int_N, ret=%d", ret); + dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret); goto tcpm_unregister_port; } enable_irq_wake(chip->gpio_int_n_irq); -- cgit v1.2.3 From ab69f61321140ff632d560775bc226259a78dfa2 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Tue, 21 Nov 2017 14:12:12 +0000 Subject: typec: tcpm: fusb302: Resolve out of order messaging events The expectation in the FUSB302 driver is that a TX_SUCCESS event should occur after a message has been sent, but before a GCRCSENT event is raised to indicate successful receipt of a message from the partner. However in some circumstances it is possible to see the hardware raise a GCRCSENT event before a TX_SUCCESS event is raised. The upshot of this is that the GCRCSENT handling portion of code ends up reporting the GoodCRC message to TCPM because the TX_SUCCESS event hasn't yet arrived to trigger a consumption of it. When TX_SUCCESS is then raised by the chip it ends up consuming the actual message that was meant for TCPM, and this incorrect sequence results in a hard reset from TCPM. To avoid this problem, this commit updates the message reading code to check whether a GoodCRC message was received or not. Based on this check it will either report that the previous transmission has completed or it will pass the msg data to TCPM for futher processing. This way the incorrect ordering of the events no longer matters. Signed-off-by: Adam Thomson Reviewed-by: Guenter Roeck Acked-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/fusb302/fusb302.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 4ce1df248c2f..1877edef6584 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -1543,6 +1543,21 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip, fusb302_log(chip, "PD message header: %x", msg->header); fusb302_log(chip, "PD message len: %d", len); + /* + * Check if we've read off a GoodCRC message. If so then indicate to + * TCPM that the previous transmission has completed. Otherwise we pass + * the received message over to TCPM for processing. + * + * We make this check here instead of basing the reporting decision on + * the IRQ event type, as it's possible for the chip to report the + * TX_SUCCESS and GCRCSENT events out of order on occasion, so we need + * to check the message type to ensure correct reporting to TCPM. + */ + if ((!len) && (pd_header_type_le(msg->header) == PD_CTRL_GOOD_CRC)) + tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); + else + tcpm_pd_receive(chip->tcpm_port, msg); + return ret; } @@ -1650,13 +1665,12 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) if (interrupta & FUSB_REG_INTERRUPTA_TX_SUCCESS) { fusb302_log(chip, "IRQ: PD tx success"); - /* read out the received good CRC */ ret = fusb302_pd_read_message(chip, &pd_msg); if (ret < 0) { - fusb302_log(chip, "cannot read in GCRC, ret=%d", ret); + fusb302_log(chip, + "cannot read in PD message, ret=%d", ret); goto done; } - tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); } if (interrupta & FUSB_REG_INTERRUPTA_HARDRESET) { @@ -1677,7 +1691,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) "cannot read in PD message, ret=%d", ret); goto done; } - tcpm_pd_receive(chip->tcpm_port, &pd_msg); } done: mutex_unlock(&chip->lock); -- cgit v1.2.3 From 1a7e3948cb9f5bb9241112706267b8fbc7812c7a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Nov 2017 18:07:21 +0100 Subject: USB: add device-tree support for interfaces Add OF device-tree support for USB interfaces. USB "interface nodes" are children of USB "device nodes" and are identified by an interface number and a configuration value: &usb1 { /* host controller */ dev1: device@1 { /* device at port 1 */ compatible = "usb1234,5678"; reg = <1>; #address-cells = <2>; #size-cells = <0>; interface@0,2 { /* interface 0 of configuration 2 */ compatible = "usbif1234,5678.config2.0"; reg = <0 2>; }; }; }; The configuration component is not included in the textual representation of an interface-node unit address for configuration 1: &dev1 { interface@0 { /* interface 0 of configuration 1 */ compatible = "usbif1234,5678.config1.0"; reg = <0 1>; }; }; When a USB device of class 0 or 9 (hub) has only a single configuration with a single interface, a special case "combined node" is used instead of a device node with an interface node: &usb1 { device@2 { compatible = "usb1234,abcd"; reg = <2>; }; }; Combined nodes are shared by the two device structures representing the USB device and its interface in the kernel's device model. Note that, as for device nodes, the compatible strings for interface nodes are currently not used. For more details see "Open Firmware Recommended Practice: Universal Serial Bus Version 1" and the binding documentation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 18 ++++++++---- drivers/usb/core/of.c | 70 +++++++++++++++++++++++++++++++++++++++++++++- include/linux/usb/of.h | 14 ++++++++++ 3 files changed, 96 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 5a8ab77bc367..f836bae1e485 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -18,6 +18,7 @@ #include #include #include /* for usbcore internals */ +#include #include #include "usb.h" @@ -1583,6 +1584,7 @@ static void usb_release_interface(struct device *dev) kref_put(&intfc->ref, usb_release_interface_cache); usb_put_dev(interface_to_usbdev(intf)); + of_node_put(dev->of_node); kfree(intf); } @@ -1868,6 +1870,7 @@ free_interfaces: struct usb_interface_cache *intfc; struct usb_interface *intf; struct usb_host_interface *alt; + u8 ifnum; cp->interface[i] = intf = new_interfaces[i]; intfc = cp->intf_cache[i]; @@ -1886,11 +1889,17 @@ free_interfaces: if (!alt) alt = &intf->altsetting[0]; - intf->intf_assoc = - find_iad(dev, cp, alt->desc.bInterfaceNumber); + ifnum = alt->desc.bInterfaceNumber; + intf->intf_assoc = find_iad(dev, cp, ifnum); intf->cur_altsetting = alt; usb_enable_interface(dev, intf, true); intf->dev.parent = &dev->dev; + if (usb_of_has_combined_node(dev)) { + device_set_of_node_from_dev(&intf->dev, &dev->dev); + } else { + intf->dev.of_node = usb_of_get_interface_node(dev, + configuration, ifnum); + } intf->dev.driver = NULL; intf->dev.bus = &usb_bus_type; intf->dev.type = &usb_if_device_type; @@ -1905,9 +1914,8 @@ free_interfaces: intf->minor = -1; device_initialize(&intf->dev); pm_runtime_no_callbacks(&intf->dev); - dev_set_name(&intf->dev, "%d-%s:%d.%d", - dev->bus->busnum, dev->devpath, - configuration, alt->desc.bInterfaceNumber); + dev_set_name(&intf->dev, "%d-%s:%d.%d", dev->bus->busnum, + dev->devpath, configuration, ifnum); usb_get_dev(dev); } kfree(new_interfaces); diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c index 2be968353257..074fabc26d6c 100644 --- a/drivers/usb/core/of.c +++ b/drivers/usb/core/of.c @@ -3,7 +3,8 @@ * of.c The helpers for hcd device tree support * * Copyright (C) 2016 Freescale Semiconductor, Inc. - * Author: Peter Chen + * Author: Peter Chen + * Copyright (C) 2017 Johan Hovold */ #include @@ -37,6 +38,73 @@ struct device_node *usb_of_get_child_node(struct device_node *parent, } EXPORT_SYMBOL_GPL(usb_of_get_child_node); +/** + * usb_of_has_combined_node() - determine whether a device has a combined node + * @udev: USB device + * + * Determine whether a USB device has a so called combined node which is + * shared with its sole interface. This is the case if and only if the device + * has a node and its decriptors report the following: + * + * 1) bDeviceClass is 0 or 9, and + * 2) bNumConfigurations is 1, and + * 3) bNumInterfaces is 1. + * + * Return: True iff the device has a device node and its descriptors match the + * criteria for a combined node. + */ +bool usb_of_has_combined_node(struct usb_device *udev) +{ + struct usb_device_descriptor *ddesc = &udev->descriptor; + struct usb_config_descriptor *cdesc; + + if (!udev->dev.of_node) + return false; + + switch (ddesc->bDeviceClass) { + case USB_CLASS_PER_INTERFACE: + case USB_CLASS_HUB: + if (ddesc->bNumConfigurations == 1) { + cdesc = &udev->config->desc; + if (cdesc->bNumInterfaces == 1) + return true; + } + } + + return false; +} +EXPORT_SYMBOL_GPL(usb_of_has_combined_node); + +/** + * usb_of_get_interface_node() - get a USB interface node + * @udev: USB device of interface + * @config: configuration value + * @ifnum: interface number + * + * Look up the node of a USB interface given its USB device, configuration + * value and interface number. + * + * Return: A pointer to the node with incremented refcount if found, or + * %NULL otherwise. + */ +struct device_node * +usb_of_get_interface_node(struct usb_device *udev, u8 config, u8 ifnum) +{ + struct device_node *node; + u32 reg[2]; + + for_each_child_of_node(udev->dev.of_node, node) { + if (of_property_read_u32_array(node, "reg", reg, 2)) + continue; + + if (reg[0] == ifnum && reg[1] == config) + return node; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(usb_of_get_interface_node); + /** * usb_of_get_companion_dev - Find the companion device * @dev: the device pointer to find a companion diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index 6cbe7a5c2b57..0294ccac4f1d 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h @@ -12,6 +12,8 @@ #include #include +struct usb_device; + #if IS_ENABLED(CONFIG_OF) enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0); bool of_usb_host_tpl_support(struct device_node *np); @@ -19,6 +21,9 @@ int of_usb_update_otg_caps(struct device_node *np, struct usb_otg_caps *otg_caps); struct device_node *usb_of_get_child_node(struct device_node *parent, int portnum); +bool usb_of_has_combined_node(struct usb_device *udev); +struct device_node *usb_of_get_interface_node(struct usb_device *udev, + u8 config, u8 ifnum); struct device *usb_of_get_companion_dev(struct device *dev); #else static inline enum usb_dr_mode @@ -40,6 +45,15 @@ static inline struct device_node *usb_of_get_child_node { return NULL; } +static inline bool usb_of_has_combined_node(struct usb_device *udev) +{ + return false; +} +static inline struct device_node * +usb_of_get_interface_node(struct usb_device *udev, u8 config, u8 ifnum) +{ + return NULL; +} static inline struct device *usb_of_get_companion_dev(struct device *dev) { return NULL; -- cgit v1.2.3 From 03310a15484ab6a8f6d91bbf7fe486b17275c09a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Nov 2017 18:07:22 +0100 Subject: USB: ledtrig-usbport: fix of-node leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code looks up a USB device node from a given parent USB device but never dropped its reference to the returned node. As only the address of the node is used for a later matching, the reference can be dropped immediately. Note that this trigger implementation confuses the description of the USB device connected to a port with the port itself (which does not have a device-tree representation). Fixes: 4f04c210d031 ("usb: core: read USB ports from DT in the usbport LED trigger driver") Cc: Rafał Miłecki Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/ledtrig-usbport.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c index 9dbb429cd471..f1fde5165068 100644 --- a/drivers/usb/core/ledtrig-usbport.c +++ b/drivers/usb/core/ledtrig-usbport.c @@ -137,11 +137,17 @@ static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data, if (!led_np) return false; - /* Get node of port being added */ + /* + * Get node of port being added + * + * FIXME: This is really the device node of the connected device + */ port_np = usb_of_get_child_node(usb_dev->dev.of_node, port1); if (!port_np) return false; + of_node_put(port_np); + /* Amount of trigger sources for this LED */ count = of_count_phandle_with_args(led_np, "trigger-sources", "#trigger-source-cells"); -- cgit v1.2.3 From 7739376eb1ed68593805e5b4ed359123d0718549 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Nov 2017 18:07:23 +0100 Subject: USB: of: clean up device-node helper Clean up the USB device-node helper that is used to look up a device node given a parent hub device and a port number. Also pass in a struct usb_device as first argument to provide some type checking. Give the helper the more descriptive name usb_of_get_device_node(), which matches the new usb_of_get_interface_node() helper that is used to look up a second type of of child node from a USB device. Note that the terms "device node" and "interface node" are defined and used by the OF Recommended Practice for USB. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/ledtrig-usbport.c | 2 +- drivers/usb/core/of.c | 27 ++++++++++++++------------- drivers/usb/core/usb.c | 3 +-- include/linux/usb/of.h | 7 +++---- 4 files changed, 19 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c index f1fde5165068..d775ffea20c3 100644 --- a/drivers/usb/core/ledtrig-usbport.c +++ b/drivers/usb/core/ledtrig-usbport.c @@ -142,7 +142,7 @@ static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data, * * FIXME: This is really the device node of the connected device */ - port_np = usb_of_get_child_node(usb_dev->dev.of_node, port1); + port_np = usb_of_get_device_node(usb_dev, port1); if (!port_np) return false; diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c index 074fabc26d6c..fd77442c2d12 100644 --- a/drivers/usb/core/of.c +++ b/drivers/usb/core/of.c @@ -12,31 +12,32 @@ #include /** - * usb_of_get_child_node - Find the device node match port number - * @parent: the parent device node - * @portnum: the port number which device is connecting + * usb_of_get_device_node() - get a USB device node + * @hub: hub to which device is connected + * @port1: one-based index of port * - * Find the node from device tree according to its port number. + * Look up the node of a USB device given its parent hub device and one-based + * port number. * * Return: A pointer to the node with incremented refcount if found, or * %NULL otherwise. */ -struct device_node *usb_of_get_child_node(struct device_node *parent, - int portnum) +struct device_node *usb_of_get_device_node(struct usb_device *hub, int port1) { struct device_node *node; - u32 port; + u32 reg; - for_each_child_of_node(parent, node) { - if (!of_property_read_u32(node, "reg", &port)) { - if (port == portnum) - return node; - } + for_each_child_of_node(hub->dev.of_node, node) { + if (of_property_read_u32(node, "reg", ®)) + continue; + + if (reg == port1) + return node; } return NULL; } -EXPORT_SYMBOL_GPL(usb_of_get_child_node); +EXPORT_SYMBOL_GPL(usb_of_get_device_node); /** * usb_of_has_combined_node() - determine whether a device has a combined node diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 845286f08ab0..2f5fbc56a9dd 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -645,8 +645,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, raw_port = usb_hcd_find_raw_port_number(usb_hcd, port1); } - dev->dev.of_node = usb_of_get_child_node(parent->dev.of_node, - raw_port); + dev->dev.of_node = usb_of_get_device_node(parent, raw_port); /* hub driver sets up TT records */ } diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index 0294ccac4f1d..dba55ccb9b53 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h @@ -19,8 +19,7 @@ enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0); bool of_usb_host_tpl_support(struct device_node *np); int of_usb_update_otg_caps(struct device_node *np, struct usb_otg_caps *otg_caps); -struct device_node *usb_of_get_child_node(struct device_node *parent, - int portnum); +struct device_node *usb_of_get_device_node(struct usb_device *hub, int port1); bool usb_of_has_combined_node(struct usb_device *udev); struct device_node *usb_of_get_interface_node(struct usb_device *udev, u8 config, u8 ifnum); @@ -40,8 +39,8 @@ static inline int of_usb_update_otg_caps(struct device_node *np, { return 0; } -static inline struct device_node *usb_of_get_child_node - (struct device_node *parent, int portnum) +static inline struct device_node * +usb_of_get_device_node(struct usb_device *hub, int port1) { return NULL; } -- cgit v1.2.3 From df3d9a5b771fa40689bbbdf54bd575d2817fe028 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 10 Nov 2017 16:05:45 -0600 Subject: tty: vt: replace _manual_ swap with swap macro in set_selection Make use of the swap macro instead of _manually_ swapping values and remove unnecessary variable tmp. This makes the code easier to read and maintain. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/selection.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index af4da9507180..7851383fbd6c 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -186,11 +186,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t } if (ps > pe) /* make sel_start <= sel_end */ - { - int tmp = ps; - ps = pe; - pe = tmp; - } + swap(ps, pe); if (sel_cons != vc_cons[fg_console].d) { clear_selection(); -- cgit v1.2.3 From 98869f9f9e7dfca97de3505bcdfa1115abe9b893 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Thu, 9 Nov 2017 08:05:52 -0800 Subject: serdev: Make .remove in struct serdev_device_driver optional Using devres infrastructure it is possible to write a serdev driver that doesn't have any code that needs to be called as a part of .remove. Add code to make .remove optional. Cc: linux-kernel@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: Rob Herring Cc: cphealy@gmail.com Cc: Guenter Roeck Cc: Lucas Stach Cc: Nikita Yushchenko Cc: Lee Jones Cc: Greg Kroah-Hartman Cc: Pavel Machek Cc: Andy Shevchenko Cc: Johan Hovold Cc: Sebastian Reichel Acked-by: Rob Herring Reviewed-by: Sebastian Reichel Reviewed-by: Guenter Roeck Signed-off-by: Andrey Smirnov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 1bef39828ca7..34050b439c1f 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -268,8 +268,8 @@ static int serdev_drv_probe(struct device *dev) static int serdev_drv_remove(struct device *dev) { const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver); - - sdrv->remove(to_serdev_device(dev)); + if (sdrv->remove) + sdrv->remove(to_serdev_device(dev)); return 0; } -- cgit v1.2.3 From 525ba62c96abec9130b8edb877d1128864cee01c Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Thu, 9 Nov 2017 08:05:53 -0800 Subject: serdev: Introduce devm_serdev_device_open() Add code implementing managed version of serdev_device_open() for serdev device drivers that "open" the device during driver's lifecycle only once (e.g. opened in .probe() and closed in .remove()). Cc: linux-kernel@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: Rob Herring Cc: cphealy@gmail.com Cc: Guenter Roeck Cc: Lucas Stach Cc: Nikita Yushchenko Cc: Lee Jones Cc: Greg Kroah-Hartman Cc: Pavel Machek Cc: Andy Shevchenko Cc: Johan Hovold Cc: Sebastian Reichel Acked-by: Rob Herring Reviewed-by: Sebastian Reichel Reviewed-by: Guenter Roeck Signed-off-by: Andrey Smirnov Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-model/devres.txt | 3 +++ drivers/tty/serdev/core.c | 27 +++++++++++++++++++++++++++ include/linux/serdev.h | 1 + 3 files changed, 31 insertions(+) (limited to 'drivers') diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index c180045eb43b..7c1bb3d0c222 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -384,6 +384,9 @@ RESET devm_reset_control_get() devm_reset_controller_register() +SERDEV + devm_serdev_device_open() + SLAVE DMA ENGINE devm_acpi_dma_controller_register() diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 34050b439c1f..28133dbd2808 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -132,6 +132,33 @@ void serdev_device_close(struct serdev_device *serdev) } EXPORT_SYMBOL_GPL(serdev_device_close); +static void devm_serdev_device_release(struct device *dev, void *dr) +{ + serdev_device_close(*(struct serdev_device **)dr); +} + +int devm_serdev_device_open(struct device *dev, struct serdev_device *serdev) +{ + struct serdev_device **dr; + int ret; + + dr = devres_alloc(devm_serdev_device_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + ret = serdev_device_open(serdev); + if (ret) { + devres_free(dr); + return ret; + } + + *dr = serdev; + devres_add(dev, dr); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_serdev_device_open); + void serdev_device_write_wakeup(struct serdev_device *serdev) { complete(&serdev->write_comp); diff --git a/include/linux/serdev.h b/include/linux/serdev.h index e69402d4a8ae..9929063bd45d 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -193,6 +193,7 @@ static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl, int serdev_device_open(struct serdev_device *); void serdev_device_close(struct serdev_device *); +int devm_serdev_device_open(struct device *, struct serdev_device *); unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); void serdev_device_set_flow_control(struct serdev_device *, bool); int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t); -- cgit v1.2.3 From dc88922e0a2fab90c478fbea61880acef8a06a32 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 7 Nov 2017 11:56:56 +0000 Subject: tty: n_gsm: remove redundant pointer gsm Pointer gsm is assigned a value that is never read, hence it is redundant and can be removed. Cleans up clang warning: drivers/tty/n_gsm.c:2979:2: warning: Value stored to 'gsm' is never read Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 5131bdc9e765..48e791d95f76 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2955,7 +2955,6 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) static void gsmtty_close(struct tty_struct *tty, struct file *filp) { struct gsm_dlci *dlci = tty->driver_data; - struct gsm_mux *gsm; if (dlci == NULL) return; @@ -2964,7 +2963,6 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) mutex_lock(&dlci->mutex); gsm_destroy_network(dlci); mutex_unlock(&dlci->mutex); - gsm = dlci->gsm; if (tty_port_close_start(&dlci->port, tty, filp) == 0) return; gsm_dlci_begin_close(dlci); -- cgit v1.2.3 From c0f0b8c51f674d10981704563475020604214fae Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Fri, 17 Nov 2017 19:17:59 +0100 Subject: tty: serial: meson: remove duplicate "clear error" bit definition The "clear error" bit in the AML_UART_CONTROL register is defined twice. Remove the AML_UART_CLR_ERR definition and replace it with AML_UART_CLEAR_ERR. AML_UART_CLEAR_ERR was chosen to be kept since the datasheet's description for this bit is "Clear Error" (so developer's don't have to translate this to "CLR_ERR"). No functional changes intended. Signed-off-by: Martin Blumenstingl Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/meson_uart.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index daafe60175da..78b5d2d15a97 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -36,7 +36,6 @@ #define AML_UART_RX_EN BIT(13) #define AML_UART_TX_RST BIT(22) #define AML_UART_RX_RST BIT(23) -#define AML_UART_CLR_ERR BIT(24) #define AML_UART_RX_INT_EN BIT(27) #define AML_UART_TX_INT_EN BIT(28) #define AML_UART_DATA_LEN_MASK (0x03 << 20) @@ -263,10 +262,10 @@ static void meson_uart_reset(struct uart_port *port) u32 val; val = readl(port->membase + AML_UART_CONTROL); - val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); + val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR); writel(val, port->membase + AML_UART_CONTROL); - val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); + val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR); writel(val, port->membase + AML_UART_CONTROL); } @@ -276,9 +275,9 @@ static int meson_uart_startup(struct uart_port *port) int ret = 0; val = readl(port->membase + AML_UART_CONTROL); - val |= AML_UART_CLR_ERR; + val |= AML_UART_CLEAR_ERR; writel(val, port->membase + AML_UART_CONTROL); - val &= ~AML_UART_CLR_ERR; + val &= ~AML_UART_CLEAR_ERR; writel(val, port->membase + AML_UART_CONTROL); val |= (AML_UART_RX_EN | AML_UART_TX_EN); -- cgit v1.2.3 From 44137e400c8f8b4f8b0c834d0b156c44cebc6743 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Fri, 17 Nov 2017 19:18:00 +0100 Subject: tty: serial: meson: merge the two register sections for AML_UART_CONTROL In the code there are two separate sections which each describe some of the bits in the AML_UART_CONTROL register. Merge these into one section to make the code easier to read. No functional changes intended. Signed-off-by: Martin Blumenstingl Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/meson_uart.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 78b5d2d15a97..72d425579a4d 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -34,8 +34,15 @@ /* AML_UART_CONTROL bits */ #define AML_UART_TX_EN BIT(12) #define AML_UART_RX_EN BIT(13) +#define AML_UART_TWO_WIRE_EN BIT(15) +#define AML_UART_STOP_BIN_LEN_MASK (0x03 << 16) +#define AML_UART_STOP_BIN_1SB (0x00 << 16) +#define AML_UART_STOP_BIN_2SB (0x01 << 16) +#define AML_UART_PARITY_TYPE BIT(18) +#define AML_UART_PARITY_EN BIT(19) #define AML_UART_TX_RST BIT(22) #define AML_UART_RX_RST BIT(23) +#define AML_UART_CLEAR_ERR BIT(24) #define AML_UART_RX_INT_EN BIT(27) #define AML_UART_TX_INT_EN BIT(28) #define AML_UART_DATA_LEN_MASK (0x03 << 20) @@ -56,15 +63,6 @@ AML_UART_FRAME_ERR | \ AML_UART_TX_FIFO_WERR) -/* AML_UART_CONTROL bits */ -#define AML_UART_TWO_WIRE_EN BIT(15) -#define AML_UART_PARITY_TYPE BIT(18) -#define AML_UART_PARITY_EN BIT(19) -#define AML_UART_CLEAR_ERR BIT(24) -#define AML_UART_STOP_BIN_LEN_MASK (0x03 << 16) -#define AML_UART_STOP_BIN_1SB (0x00 << 16) -#define AML_UART_STOP_BIN_2SB (0x01 << 16) - /* AML_UART_MISC bits */ #define AML_UART_XMIT_IRQ(c) (((c) & 0xff) << 8) #define AML_UART_RECV_IRQ(c) ((c) & 0xff) -- cgit v1.2.3 From f859722a8f3f145b79c4371303f3d3ea7da5c4e0 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Fri, 17 Nov 2017 19:18:01 +0100 Subject: tty: serial: meson: fix typo in the "stop bit" register definition This simply fixes a typo in the preprocessor macros. No functional changes intended. Signed-off-by: Martin Blumenstingl Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/meson_uart.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 72d425579a4d..8a842591b37c 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -35,9 +35,9 @@ #define AML_UART_TX_EN BIT(12) #define AML_UART_RX_EN BIT(13) #define AML_UART_TWO_WIRE_EN BIT(15) -#define AML_UART_STOP_BIN_LEN_MASK (0x03 << 16) -#define AML_UART_STOP_BIN_1SB (0x00 << 16) -#define AML_UART_STOP_BIN_2SB (0x01 << 16) +#define AML_UART_STOP_BIT_LEN_MASK (0x03 << 16) +#define AML_UART_STOP_BIT_1SB (0x00 << 16) +#define AML_UART_STOP_BIT_2SB (0x01 << 16) #define AML_UART_PARITY_TYPE BIT(18) #define AML_UART_PARITY_EN BIT(19) #define AML_UART_TX_RST BIT(22) @@ -351,11 +351,11 @@ static void meson_uart_set_termios(struct uart_port *port, else val &= ~AML_UART_PARITY_TYPE; - val &= ~AML_UART_STOP_BIN_LEN_MASK; + val &= ~AML_UART_STOP_BIT_LEN_MASK; if (cflags & CSTOPB) - val |= AML_UART_STOP_BIN_2SB; + val |= AML_UART_STOP_BIT_2SB; else - val |= AML_UART_STOP_BIN_1SB; + val |= AML_UART_STOP_BIT_1SB; if (cflags & CRTSCTS) val &= ~AML_UART_TWO_WIRE_EN; -- cgit v1.2.3 From e73be92d82e6a842eda6adac339963a3560ca0e4 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 25 Nov 2017 00:40:49 +0100 Subject: serial: pl011: Drop duplicate loop counter pl011_fifo_to_tty() has two counters (max_count and fifotaken) for the same loop. One counter should suffice. This saves one subtraction per character read from the RX FIFO. Cc: Mathias Duckeck Cc: Phil Elwell Cc: Stefan Wahren Cc: Linus Walleij Cc: Russell King Signed-off-by: Lukas Wunner Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 04af8de8617e..7c8f9804f585 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -314,10 +314,9 @@ static void pl011_write(unsigned int val, const struct uart_amba_port *uap, static int pl011_fifo_to_tty(struct uart_amba_port *uap) { u16 status; - unsigned int ch, flag, max_count = 256; - int fifotaken = 0; + unsigned int ch, flag, fifotaken; - while (max_count--) { + for (fifotaken = 0; fifotaken != 256; fifotaken++) { status = pl011_read(uap, REG_FR); if (status & UART01x_FR_RXFE) break; @@ -326,7 +325,6 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) ch = pl011_read(uap, REG_DR) | UART_DUMMY_DR_RX; flag = TTY_NORMAL; uap->port.icount.rx++; - fifotaken++; if (unlikely(ch & UART_DR_ERROR)) { if (ch & UART011_DR_BE) { -- cgit v1.2.3 From d8dcbdd08c653d9a6754b3c775f13cb987fa91ec Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Tue, 28 Nov 2017 11:55:17 +0100 Subject: tty: moxa: Add support for CMSPAR The mode constants are taken from the GPL-2.0+ driver available in the driver section of the Moxa homepage. It is tested on a C320Turbo PCI card per logic analyzer and per a device which requires 9 bit character communication. The vendors driver supports CMSPAR unconditionally, so that all other available firmware versions seems to support mark/space parity modes as well. Signed-off-by: Lars Kanis Signed-off-by: Greg Kroah-Hartman --- drivers/tty/moxa.c | 17 +++++++++++------ drivers/tty/moxa.h | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 68cbc03aab4b..250a19f042d7 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1487,8 +1487,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term if (ts->c_iflag & IXANY) xany = 1; - /* Clear the features we don't support */ - ts->c_cflag &= ~CMSPAR; MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany); baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty)); if (baud == -1) @@ -1781,10 +1779,17 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, mode |= MX_STOP1; if (termio->c_cflag & PARENB) { - if (termio->c_cflag & PARODD) - mode |= MX_PARODD; - else - mode |= MX_PAREVEN; + if (termio->c_cflag & PARODD) { + if (termio->c_cflag & CMSPAR) + mode |= MX_PARMARK; + else + mode |= MX_PARODD; + } else { + if (termio->c_cflag & CMSPAR) + mode |= MX_PARSPACE; + else + mode |= MX_PAREVEN; + } } else mode |= MX_PARNONE; diff --git a/drivers/tty/moxa.h b/drivers/tty/moxa.h index 8ce89fd36c7b..563d2dce80b3 100644 --- a/drivers/tty/moxa.h +++ b/drivers/tty/moxa.h @@ -301,5 +301,7 @@ #define MX_PARNONE 0x00 #define MX_PAREVEN 0x40 #define MX_PARODD 0xC0 +#define MX_PARMARK 0xA0 +#define MX_PARSPACE 0x20 #endif -- cgit v1.2.3 From d3a96c94163b7c577f4505168d0041ce9ee32a96 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 25 Nov 2017 00:33:27 +0100 Subject: serial: pl011: Use cached copy of IMSC register Commit 075167ed71b7 ("drivers: PL011: replace UART_MIS reading with _RIS & _IMSC") amended this driver's interrupt handler to read the Raw Interrupt Status (RIS) and Interrupt Mask Set/Clear (IMSC) registers instead of the Masked Interrupt Status (MIS) register. The change was made to attain compatibility with SBSA UARTs which lack the MIS register. However the IMSC register is cached by the driver. Using the cached copy saves one register read per interrupt. I've tested this change successfully on a BCM2837 (Raspberry Pi CM3). Cc: Mathias Duckeck Cc: Phil Elwell Cc: Stefan Wahren Cc: Andre Przywara Cc: Mark Langsdorf Cc: Naresh Bhat Cc: Russell King Signed-off-by: Lukas Wunner Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 7c8f9804f585..4b40a5b449ee 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1480,12 +1480,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id) struct uart_amba_port *uap = dev_id; unsigned long flags; unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; - u16 imsc; int handled = 0; spin_lock_irqsave(&uap->port.lock, flags); - imsc = pl011_read(uap, REG_IMSC); - status = pl011_read(uap, REG_RIS) & imsc; + status = pl011_read(uap, REG_RIS) & uap->im; if (status) { do { check_apply_cts_event_workaround(uap); @@ -1509,7 +1507,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) if (pass_counter-- == 0) break; - status = pl011_read(uap, REG_RIS) & imsc; + status = pl011_read(uap, REG_RIS) & uap->im; } while (status != 0); handled = 1; } -- cgit v1.2.3 From 1f043572cbbee03f1de814e312f9dc11251fdc5a Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 16 Nov 2017 11:14:53 -0700 Subject: tty: serial: imx: remove imx_disable_rx_int Since imx_disable_rx_int is only called by imx_startup, let's integrate it into that function. Notice UCR2_ATEN is never set by the driver. The bit is still cleaned to make this patch a noop. Signed-off-by: Troy Kisky Acked-by: Uwe Kleine-Koenig Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e4b3d9123a03..16311a24b483 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -703,25 +703,6 @@ out: return IRQ_HANDLED; } -static void imx_disable_rx_int(struct imx_port *sport) -{ - unsigned long temp; - - /* disable the receiver ready and aging timer interrupts */ - temp = readl(sport->port.membase + UCR1); - temp &= ~(UCR1_RRDYEN); - writel(temp, sport->port.membase + UCR1); - - temp = readl(sport->port.membase + UCR2); - temp &= ~(UCR2_ATEN); - writel(temp, sport->port.membase + UCR2); - - /* disable the rx errors interrupts */ - temp = readl(sport->port.membase + UCR4); - temp &= ~UCR4_OREN; - writel(temp, sport->port.membase + UCR4); -} - static void clear_rx_errors(struct imx_port *sport); /* @@ -1252,18 +1233,21 @@ static int imx_startup(struct uart_port *port) if (sport->dma_is_inited && !sport->dma_is_enabled) imx_enable_dma(sport); - temp = readl(sport->port.membase + UCR1); - temp |= UCR1_RRDYEN | UCR1_UARTEN; + temp = readl(sport->port.membase + UCR1) & ~UCR1_RRDYEN; + if (!sport->dma_is_enabled) + temp |= UCR1_RRDYEN; + temp |= UCR1_UARTEN; if (sport->have_rtscts) temp |= UCR1_RTSDEN; writel(temp, sport->port.membase + UCR1); - temp = readl(sport->port.membase + UCR4); - temp |= UCR4_OREN; + temp = readl(sport->port.membase + UCR4) & ~UCR4_OREN; + if (!sport->dma_is_enabled) + temp |= UCR4_OREN; writel(temp, sport->port.membase + UCR4); - temp = readl(sport->port.membase + UCR2); + temp = readl(sport->port.membase + UCR2) & ~UCR2_ATEN; temp |= (UCR2_RXEN | UCR2_TXEN); if (!sport->have_rtscts) temp |= UCR2_IRTS; @@ -1297,10 +1281,8 @@ static int imx_startup(struct uart_port *port) * In our iMX53 the average delay for the first reception dropped from * approximately 35000 microseconds to 1000 microseconds. */ - if (sport->dma_is_enabled) { - imx_disable_rx_int(sport); + if (sport->dma_is_enabled) start_rx_dma(sport); - } spin_unlock_irqrestore(&sport->port.lock, flags); -- cgit v1.2.3 From 5cd2d8fc6c6bca979ac5dd8ad0e41153f1f982f9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 7 Nov 2017 23:54:17 +0200 Subject: iwlwifi: fix the ALIVE notification layout The ucode_major and ucode_minor were swapped. This has no practical consequences since those fields are not used. Same goes for umac_major and umac_minor which were only printed under certain debug flags. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/alive.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h index 3684a3e180e5..007bfe7656a4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h @@ -95,8 +95,8 @@ enum { #define IWL_ALIVE_FLG_RFKILL BIT(0) struct iwl_lmac_alive { - __le32 ucode_minor; __le32 ucode_major; + __le32 ucode_minor; u8 ver_subtype; u8 ver_type; u8 mac; @@ -113,8 +113,8 @@ struct iwl_lmac_alive { } __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */ struct iwl_umac_alive { - __le32 umac_minor; /* UMAC version: minor */ __le32 umac_major; /* UMAC version: major */ + __le32 umac_minor; /* UMAC version: minor */ __le32 error_info_addr; /* SRAM address for UMAC error log */ __le32 dbg_print_buff_addr; } __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */ -- cgit v1.2.3 From 9834781cc1ff2e6ce327d9a7ce4901ce30ec7644 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 Nov 2017 10:16:47 +0100 Subject: iwlwifi: mvm: remove superfluous flush_work() Since iwl_mvm_start_p2p_roc() is only called from iwl_mvm_roc(), which already flushes the same work item, doing it again in it is superfluous. Remove it and move the comment to the first one. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 ++++ drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 6 ------ 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 149d301e5e98..e0226d2315bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3192,6 +3192,10 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, duration, type); + /* + * Flush the done work, just in case it's still pending, so that + * the work it does can complete and we can accept new frames. + */ flush_work(&mvm->roc_done_wk); mutex_lock(&mvm->mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 4d0314912e94..d3b8cb1e20b6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -759,12 +759,6 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return -EBUSY; } - /* - * Flush the done work, just in case it's still pending, so that - * the work it does can complete and we can accept new frames. - */ - flush_work(&mvm->roc_done_wk); - time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); time_cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); -- cgit v1.2.3 From 2f7a3863191afc2c132854b7ffb1b867b4b9e8be Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 15 Nov 2017 15:07:34 +0200 Subject: iwlwifi: rename the temporary name of A000 to the official 22000 The family name A000 was just a place-holder when we didn't know what the official name would be yet. Now we know that the family name is 22000, so rename all occurrences accordingly. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/Makefile | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 216 +++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/cfg/a000.c | 216 --------------------- .../net/wireless/intel/iwlwifi/fw/api/commands.h | 2 +- drivers/net/wireless/intel/iwlwifi/fw/api/tx.h | 4 +- drivers/net/wireless/intel/iwlwifi/fw/smem.c | 8 +- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 20 +- drivers/net/wireless/intel/iwlwifi/iwl-fh.h | 12 +- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 6 +- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 10 +- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 36 ++-- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 4 +- 16 files changed, 272 insertions(+), 272 deletions(-) create mode 100644 drivers/net/wireless/intel/iwlwifi/cfg/22000.c delete mode 100644 drivers/net/wireless/intel/iwlwifi/cfg/a000.c (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index ff136f299a0a..e2c151ae8649 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -9,7 +9,7 @@ iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o iwlwifi-objs += pcie/ctxt-info.o pcie/trans-gen2.o pcie/tx-gen2.o iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o -iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/a000.o +iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o iwlwifi-objs += iwl-trans.o iwlwifi-objs += fw/notif-wait.o iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o fw/dbg.o diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c new file mode 100644 index 000000000000..7c08711a9f94 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -0,0 +1,216 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2015-2017 Intel Deutschland GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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. + * + * BSD LICENSE + * + * Copyright(c) 2015-2017 Intel Deutschland GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include +#include +#include "iwl-config.h" +#include "iwl-agn-hw.h" + +/* Highest firmware API version supported */ +#define IWL_22000_UCODE_API_MAX 34 + +/* Lowest firmware API version supported */ +#define IWL_22000_UCODE_API_MIN 24 + +/* NVM versions */ +#define IWL_22000_NVM_VERSION 0x0a1d +#define IWL_22000_TX_POWER_VERSION 0xffff /* meaningless */ + +/* Memory offsets and lengths */ +#define IWL_22000_DCCM_OFFSET 0x800000 /* LMAC1 */ +#define IWL_22000_DCCM_LEN 0x10000 /* LMAC1 */ +#define IWL_22000_DCCM2_OFFSET 0x880000 +#define IWL_22000_DCCM2_LEN 0x8000 +#define IWL_22000_SMEM_OFFSET 0x400000 +#define IWL_22000_SMEM_LEN 0xD0000 + +#define IWL_22000_JF_FW_PRE "iwlwifi-Qu-a0-jf-b0-" +#define IWL_22000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-" +#define IWL_22000_HR_CDB_FW_PRE "iwlwifi-QuIcp-z0-hrcdb-a0-" +#define IWL_22000_HR_F0_FW_PRE "iwlwifi-QuQnj-f0-hr-a0-" +#define IWL_22000_JF_B0_FW_PRE "iwlwifi-QuQnj-a0-jf-b0-" +#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-" + +#define IWL_22000_HR_MODULE_FIRMWARE(api) \ + IWL_22000_HR_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_22000_JF_MODULE_FIRMWARE(api) \ + IWL_22000_JF_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_22000_HR_F0_QNJ_MODULE_FIRMWARE(api) \ + IWL_22000_HR_F0_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(api) \ + IWL_22000_JF_B0_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \ + IWL_22000_HR_A0_FW_PRE "-" __stringify(api) ".ucode" + +#define NVM_HW_SECTION_NUM_FAMILY_22000 10 + +static const struct iwl_base_params iwl_22000_base_params = { + .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_22000, + .num_of_queues = 512, + .shadow_ram_support = true, + .led_compensation = 57, + .wd_timeout = IWL_LONG_WD_TIMEOUT, + .max_event_log_size = 512, + .shadow_reg_enable = true, + .pcie_l1_allowed = true, +}; + +static const struct iwl_ht_params iwl_22000_ht_params = { + .stbc = true, + .ldpc = true, + .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), +}; + +#define IWL_DEVICE_22000 \ + .ucode_api_max = IWL_22000_UCODE_API_MAX, \ + .ucode_api_min = IWL_22000_UCODE_API_MIN, \ + .device_family = IWL_DEVICE_FAMILY_22000, \ + .max_inst_size = IWL60_RTC_INST_SIZE, \ + .max_data_size = IWL60_RTC_DATA_SIZE, \ + .base_params = &iwl_22000_base_params, \ + .led_mode = IWL_LED_RF_STATE, \ + .nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_22000, \ + .non_shared_ant = ANT_A, \ + .dccm_offset = IWL_22000_DCCM_OFFSET, \ + .dccm_len = IWL_22000_DCCM_LEN, \ + .dccm2_offset = IWL_22000_DCCM2_OFFSET, \ + .dccm2_len = IWL_22000_DCCM2_LEN, \ + .smem_offset = IWL_22000_SMEM_OFFSET, \ + .smem_len = IWL_22000_SMEM_LEN, \ + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \ + .apmg_not_supported = true, \ + .mq_rx_supported = true, \ + .vht_mu_mimo_supported = true, \ + .mac_addr_from_csr = true, \ + .use_tfh = true, \ + .rf_id = true, \ + .gen2 = true, \ + .nvm_type = IWL_NVM_EXT, \ + .dbgc_supported = true, \ + .tx_cmd_queue_size = 32, \ + .min_umac_error_event_table = 0x400000 + +const struct iwl_cfg iwl22000_2ac_cfg_hr = { + .name = "Intel(R) Dual Band Wireless AC 22000", + .fw_name_pre = IWL_22000_HR_FW_PRE, + IWL_DEVICE_22000, + .ht_params = &iwl_22000_ht_params, + .nvm_ver = IWL_22000_NVM_VERSION, + .nvm_calib_ver = IWL_22000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, +}; + +const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb = { + .name = "Intel(R) Dual Band Wireless AC 22000", + .fw_name_pre = IWL_22000_HR_CDB_FW_PRE, + IWL_DEVICE_22000, + .ht_params = &iwl_22000_ht_params, + .nvm_ver = IWL_22000_NVM_VERSION, + .nvm_calib_ver = IWL_22000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, + .cdb = true, +}; + +const struct iwl_cfg iwl22000_2ac_cfg_jf = { + .name = "Intel(R) Dual Band Wireless AC 22000", + .fw_name_pre = IWL_22000_JF_FW_PRE, + IWL_DEVICE_22000, + .ht_params = &iwl_22000_ht_params, + .nvm_ver = IWL_22000_NVM_VERSION, + .nvm_calib_ver = IWL_22000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, +}; + +const struct iwl_cfg iwl22000_2ax_cfg_hr = { + .name = "Intel(R) Dual Band Wireless AX 22000", + .fw_name_pre = IWL_22000_HR_FW_PRE, + IWL_DEVICE_22000, + .ht_params = &iwl_22000_ht_params, + .nvm_ver = IWL_22000_NVM_VERSION, + .nvm_calib_ver = IWL_22000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, +}; + +const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_f0 = { + .name = "Intel(R) Dual Band Wireless AX 22000", + .fw_name_pre = IWL_22000_HR_F0_FW_PRE, + IWL_DEVICE_22000, + .ht_params = &iwl_22000_ht_params, + .nvm_ver = IWL_22000_NVM_VERSION, + .nvm_calib_ver = IWL_22000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, +}; + +const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0 = { + .name = "Intel(R) Dual Band Wireless AX 22000", + .fw_name_pre = IWL_22000_JF_B0_FW_PRE, + IWL_DEVICE_22000, + .ht_params = &iwl_22000_ht_params, + .nvm_ver = IWL_22000_NVM_VERSION, + .nvm_calib_ver = IWL_22000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, +}; + +const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = { + .name = "Intel(R) Dual Band Wireless AX 22000", + .fw_name_pre = IWL_22000_HR_A0_FW_PRE, + IWL_DEVICE_22000, + .ht_params = &iwl_22000_ht_params, + .nvm_ver = IWL_22000_NVM_VERSION, + .nvm_calib_ver = IWL_22000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, +}; + +MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_22000_HR_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/a000.c b/drivers/net/wireless/intel/iwlwifi/cfg/a000.c deleted file mode 100644 index ea8206515171..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/cfg/a000.c +++ /dev/null @@ -1,216 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2015-2017 Intel Deutschland GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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. - * - * BSD LICENSE - * - * Copyright(c) 2015-2017 Intel Deutschland GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include -#include -#include "iwl-config.h" -#include "iwl-agn-hw.h" - -/* Highest firmware API version supported */ -#define IWL_A000_UCODE_API_MAX 34 - -/* Lowest firmware API version supported */ -#define IWL_A000_UCODE_API_MIN 24 - -/* NVM versions */ -#define IWL_A000_NVM_VERSION 0x0a1d -#define IWL_A000_TX_POWER_VERSION 0xffff /* meaningless */ - -/* Memory offsets and lengths */ -#define IWL_A000_DCCM_OFFSET 0x800000 /* LMAC1 */ -#define IWL_A000_DCCM_LEN 0x10000 /* LMAC1 */ -#define IWL_A000_DCCM2_OFFSET 0x880000 -#define IWL_A000_DCCM2_LEN 0x8000 -#define IWL_A000_SMEM_OFFSET 0x400000 -#define IWL_A000_SMEM_LEN 0xD0000 - -#define IWL_A000_JF_FW_PRE "iwlwifi-Qu-a0-jf-b0-" -#define IWL_A000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-" -#define IWL_A000_HR_CDB_FW_PRE "iwlwifi-QuIcp-z0-hrcdb-a0-" -#define IWL_A000_HR_F0_FW_PRE "iwlwifi-QuQnj-f0-hr-a0-" -#define IWL_A000_JF_B0_FW_PRE "iwlwifi-QuQnj-a0-jf-b0-" -#define IWL_A000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-" - -#define IWL_A000_HR_MODULE_FIRMWARE(api) \ - IWL_A000_HR_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_A000_JF_MODULE_FIRMWARE(api) \ - IWL_A000_JF_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_A000_HR_F0_QNJ_MODULE_FIRMWARE(api) \ - IWL_A000_HR_F0_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_A000_JF_B0_QNJ_MODULE_FIRMWARE(api) \ - IWL_A000_JF_B0_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_A000_HR_A0_QNJ_MODULE_FIRMWARE(api) \ - IWL_A000_HR_A0_FW_PRE "-" __stringify(api) ".ucode" - -#define NVM_HW_SECTION_NUM_FAMILY_A000 10 - -static const struct iwl_base_params iwl_a000_base_params = { - .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_A000, - .num_of_queues = 512, - .shadow_ram_support = true, - .led_compensation = 57, - .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, - .shadow_reg_enable = true, - .pcie_l1_allowed = true, -}; - -static const struct iwl_ht_params iwl_a000_ht_params = { - .stbc = true, - .ldpc = true, - .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), -}; - -#define IWL_DEVICE_A000 \ - .ucode_api_max = IWL_A000_UCODE_API_MAX, \ - .ucode_api_min = IWL_A000_UCODE_API_MIN, \ - .device_family = IWL_DEVICE_FAMILY_A000, \ - .max_inst_size = IWL60_RTC_INST_SIZE, \ - .max_data_size = IWL60_RTC_DATA_SIZE, \ - .base_params = &iwl_a000_base_params, \ - .led_mode = IWL_LED_RF_STATE, \ - .nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_A000, \ - .non_shared_ant = ANT_A, \ - .dccm_offset = IWL_A000_DCCM_OFFSET, \ - .dccm_len = IWL_A000_DCCM_LEN, \ - .dccm2_offset = IWL_A000_DCCM2_OFFSET, \ - .dccm2_len = IWL_A000_DCCM2_LEN, \ - .smem_offset = IWL_A000_SMEM_OFFSET, \ - .smem_len = IWL_A000_SMEM_LEN, \ - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \ - .apmg_not_supported = true, \ - .mq_rx_supported = true, \ - .vht_mu_mimo_supported = true, \ - .mac_addr_from_csr = true, \ - .use_tfh = true, \ - .rf_id = true, \ - .gen2 = true, \ - .nvm_type = IWL_NVM_EXT, \ - .dbgc_supported = true, \ - .tx_cmd_queue_size = 32, \ - .min_umac_error_event_table = 0x400000 - -const struct iwl_cfg iwla000_2ac_cfg_hr = { - .name = "Intel(R) Dual Band Wireless AC a000", - .fw_name_pre = IWL_A000_HR_FW_PRE, - IWL_DEVICE_A000, - .ht_params = &iwl_a000_ht_params, - .nvm_ver = IWL_A000_NVM_VERSION, - .nvm_calib_ver = IWL_A000_TX_POWER_VERSION, - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, -}; - -const struct iwl_cfg iwla000_2ac_cfg_hr_cdb = { - .name = "Intel(R) Dual Band Wireless AC a000", - .fw_name_pre = IWL_A000_HR_CDB_FW_PRE, - IWL_DEVICE_A000, - .ht_params = &iwl_a000_ht_params, - .nvm_ver = IWL_A000_NVM_VERSION, - .nvm_calib_ver = IWL_A000_TX_POWER_VERSION, - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, - .cdb = true, -}; - -const struct iwl_cfg iwla000_2ac_cfg_jf = { - .name = "Intel(R) Dual Band Wireless AC a000", - .fw_name_pre = IWL_A000_JF_FW_PRE, - IWL_DEVICE_A000, - .ht_params = &iwl_a000_ht_params, - .nvm_ver = IWL_A000_NVM_VERSION, - .nvm_calib_ver = IWL_A000_TX_POWER_VERSION, - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, -}; - -const struct iwl_cfg iwla000_2ax_cfg_hr = { - .name = "Intel(R) Dual Band Wireless AX a000", - .fw_name_pre = IWL_A000_HR_FW_PRE, - IWL_DEVICE_A000, - .ht_params = &iwl_a000_ht_params, - .nvm_ver = IWL_A000_NVM_VERSION, - .nvm_calib_ver = IWL_A000_TX_POWER_VERSION, - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, -}; - -const struct iwl_cfg iwla000_2ax_cfg_qnj_hr_f0 = { - .name = "Intel(R) Dual Band Wireless AX a000", - .fw_name_pre = IWL_A000_HR_F0_FW_PRE, - IWL_DEVICE_A000, - .ht_params = &iwl_a000_ht_params, - .nvm_ver = IWL_A000_NVM_VERSION, - .nvm_calib_ver = IWL_A000_TX_POWER_VERSION, - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, -}; - -const struct iwl_cfg iwla000_2ax_cfg_qnj_jf_b0 = { - .name = "Intel(R) Dual Band Wireless AX a000", - .fw_name_pre = IWL_A000_JF_B0_FW_PRE, - IWL_DEVICE_A000, - .ht_params = &iwl_a000_ht_params, - .nvm_ver = IWL_A000_NVM_VERSION, - .nvm_calib_ver = IWL_A000_TX_POWER_VERSION, - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, -}; - -const struct iwl_cfg iwla000_2ax_cfg_qnj_hr_a0 = { - .name = "Intel(R) Dual Band Wireless AX a000", - .fw_name_pre = IWL_A000_HR_A0_FW_PRE, - IWL_DEVICE_A000, - .ht_params = &iwl_a000_ht_params, - .nvm_ver = IWL_A000_NVM_VERSION, - .nvm_calib_ver = IWL_A000_TX_POWER_VERSION, - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, -}; - -MODULE_FIRMWARE(IWL_A000_HR_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_A000_JF_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_A000_HR_F0_QNJ_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_A000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_A000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 7ebbf097488b..f285bacc8726 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -215,7 +215,7 @@ enum iwl_legacy_cmds { /** * @SCD_QUEUE_CFG: &struct iwl_scd_txq_cfg_cmd for older hardware, * &struct iwl_tx_queue_cfg_cmd with &struct iwl_tx_queue_cfg_rsp - * for newer (A000) hardware. + * for newer (22000) hardware. */ SCD_QUEUE_CFG = 0x1d, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index f5d5ba7e37ec..a2a40b515a3c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -121,7 +121,7 @@ enum iwl_tx_flags { }; /* TX_FLAGS_BITS_API_S_VER_1 */ /** - * enum iwl_tx_cmd_flags - bitmasks for tx_flags in TX command for a000 + * enum iwl_tx_cmd_flags - bitmasks for tx_flags in TX command for 22000 * @IWL_TX_FLAGS_CMD_RATE: use rate from the TX command * @IWL_TX_FLAGS_ENCRYPT_DIS: frame should not be encrypted, even if it belongs * to a secured STA @@ -301,7 +301,7 @@ struct iwl_dram_sec_info { } __packed; /* DRAM_SEC_INFO_API_S_VER_1 */ /** - * struct iwl_tx_cmd_gen2 - TX command struct to FW for a000 devices + * struct iwl_tx_cmd_gen2 - TX command struct to FW for 22000 devices * ( TX_CMD = 0x1c ) * @len: in bytes of the payload, see below for details * @offload_assist: TX offload configuration diff --git a/drivers/net/wireless/intel/iwlwifi/fw/smem.c b/drivers/net/wireless/intel/iwlwifi/fw/smem.c index 76675736ba4f..fb4b6442b4d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/smem.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/smem.c @@ -63,8 +63,8 @@ #include "runtime.h" #include "fw/api/commands.h" -static void iwl_parse_shared_mem_a000(struct iwl_fw_runtime *fwrt, - struct iwl_rx_packet *pkt) +static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt, + struct iwl_rx_packet *pkt) { struct iwl_shared_mem_cfg *mem_cfg = (void *)pkt->data; int i, lmac; @@ -143,8 +143,8 @@ void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt) return; pkt = cmd.resp_pkt; - if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_A000) - iwl_parse_shared_mem_a000(fwrt, pkt); + if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_22000) + iwl_parse_shared_mem_22000(fwrt, pkt); else iwl_parse_shared_mem(fwrt, pkt); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index d1263a554420..9cc4647ded7e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -89,7 +89,7 @@ enum iwl_device_family { IWL_DEVICE_FAMILY_7000, IWL_DEVICE_FAMILY_8000, IWL_DEVICE_FAMILY_9000, - IWL_DEVICE_FAMILY_A000, + IWL_DEVICE_FAMILY_22000, }; /* @@ -266,7 +266,7 @@ struct iwl_tt_params { #define OTP_LOW_IMAGE_SIZE_FAMILY_7000 (16 * 512 * sizeof(u16)) /* 16 KB */ #define OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(u16)) /* 32 KB */ #define OTP_LOW_IMAGE_SIZE_FAMILY_9000 OTP_LOW_IMAGE_SIZE_FAMILY_8000 -#define OTP_LOW_IMAGE_SIZE_FAMILY_A000 OTP_LOW_IMAGE_SIZE_FAMILY_9000 +#define OTP_LOW_IMAGE_SIZE_FAMILY_22000 OTP_LOW_IMAGE_SIZE_FAMILY_9000 struct iwl_eeprom_params { const u8 regulatory_bands[7]; @@ -330,7 +330,7 @@ struct iwl_pwr_tx_backoff { * @vht_mu_mimo_supported: VHT MU-MIMO support * @rf_id: need to read rf_id to determine the firmware image * @integrated: discrete or integrated - * @gen2: a000 and on transport operation + * @gen2: 22000 and on transport operation * @cdb: CDB support * @nvm_type: see &enum iwl_nvm_type * @tx_cmd_queue_size: size of the cmd queue. If zero, use the same value as @@ -472,13 +472,13 @@ extern const struct iwl_cfg iwl9260_2ac_cfg; extern const struct iwl_cfg iwl9270_2ac_cfg; extern const struct iwl_cfg iwl9460_2ac_cfg; extern const struct iwl_cfg iwl9560_2ac_cfg; -extern const struct iwl_cfg iwla000_2ac_cfg_hr; -extern const struct iwl_cfg iwla000_2ac_cfg_hr_cdb; -extern const struct iwl_cfg iwla000_2ac_cfg_jf; -extern const struct iwl_cfg iwla000_2ax_cfg_hr; -extern const struct iwl_cfg iwla000_2ax_cfg_qnj_hr_f0; -extern const struct iwl_cfg iwla000_2ax_cfg_qnj_jf_b0; -extern const struct iwl_cfg iwla000_2ax_cfg_qnj_hr_a0; +extern const struct iwl_cfg iwl22000_2ac_cfg_hr; +extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; +extern const struct iwl_cfg iwl22000_2ac_cfg_jf; +extern const struct iwl_cfg iwl22000_2ax_cfg_hr; +extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_f0; +extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0; +extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0; #endif /* CONFIG_IWLMVM */ #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h index 66e5db41e559..11789ffb6512 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h @@ -121,7 +121,7 @@ #define FH_MEM_CBBC_16_19_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00) #define FH_MEM_CBBC_20_31_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xB20) #define FH_MEM_CBBC_20_31_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xB80) -/* a000 TFD table address, 64 bit */ +/* 22000 TFD table address, 64 bit */ #define TFH_TFDQ_CBB_TABLE (0x1C00) /* Find TFD CB base pointer for given queue */ @@ -140,7 +140,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans, return FH_MEM_CBBC_20_31_LOWER_BOUND + 4 * (chnl - 20); } -/* a000 configuration registers */ +/* 22000 configuration registers */ /* * TFH Configuration register. @@ -697,8 +697,8 @@ struct iwl_tfh_tb { * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM. * Both driver and device share these circular buffers, each of which must be * contiguous 256 TFDs. - * For pre a000 HW it is 256 x 128 bytes-per-TFD = 32 KBytes - * For a000 HW and on it is 256 x 256 bytes-per-TFD = 65 KBytes + * For pre 22000 HW it is 256 x 128 bytes-per-TFD = 32 KBytes + * For 22000 HW and on it is 256 x 256 bytes-per-TFD = 65 KBytes * * Driver must indicate the physical address of the base of each * circular buffer via the FH_MEM_CBBC_QUEUE registers. @@ -750,10 +750,10 @@ struct iwl_tfh_tfd { /** * struct iwlagn_schedq_bc_tbl scheduler byte count table * base physical address provided by SCD_DRAM_BASE_ADDR - * For devices up to a000: + * For devices up to 22000: * @tfd_offset 0-12 - tx command byte count * 12-16 - station index - * For a000 and on: + * For 22000 and on: * @tfd_offset 0-12 - tx command byte count * 12-13 - number of 64 byte chunks * 14-16 - reserved diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index ca0b5536a8a6..196b90b0451f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -549,7 +549,7 @@ struct iwl_trans_ops { unsigned int queue_wdg_timeout); void (*txq_disable)(struct iwl_trans *trans, int queue, bool configure_scd); - /* a000 functions */ + /* 22000 functions */ int (*txq_alloc)(struct iwl_trans *trans, struct iwl_tx_queue_cfg_cmd *cmd, int cmd_id, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index c0de7bb86cf7..3019ed9bccd2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -297,7 +297,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, if (ret) { struct iwl_trans *trans = mvm->trans; - if (trans->cfg->device_family == IWL_DEVICE_FAMILY_A000) + if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22000) IWL_ERR(mvm, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS), @@ -998,9 +998,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) goto error; /* Init RSS configuration */ - /* TODO - remove a000 disablement when we have RXQ config API */ + /* TODO - remove 22000 disablement when we have RXQ config API */ if (iwl_mvm_has_new_rx_api(mvm) && - mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_A000) { + mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_22000) { ret = iwl_send_rss_cfg_cmd(mvm); if (ret) { IWL_ERR(mvm, "Failed to configure RSS queues: %d\n", diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index e0226d2315bb..5a646dc6ad87 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -4281,7 +4281,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, mvm->trans->num_rx_queues); /* TODO - remove this when we have RXQ config API */ - if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_A000) { + if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_22000) { qmask = BIT(0); if (notif->sync) atomic_set(&mvm->queue_sync_counter, 1); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index bd6ba550c809..d556a1dd5e0d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1239,7 +1239,7 @@ static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm) static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm) { /* TODO - better define this */ - return mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_A000; + return mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000; } static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index c19f98489d4e..8351232472eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1760,7 +1760,7 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) } /* - * For a000 firmware and on we cannot add queue to a station unknown + * For 22000 firmware and on we cannot add queue to a station unknown * to firmware so enable queue here - after the station was added */ if (iwl_mvm_has_new_tx_api(mvm)) @@ -1858,7 +1858,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) return ret; /* - * For a000 firmware and on we cannot add queue to a station unknown + * For 22000 firmware and on we cannot add queue to a station unknown * to firmware so enable queue here - after the station was added */ if (iwl_mvm_has_new_tx_api(mvm)) { @@ -2037,7 +2037,7 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) /* * Enable cab queue after the ADD_STA command is sent. - * This is needed for a000 firmware which won't accept SCD_QUEUE_CFG + * This is needed for 22000 firmware which won't accept SCD_QUEUE_CFG * command with unknown station id, and for FW that doesn't support * station API since the cab queue is not included in the * tfd_queue_mask. @@ -2503,7 +2503,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, tid_data->next_reclaimed); /* - * In A000 HW, the next_reclaimed index is only 8 bit, so we'll need + * In 22000 HW, the next_reclaimed index is only 8 bit, so we'll need * to align the wrap around of ssn so we compare relevant values. */ normalized_ssn = tid_data->ssn; @@ -3588,7 +3588,7 @@ u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data) u16 sn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); /* - * In A000 HW, the next_reclaimed index is only 8 bit, so we'll need + * In 22000 HW, the next_reclaimed index is only 8 bit, so we'll need * to align the wrap around of ssn so we compare relevant values. */ if (mvm->trans->cfg->gen2) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 0407ea30bb82..e359e2538f9a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1131,7 +1131,7 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, } /* - * In A000 HW, the next_reclaimed index is only 8 bit, so we'll need + * In 22000 HW, the next_reclaimed index is only 8 bit, so we'll need * to align the wrap around of ssn so we compare relevant values. */ normalized_ssn = tid_data->ssn; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 4a21c12276d7..a0f5081f4355 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -577,19 +577,19 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA370, 0x0060, iwl9460_2ac_cfg)}, {IWL_PCI_DEVICE(0xA370, 0x1030, iwl9560_2ac_cfg)}, -/* a000 Series */ - {IWL_PCI_DEVICE(0x2720, 0x0A10, iwla000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x34F0, 0x0310, iwla000_2ac_cfg_jf)}, - {IWL_PCI_DEVICE(0x2720, 0x0000, iwla000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0070, iwla000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0078, iwla000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0070, iwla000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x2720, 0x0030, iwla000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x2720, 0x1080, iwla000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0090, iwla000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x2720, 0x0310, iwla000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x40C0, 0x0000, iwla000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwla000_2ax_cfg_hr)}, +/* 22000 Series */ + {IWL_PCI_DEVICE(0x2720, 0x0A10, iwl22000_2ac_cfg_hr_cdb)}, + {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22000_2ac_cfg_jf)}, + {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0078, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)}, + {IWL_PCI_DEVICE(0x2720, 0x0030, iwl22000_2ac_cfg_hr_cdb)}, + {IWL_PCI_DEVICE(0x2720, 0x1080, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)}, + {IWL_PCI_DEVICE(0x2720, 0x0310, iwl22000_2ac_cfg_hr_cdb)}, + {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22000_2ax_cfg_hr)}, #endif /* CONFIG_IWLMVM */ @@ -631,7 +631,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_trans->cfg = cfg_7265d; } - if (iwl_trans->cfg->rf_id && cfg == &iwla000_2ac_cfg_hr_cdb && + if (iwl_trans->cfg->rf_id && cfg == &iwl22000_2ac_cfg_hr_cdb && iwl_trans->hw_rev != CSR_HW_REV_TYPE_HR_CDB) { u32 rf_id_chp = CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id); u32 jf_chp_id = CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF); @@ -639,14 +639,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (rf_id_chp == jf_chp_id) { if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ) - cfg = &iwla000_2ax_cfg_qnj_jf_b0; + cfg = &iwl22000_2ax_cfg_qnj_jf_b0; else - cfg = &iwla000_2ac_cfg_jf; + cfg = &iwl22000_2ac_cfg_jf; } else if (rf_id_chp == hr_chp_id) { if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ) - cfg = &iwla000_2ax_cfg_qnj_hr_a0; + cfg = &iwl22000_2ax_cfg_qnj_hr_a0; else - cfg = &iwla000_2ac_cfg_hr; + cfg = &iwl22000_2ac_cfg_hr; } iwl_trans->cfg = cfg; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 8d992d5ba064..05e34a243042 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3240,9 +3240,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS); if (hw_status & UMAG_GEN_HW_IS_FPGA) - trans->cfg = &iwla000_2ax_cfg_qnj_hr_f0; + trans->cfg = &iwl22000_2ax_cfg_qnj_hr_f0; else - trans->cfg = &iwla000_2ac_cfg_hr; + trans->cfg = &iwl22000_2ac_cfg_hr; } #endif -- cgit v1.2.3 From 51899a63b42ee01df676b0624df4e81a517c3571 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 3 Nov 2017 15:30:57 +0100 Subject: serdev: ttyport: release tty lock sooner on open Release the tty lock once tty-driver open returns to make it clear that it does not protect neither tty->termios or the serport flags. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/serdev-ttyport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index ce7ad0acee7a..f76a8e044e4e 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -104,6 +104,8 @@ static int ttyport_open(struct serdev_controller *ctrl) if (ret) goto err_close; + tty_unlock(serport->tty); + /* Bring the UART into a known 8 bits no parity hw fc state */ ktermios = tty->termios; ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | @@ -117,7 +119,6 @@ static int ttyport_open(struct serdev_controller *ctrl) set_bit(SERPORT_ACTIVE, &serport->flags); - tty_unlock(serport->tty); return 0; err_close: -- cgit v1.2.3 From cda64188ca918fcddc8c6e89bbee5a38b029117a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 3 Nov 2017 15:30:58 +0100 Subject: serdev: ttyport: ignore carrier detect to avoid hangups Serdev currently does not support hangups so make sure to set CLOCAL to prevent loss of carrier from triggering one. Note however that not all tty drivers honour CLOCAL. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/serdev-ttyport.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index f76a8e044e4e..75f312ed96e8 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -115,6 +115,8 @@ static int ttyport_open(struct serdev_controller *ctrl) ktermios.c_cflag &= ~(CSIZE | PARENB); ktermios.c_cflag |= CS8; ktermios.c_cflag |= CRTSCTS; + /* Hangups are not supported so make sure to ignore carrier detect. */ + ktermios.c_cflag |= CLOCAL; tty_set_termios(tty, &ktermios); set_bit(SERPORT_ACTIVE, &serport->flags); -- cgit v1.2.3 From 743f93f822be1b54f3f9bd53d13f02192e65ce0b Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 24 Nov 2017 23:26:40 +0100 Subject: serial: Make retrieval of rs485 properties platform-agnostic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit ef838a81dd4d ("serial: Add common rs485 device tree parsing function") consolidated retrieval of rs485 OF properties in a common helper function but did not #ifdef it to CONFIG_OF. The function is therefore included on ACPI platforms as well even though it's not used. On the other hand ACPI platforms with rs485 do exist (e.g. Siemens IOT2040) and they may leverage _DSD to store rs485 properties. Likewise, UART platform devices instantiated from an MFD should be able to specify rs485 properties. In fact, the tty subsystem maintainer had asked for a "generic" function during review of commit ef838a81dd4d: https://marc.info/?l=linux-serial&m=150143441725194&w=4 Thus, instead of constraining the helper to OF platforms, make it platform-agnostic by converting it to device_property_*() functions and renaming it accordingly. In imx.c, move the invocation of uart_get_rs485_mode() from serial_imx_probe_dt() to serial_imx_probe() so that it also gets called for non-OF devices. In omap-serial.c, move its invocation further up within serial_omap_probe_rs485() so that the RTS polarity can be overridden with the driver-specific "rs485-rts-active-high" property once we introduce a generic "rs485-rts-active-low" property. Cc: Jan Kiszka Cc: Richard Genoud Cc: Sascha Hauer Signed-off-by: Lukas Wunner Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 2 +- drivers/tty/serial/fsl_lpuart.c | 2 +- drivers/tty/serial/imx.c | 4 ++-- drivers/tty/serial/omap-serial.c | 4 ++-- drivers/tty/serial/serial_core.c | 15 ++++++++------- include/linux/serial_core.h | 6 +----- 6 files changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index efa25611ca0c..df46a9e88c34 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2345,7 +2345,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, atmel_init_property(atmel_port, pdev); atmel_set_ops(port); - of_get_rs485_mode(pdev->dev.of_node, &port->rs485); + uart_get_rs485_mode(&pdev->dev, &port->rs485); port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 1c4d3f387138..38e76f95490e 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2206,7 +2206,7 @@ static int lpuart_probe(struct platform_device *pdev) if (ret) goto failed_attach_port; - of_get_rs485_mode(np, &sport->port.rs485); + uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) { dev_err(&pdev->dev, "driver doesn't support RX during TX\n"); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 16311a24b483..aca3b7dbd09c 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1999,8 +1999,6 @@ static int serial_imx_probe_dt(struct imx_port *sport, if (of_get_property(np, "rts-gpios", NULL)) sport->have_rtsgpio = 1; - of_get_rs485_mode(np, &sport->port.rs485); - return 0; } #else @@ -2093,6 +2091,8 @@ static int serial_imx_probe(struct platform_device *pdev) return ret; } + uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); + /* Disable interrupts before requesting them */ reg = readl_relaxed(sport->port.membase + UCR1); reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 53d59e9b944a..227347548fff 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1611,6 +1611,8 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, if (!np) return 0; + uart_get_rs485_mode(up->dev, rs485conf); + if (of_property_read_bool(np, "rs485-rts-active-high")) rs485conf->flags |= SER_RS485_RTS_ON_SEND; else @@ -1632,8 +1634,6 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, up->rts_gpio = -EINVAL; } - of_get_rs485_mode(np, rs485conf); - return 0; } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 854995e1cae7..a59184a7afb0 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3013,19 +3013,20 @@ EXPORT_SYMBOL(uart_add_one_port); EXPORT_SYMBOL(uart_remove_one_port); /** - * of_get_rs485_mode() - Implement parsing rs485 properties - * @np: uart node + * uart_get_rs485_mode() - retrieve rs485 properties for given uart + * @dev: uart device * @rs485conf: output parameter * * This function implements the device tree binding described in * Documentation/devicetree/bindings/serial/rs485.txt. */ -void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf) +void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) { u32 rs485_delay[2]; int ret; - ret = of_property_read_u32_array(np, "rs485-rts-delay", rs485_delay, 2); + ret = device_property_read_u32_array(dev, "rs485-rts-delay", + rs485_delay, 2); if (!ret) { rs485conf->delay_rts_before_send = rs485_delay[0]; rs485conf->delay_rts_after_send = rs485_delay[1]; @@ -3040,13 +3041,13 @@ void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf) */ rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED); - if (of_property_read_bool(np, "rs485-rx-during-tx")) + if (device_property_read_bool(dev, "rs485-rx-during-tx")) rs485conf->flags |= SER_RS485_RX_DURING_TX; - if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time")) + if (device_property_read_bool(dev, "linux,rs485-enabled-at-boot-time")) rs485conf->flags |= SER_RS485_ENABLED; } -EXPORT_SYMBOL_GPL(of_get_rs485_mode); +EXPORT_SYMBOL_GPL(uart_get_rs485_mode); MODULE_DESCRIPTION("Serial driver core"); MODULE_LICENSE("GPL"); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 37b044e78333..b60b225c0a59 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -501,9 +501,5 @@ static inline int uart_handle_break(struct uart_port *port) (cflag) & CRTSCTS || \ !((cflag) & CLOCAL)) -/* - * Common device tree parsing helpers - */ -void of_get_rs485_mode(struct device_node *np, struct serial_rs485 *rs485conf); - +void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf); #endif /* LINUX_SERIAL_CORE_H */ -- cgit v1.2.3 From f1e5b618c1c26cb8b5818e36f996e8c2fbedbeb7 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 24 Nov 2017 23:26:40 +0100 Subject: serial: core: Support common rs485 binding for RTS polarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a driver invokes the uart_get_rs485_mode() helper, set the RTS polarity to active high by default unless the newly introduced "rs485-rts-active-low" property was specified. imx contains a line to set the default RTS polarity to active high, it is now superfluous and hence deleted. omap-serial historically defaults to active low and supports an "rs485-rts-active-high" property to inverse the polarity. Retain that behavior for compatibility. Cc: Mark Jackson Cc: Michał Oleszczyk Cc: Rafael Gago Castano Cc: Sascha Hauer Signed-off-by: Lukas Wunner Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 1 - drivers/tty/serial/omap-serial.c | 7 +++++-- drivers/tty/serial/serial_core.c | 13 ++++++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index aca3b7dbd09c..d2c7d88d5774 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2060,7 +2060,6 @@ static int serial_imx_probe(struct platform_device *pdev) sport->port.fifosize = 32; sport->port.ops = &imx_pops; sport->port.rs485_config = imx_rs485_config; - sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND; sport->port.flags = UPF_BOOT_AUTOCONF; timer_setup(&sport->timer, imx_timeout, 0); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 227347548fff..56e683373d6d 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1613,10 +1613,13 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, uart_get_rs485_mode(up->dev, rs485conf); - if (of_property_read_bool(np, "rs485-rts-active-high")) + if (of_property_read_bool(np, "rs485-rts-active-high")) { rs485conf->flags |= SER_RS485_RTS_ON_SEND; - else + rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; + } else { + rs485conf->flags &= ~SER_RS485_RTS_ON_SEND; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + } /* check for tx enable gpio */ up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index a59184a7afb0..f57969de2f1c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3036,16 +3036,23 @@ void uart_get_rs485_mode(struct device *dev, struct serial_rs485 *rs485conf) } /* - * clear full-duplex and enabled flags to get to a defined state with - * the two following properties. + * Clear full-duplex and enabled flags, set RTS polarity to active high + * to get to a defined state with the following properties: */ - rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED); + rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED | + SER_RS485_RTS_AFTER_SEND); + rs485conf->flags |= SER_RS485_RTS_ON_SEND; if (device_property_read_bool(dev, "rs485-rx-during-tx")) rs485conf->flags |= SER_RS485_RX_DURING_TX; if (device_property_read_bool(dev, "linux,rs485-enabled-at-boot-time")) rs485conf->flags |= SER_RS485_ENABLED; + + if (device_property_read_bool(dev, "rs485-rts-active-low")) { + rs485conf->flags &= ~SER_RS485_RTS_ON_SEND; + rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + } } EXPORT_SYMBOL_GPL(uart_get_rs485_mode); -- cgit v1.2.3 From 01d845352a81df133234a106f34cc93937dcb7bd Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 24 Nov 2017 23:26:40 +0100 Subject: serial: fsl_lpuart: Support common rs485 binding for RTS polarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Invoke the ->rs485_config callback on probe to set UARTMODEM_TXRTSPOL appropriately based on the UART's device properties. This implicitly sets UARTMODEM_TXRTSE if rs485 was enabled in the device properties, so drop the identical code from lpuart_probe(). It also fixes a bug: If an unsupported rs485 property was specified (rs485-rx-during-tx or rs485-rts-delay), the driver returns -ENOSYS without performing any cleanup, in particular without calling uart_remove_one_port() or clk_disable_unprepare(), thus leaking the uart_port. But with the invocation of ->rs485_config, the unsupported properties are now cleared in struct serial_rs485 and thus ignored. It therefore seems sufficient to just log an error instead of bailing out. Cc: Sascha Hauer Signed-off-by: Lukas Wunner Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 38e76f95490e..8cf112f2efc3 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2208,21 +2208,14 @@ static int lpuart_probe(struct platform_device *pdev) uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); - if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) { + if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) dev_err(&pdev->dev, "driver doesn't support RX during TX\n"); - return -ENOSYS; - } if (sport->port.rs485.delay_rts_before_send || - sport->port.rs485.delay_rts_after_send) { + sport->port.rs485.delay_rts_after_send) dev_err(&pdev->dev, "driver doesn't support RTS delays\n"); - return -ENOSYS; - } - if (sport->port.rs485.flags & SER_RS485_ENABLED) { - sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND; - writeb(UARTMODEM_TXRTSE, sport->port.membase + UARTMODEM); - } + lpuart_config_rs485(&sport->port, &sport->port.rs485); sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx"); if (!sport->dma_tx_chan) -- cgit v1.2.3 From b8f3bff057b017309fbd61fe74712b1f185b5399 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 24 Nov 2017 23:26:40 +0100 Subject: serial: imx: Support common rs485 binding for RTS polarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Invoke the ->rs485_config callback on probe to adjust the initial RTS polarity based on the UART's device properties. This implicitly fixes a bug: If RTS control is not available, rs485 should be disabled even if it was enabled through a device property. Log an error when that occurs. Cc: Sascha Hauer Signed-off-by: Lukas Wunner Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index d2c7d88d5774..c2b29fd66e8a 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2092,6 +2092,12 @@ static int serial_imx_probe(struct platform_device *pdev) uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); + if (sport->port.rs485.flags & SER_RS485_ENABLED && + (!sport->have_rtscts || !sport->have_rtsgpio)) + dev_err(&pdev->dev, "no RTS control, disabling rs485\n"); + + imx_rs485_config(&sport->port, &sport->port.rs485); + /* Disable interrupts before requesting them */ reg = readl_relaxed(sport->port.membase + UCR1); reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | -- cgit v1.2.3 From 9c1c4b2753fea36a072e78a5efc82fca0d13b455 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:11 -0600 Subject: fpga: bridge: support getting bridge from device Add two functions for getting the FPGA bridge from the device rather than device tree node. This is to enable writing code that will support using FPGA bridges without device tree. Rename one old function to make it clear that it is device tree-ish. This leaves us with 3 functions for getting a bridge: * fpga_bridge_get Get the bridge given the device. * fpga_bridges_get_to_list Given the device, get the bridge and add it to a list. * of_fpga_bridges_get_to_list Renamed from priviously existing fpga_bridges_get_to_list. Given the device node, get the bridge and add it to a list. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-bridge.c | 110 +++++++++++++++++++++++++++++++-------- drivers/fpga/fpga-region.c | 11 ++-- include/linux/fpga/fpga-bridge.h | 12 +++-- 3 files changed, 103 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 9651aa56244a..0dfe9d78cee2 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -2,6 +2,7 @@ * FPGA Bridge Framework Driver * * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. + * Copyright (C) 2017 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -70,29 +71,12 @@ int fpga_bridge_disable(struct fpga_bridge *bridge) } EXPORT_SYMBOL_GPL(fpga_bridge_disable); -/** - * of_fpga_bridge_get - get an exclusive reference to a fpga bridge - * - * @np: node pointer of a FPGA bridge - * @info: fpga image specific information - * - * Return fpga_bridge struct if successful. - * Return -EBUSY if someone already has a reference to the bridge. - * Return -ENODEV if @np is not a FPGA Bridge. - */ -struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, - struct fpga_image_info *info) - +static struct fpga_bridge *__fpga_bridge_get(struct device *dev, + struct fpga_image_info *info) { - struct device *dev; struct fpga_bridge *bridge; int ret = -ENODEV; - dev = class_find_device(fpga_bridge_class, NULL, np, - fpga_bridge_of_node_match); - if (!dev) - goto err_dev; - bridge = to_fpga_bridge(dev); if (!bridge) goto err_dev; @@ -117,8 +101,58 @@ err_dev: put_device(dev); return ERR_PTR(ret); } + +/** + * of_fpga_bridge_get - get an exclusive reference to a fpga bridge + * + * @np: node pointer of a FPGA bridge + * @info: fpga image specific information + * + * Return fpga_bridge struct if successful. + * Return -EBUSY if someone already has a reference to the bridge. + * Return -ENODEV if @np is not a FPGA Bridge. + */ +struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, + struct fpga_image_info *info) +{ + struct device *dev; + + dev = class_find_device(fpga_bridge_class, NULL, np, + fpga_bridge_of_node_match); + if (!dev) + return ERR_PTR(-ENODEV); + + return __fpga_bridge_get(dev, info); +} EXPORT_SYMBOL_GPL(of_fpga_bridge_get); +static int fpga_bridge_dev_match(struct device *dev, const void *data) +{ + return dev->parent == data; +} + +/** + * fpga_bridge_get - get an exclusive reference to a fpga bridge + * @dev: parent device that fpga bridge was registered with + * + * Given a device, get an exclusive reference to a fpga bridge. + * + * Return: fpga manager struct or IS_ERR() condition containing error code. + */ +struct fpga_bridge *fpga_bridge_get(struct device *dev, + struct fpga_image_info *info) +{ + struct device *bridge_dev; + + bridge_dev = class_find_device(fpga_bridge_class, NULL, dev, + fpga_bridge_dev_match); + if (!bridge_dev) + return ERR_PTR(-ENODEV); + + return __fpga_bridge_get(bridge_dev, info); +} +EXPORT_SYMBOL_GPL(fpga_bridge_get); + /** * fpga_bridge_put - release a reference to a bridge * @@ -206,7 +240,7 @@ void fpga_bridges_put(struct list_head *bridge_list) EXPORT_SYMBOL_GPL(fpga_bridges_put); /** - * fpga_bridges_get_to_list - get a bridge, add it to a list + * of_fpga_bridge_get_to_list - get a bridge, add it to a list * * @np: node pointer of a FPGA bridge * @info: fpga image specific information @@ -216,14 +250,44 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put); * * Return 0 for success, error code from of_fpga_bridge_get() othewise. */ -int fpga_bridge_get_to_list(struct device_node *np, +int of_fpga_bridge_get_to_list(struct device_node *np, + struct fpga_image_info *info, + struct list_head *bridge_list) +{ + struct fpga_bridge *bridge; + unsigned long flags; + + bridge = of_fpga_bridge_get(np, info); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); + + spin_lock_irqsave(&bridge_list_lock, flags); + list_add(&bridge->node, bridge_list); + spin_unlock_irqrestore(&bridge_list_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(of_fpga_bridge_get_to_list); + +/** + * fpga_bridge_get_to_list - given device, get a bridge, add it to a list + * + * @dev: FPGA bridge device + * @info: fpga image specific information + * @bridge_list: list of FPGA bridges + * + * Get an exclusive reference to the bridge and and it to the list. + * + * Return 0 for success, error code from fpga_bridge_get() othewise. + */ +int fpga_bridge_get_to_list(struct device *dev, struct fpga_image_info *info, struct list_head *bridge_list) { struct fpga_bridge *bridge; unsigned long flags; - bridge = of_fpga_bridge_get(np, info); + bridge = fpga_bridge_get(dev, info); if (IS_ERR(bridge)) return PTR_ERR(bridge); @@ -381,7 +445,7 @@ static void __exit fpga_bridge_dev_exit(void) } MODULE_DESCRIPTION("FPGA Bridge Driver"); -MODULE_AUTHOR("Alan Tull "); +MODULE_AUTHOR("Alan Tull "); MODULE_LICENSE("GPL v2"); subsys_initcall(fpga_bridge_dev_init); diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index d9ab7c75b14f..9175556215b1 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -183,11 +183,14 @@ static int fpga_region_get_bridges(struct fpga_region *region, int i, ret; /* If parent is a bridge, add to list */ - ret = fpga_bridge_get_to_list(region_np->parent, region->info, - ®ion->bridge_list); + ret = of_fpga_bridge_get_to_list(region_np->parent, region->info, + ®ion->bridge_list); + + /* -EBUSY means parent is a bridge that is under use. Give up. */ if (ret == -EBUSY) return ret; + /* Zero return code means parent was a bridge and was added to list. */ if (!ret) parent_br = region_np->parent; @@ -207,8 +210,8 @@ static int fpga_region_get_bridges(struct fpga_region *region, continue; /* If node is a bridge, get it and add to list */ - ret = fpga_bridge_get_to_list(br, region->info, - ®ion->bridge_list); + ret = of_fpga_bridge_get_to_list(br, region->info, + ®ion->bridge_list); /* If any of the bridges are in use, give up */ if (ret == -EBUSY) { diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h index aa66c87c120b..6ca41f8f949f 100644 --- a/include/linux/fpga/fpga-bridge.h +++ b/include/linux/fpga/fpga-bridge.h @@ -1,10 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#include -#include #ifndef _LINUX_FPGA_BRIDGE_H #define _LINUX_FPGA_BRIDGE_H +#include +#include + struct fpga_bridge; /** @@ -43,6 +44,8 @@ struct fpga_bridge { struct fpga_bridge *of_fpga_bridge_get(struct device_node *node, struct fpga_image_info *info); +struct fpga_bridge *fpga_bridge_get(struct device *dev, + struct fpga_image_info *info); void fpga_bridge_put(struct fpga_bridge *bridge); int fpga_bridge_enable(struct fpga_bridge *bridge); int fpga_bridge_disable(struct fpga_bridge *bridge); @@ -50,9 +53,12 @@ int fpga_bridge_disable(struct fpga_bridge *bridge); int fpga_bridges_enable(struct list_head *bridge_list); int fpga_bridges_disable(struct list_head *bridge_list); void fpga_bridges_put(struct list_head *bridge_list); -int fpga_bridge_get_to_list(struct device_node *np, +int fpga_bridge_get_to_list(struct device *dev, struct fpga_image_info *info, struct list_head *bridge_list); +int of_fpga_bridge_get_to_list(struct device_node *np, + struct fpga_image_info *info, + struct list_head *bridge_list); int fpga_bridge_register(struct device *dev, const char *name, const struct fpga_bridge_ops *br_ops, void *priv); -- cgit v1.2.3 From 5cf0c7f6502f26332b46fa87914553a4d6ae75ac Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:12 -0600 Subject: fpga: mgr: API change to replace fpga load functions with single function fpga-mgr has three methods for programming FPGAs, depending on whether the image is in a scatter gather list, a contiguous buffer, or a firmware file. This makes it difficult to write upper layers as the caller has to assume whether the FPGA image is in a sg table, as a single buffer, or a firmware file. This commit moves these parameters to struct fpga_image_info and adds a single function for programming fpgas. New functions: * fpga_mgr_load - given fpga manager and struct fpga_image_info, program the fpga. * fpga_image_info_alloc - alloc a struct fpga_image_info. * fpga_image_info_free - free a struct fpga_image_info. These three functions are unexported: * fpga_mgr_buf_load_sg * fpga_mgr_buf_load * fpga_mgr_firmware_load Also use devm_kstrdup to copy firmware_name so we aren't making assumptions about where it comes from when allocing/freeing the struct fpga_image_info. API documentation has been updated and a new document for FPGA region has been added. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- Documentation/fpga/fpga-mgr.txt | 119 ++++++++++++++++--------------------- Documentation/fpga/fpga-region.txt | 95 +++++++++++++++++++++++++++++ Documentation/fpga/overview.txt | 23 +++++++ drivers/fpga/fpga-mgr.c | 68 +++++++++++++++++---- drivers/fpga/fpga-region.c | 43 +++++++++----- include/linux/fpga/fpga-mgr.h | 30 ++++++---- 6 files changed, 273 insertions(+), 105 deletions(-) create mode 100644 Documentation/fpga/fpga-region.txt create mode 100644 Documentation/fpga/overview.txt (limited to 'drivers') diff --git a/Documentation/fpga/fpga-mgr.txt b/Documentation/fpga/fpga-mgr.txt index 78f197fadfd1..6ebc714f4b03 100644 --- a/Documentation/fpga/fpga-mgr.txt +++ b/Documentation/fpga/fpga-mgr.txt @@ -11,61 +11,53 @@ hidden away in a low level driver which registers a set of ops with the core. The FPGA image data itself is very manufacturer specific, but for our purposes it's just binary data. The FPGA manager core won't parse it. +The FPGA image to be programmed can be in a scatter gather list, a single +contiguous buffer, or a firmware file. Because allocating contiguous kernel +memory for the buffer should be avoided, users are encouraged to use a scatter +gather list instead if possible. + +The particulars for programming the image are presented in a structure (struct +fpga_image_info). This struct contains parameters such as pointers to the +FPGA image as well as image-specific particulars such as whether the image was +built for full or partial reconfiguration. API Functions: ============== -To program the FPGA from a file or from a buffer: -------------------------------------------------- - - int fpga_mgr_buf_load(struct fpga_manager *mgr, - struct fpga_image_info *info, - const char *buf, size_t count); - -Load the FPGA from an image which exists as a contiguous buffer in -memory. Allocating contiguous kernel memory for the buffer should be avoided, -users are encouraged to use the _sg interface instead of this. - - int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, - struct fpga_image_info *info, - struct sg_table *sgt); +To program the FPGA: +-------------------- -Load the FPGA from an image from non-contiguous in memory. Callers can -construct a sg_table using alloc_page backed memory. + int fpga_mgr_load(struct fpga_manager *mgr, + struct fpga_image_info *info); - int fpga_mgr_firmware_load(struct fpga_manager *mgr, - struct fpga_image_info *info, - const char *image_name); - -Load the FPGA from an image which exists as a file. The image file must be on -the firmware search path (see the firmware class documentation). If successful, +Load the FPGA from an image which is indicated in the info. If successful, the FPGA ends up in operating mode. Return 0 on success or a negative error code. -A FPGA design contained in a FPGA image file will likely have particulars that -affect how the image is programmed to the FPGA. These are contained in struct -fpga_image_info. Currently the only such particular is a single flag bit -indicating whether the image is for full or partial reconfiguration. +To allocate or free a struct fpga_image_info: +--------------------------------------------- + + struct fpga_image_info *fpga_image_info_alloc(struct device *dev); + + void fpga_image_info_free(struct fpga_image_info *info); To get/put a reference to a FPGA manager: ----------------------------------------- struct fpga_manager *of_fpga_mgr_get(struct device_node *node); struct fpga_manager *fpga_mgr_get(struct device *dev); - -Given a DT node or device, get an exclusive reference to a FPGA manager. - void fpga_mgr_put(struct fpga_manager *mgr); -Release the reference. +Given a DT node or device, get an exclusive reference to a FPGA manager. +fpga_mgr_put releases the reference. To register or unregister the low level FPGA-specific driver: ------------------------------------------------------------- int fpga_mgr_register(struct device *dev, const char *name, - const struct fpga_manager_ops *mops, - void *priv); + const struct fpga_manager_ops *mops, + void *priv); void fpga_mgr_unregister(struct device *dev); @@ -78,59 +70,50 @@ How to write an image buffer to a supported FPGA /* Include to get the API */ #include -/* device node that specifies the FPGA manager to use */ -struct device_node *mgr_node = ... - -/* FPGA image is in this buffer. count is size of the buffer. */ -char *buf = ... -int count = ... +struct fpga_manager *mgr; +struct fpga_image_info *info; +int ret; /* struct with information about the FPGA image to program. */ -struct fpga_image_info info; +info = fpga_image_info_alloc(dev); /* flags indicates whether to do full or partial reconfiguration */ -info.flags = 0; - -int ret; +info->flags = FPGA_MGR_PARTIAL_RECONFIG; -/* Get exclusive control of FPGA manager */ -struct fpga_manager *mgr = of_fpga_mgr_get(mgr_node); +/* + * At this point, indicate where the image is. This is pseudo-code; you're + * going to use one of these three. + */ +if (image is in a scatter gather table) { -/* Load the buffer to the FPGA */ -ret = fpga_mgr_buf_load(mgr, &info, buf, count); - -/* Release the FPGA manager */ -fpga_mgr_put(mgr); + info->sgt = [your scatter gather table] +} else if (image is in a buffer) { -How to write an image file to a supported FPGA -============================================== -/* Include to get the API */ -#include + info->buf = [your image buffer] + info->count = [image buffer size] -/* device node that specifies the FPGA manager to use */ -struct device_node *mgr_node = ... +} else if (image is in a firmware file) { -/* FPGA image is in this file which is in the firmware search path */ -const char *path = "fpga-image-9.rbf" + info->firmware_name = devm_kstrdup(dev, firmware_name, GFP_KERNEL); -/* struct with information about the FPGA image to program. */ -struct fpga_image_info info; - -/* flags indicates whether to do full or partial reconfiguration */ -info.flags = 0; - -int ret; +} -/* Get exclusive control of FPGA manager */ -struct fpga_manager *mgr = of_fpga_mgr_get(mgr_node); +/* + * Get a reference to FPGA manager. This example uses the device node of the + * manager. You could use fpga_mgr_get() instead if you have the device instead + * of the device node. + */ +mgr = of_fpga_mgr_get(mgr_node); -/* Get the firmware image (path) and load it to the FPGA */ -ret = fpga_mgr_firmware_load(mgr, &info, path); +/* Load the buffer to the FPGA */ +ret = fpga_mgr_buf_load(mgr, &info, buf, count); /* Release the FPGA manager */ fpga_mgr_put(mgr); +/* Deallocate the image info if you're done with it */ +fpga_image_info_free(info); How to support a new FPGA device ================================ diff --git a/Documentation/fpga/fpga-region.txt b/Documentation/fpga/fpga-region.txt new file mode 100644 index 000000000000..139a02ba1ff6 --- /dev/null +++ b/Documentation/fpga/fpga-region.txt @@ -0,0 +1,95 @@ +FPGA Regions + +Alan Tull 2017 + +CONTENTS + - Introduction + - The FPGA region API + - Usage example + +Introduction +============ + +This document is meant to be an brief overview of the FPGA region API usage. A +more conceptual look at regions can be found in [1]. + +For the purposes of this API document, let's just say that a region associates +an FPGA Manager and a bridge (or bridges) with a reprogrammable region of an +FPGA or the whole FPGA. The API provides a way to register a region and to +program a region. + +Currently the only layer above fpga-region.c in the kernel is the Device Tree +support (of-fpga-region.c) described in [1]. The DT support layer uses regions +to program the FPGA and then DT to handle enumeration. The common region code +is intended to be used by other schemes that have other ways of accomplishing +enumeration after programming. + +An fpga-region can be set up to know the following things: +* which FPGA manager to use to do the programming +* which bridges to disable before programming and enable afterwards. + +Additional info needed to program the FPGA image is passed in the struct +fpga_image_info [2] including: +* pointers to the image as either a scatter-gather buffer, a contiguous + buffer, or the name of firmware file +* flags indicating specifics such as whether the image if for partial + reconfiguration. + +=================== +The FPGA region API +=================== + +To register or unregister a region: +----------------------------------- + + int fpga_region_register(struct device *dev, + struct fpga_region *region); + int fpga_region_unregister(struct fpga_region *region); + +An example of usage can be seen in the probe function of [3] + +To program an FPGA: +------------------- + int fpga_region_program_fpga(struct fpga_region *region); + +This function operates on info passed in the fpga_image_info +(region->info). + +This function will attempt to: + * lock the region's mutex + * lock the region's FPGA manager + * build a list of FPGA bridges if a method has been specified to do so + * disable the bridges + * program the FPGA + * re-enable the bridges + * release the locks + +============= +Usage example +============= + +First, allocate the info struct: + + info = fpga_image_info_alloc(dev); + if (!info) + return -ENOMEM; + +Set flags as needed, i.e. + + info->flags |= FPGA_MGR_PARTIAL_RECONFIG; + +Point to your FPGA image, such as: + + info->sgt = &sgt; + +Add info to region and do the programming: + + region->info = info; + ret = fpga_region_program_fpga(region); + +Then enumerate whatever hardware has appeared in the FPGA. + +-- +[1] ../devicetree/bindings/fpga/fpga-region.txt +[2] ./fpga-mgr.txt +[3] ../../drivers/fpga/of-fpga-region.c diff --git a/Documentation/fpga/overview.txt b/Documentation/fpga/overview.txt new file mode 100644 index 000000000000..0f1236e7e675 --- /dev/null +++ b/Documentation/fpga/overview.txt @@ -0,0 +1,23 @@ +Linux kernel FPGA support + +Alan Tull 2017 + +The main point of this project has been to separate the out the upper layers +that know when to reprogram a FPGA from the lower layers that know how to +reprogram a specific FPGA device. The intention is to make this manufacturer +agnostic, understanding that of course the FPGA images are very device specific +themselves. + +The framework in the kernel includes: +* low level FPGA manager drivers that know how to program a specific device +* the fpga-mgr framework they are registered with +* low level FPGA bridge drivers for hard/soft bridges which are intended to + be disable during FPGA programming +* the fpga-bridge framework they are registered with +* the fpga-region framework which associates and controls managers and bridges + as reconfigurable regions +* the of-fpga-region support for reprogramming FPGAs when device tree overlays + are applied. + +I would encourage you the user to add code that creates FPGA regions rather +that trying to control managers and bridges separately. diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 188ffefa3cc3..a8dd54945470 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -2,6 +2,7 @@ * FPGA Manager Core * * Copyright (C) 2013-2015 Altera Corporation + * Copyright (C) 2017 Intel Corporation * * With code from the mailing list: * Copyright (C) 2013 Xilinx, Inc. @@ -31,6 +32,40 @@ static DEFINE_IDA(fpga_mgr_ida); static struct class *fpga_mgr_class; +struct fpga_image_info *fpga_image_info_alloc(struct device *dev) +{ + struct fpga_image_info *info; + + get_device(dev); + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) { + put_device(dev); + return NULL; + } + + info->dev = dev; + + return info; +} +EXPORT_SYMBOL_GPL(fpga_image_info_alloc); + +void fpga_image_info_free(struct fpga_image_info *info) +{ + struct device *dev; + + if (!info) + return; + + dev = info->dev; + if (info->firmware_name) + devm_kfree(dev, info->firmware_name); + + devm_kfree(dev, info); + put_device(dev); +} +EXPORT_SYMBOL_GPL(fpga_image_info_free); + /* * Call the low level driver's write_init function. This will do the * device-specific things to get the FPGA into the state where it is ready to @@ -137,8 +172,9 @@ static int fpga_mgr_write_complete(struct fpga_manager *mgr, * * Return: 0 on success, negative error code otherwise. */ -int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info, - struct sg_table *sgt) +static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, + struct fpga_image_info *info, + struct sg_table *sgt) { int ret; @@ -170,7 +206,6 @@ int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info, return fpga_mgr_write_complete(mgr, info); } -EXPORT_SYMBOL_GPL(fpga_mgr_buf_load_sg); static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, struct fpga_image_info *info, @@ -210,8 +245,9 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, * * Return: 0 on success, negative error code otherwise. */ -int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, - const char *buf, size_t count) +static int fpga_mgr_buf_load(struct fpga_manager *mgr, + struct fpga_image_info *info, + const char *buf, size_t count) { struct page **pages; struct sg_table sgt; @@ -266,7 +302,6 @@ int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, return rc; } -EXPORT_SYMBOL_GPL(fpga_mgr_buf_load); /** * fpga_mgr_firmware_load - request firmware and load to fpga @@ -282,9 +317,9 @@ EXPORT_SYMBOL_GPL(fpga_mgr_buf_load); * * Return: 0 on success, negative error code otherwise. */ -int fpga_mgr_firmware_load(struct fpga_manager *mgr, - struct fpga_image_info *info, - const char *image_name) +static int fpga_mgr_firmware_load(struct fpga_manager *mgr, + struct fpga_image_info *info, + const char *image_name) { struct device *dev = &mgr->dev; const struct firmware *fw; @@ -307,7 +342,18 @@ int fpga_mgr_firmware_load(struct fpga_manager *mgr, return ret; } -EXPORT_SYMBOL_GPL(fpga_mgr_firmware_load); + +int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) +{ + if (info->sgt) + return fpga_mgr_buf_load_sg(mgr, info, info->sgt); + if (info->buf && info->count) + return fpga_mgr_buf_load(mgr, info, info->buf, info->count); + if (info->firmware_name) + return fpga_mgr_firmware_load(mgr, info, info->firmware_name); + return -EINVAL; +} +EXPORT_SYMBOL_GPL(fpga_mgr_load); static const char * const state_str[] = { [FPGA_MGR_STATE_UNKNOWN] = "unknown", @@ -578,7 +624,7 @@ static void __exit fpga_mgr_class_exit(void) ida_destroy(&fpga_mgr_ida); } -MODULE_AUTHOR("Alan Tull "); +MODULE_AUTHOR("Alan Tull "); MODULE_DESCRIPTION("FPGA manager framework"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 9175556215b1..120c496eb7bd 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -226,14 +226,11 @@ static int fpga_region_get_bridges(struct fpga_region *region, /** * fpga_region_program_fpga - program FPGA * @region: FPGA region - * @firmware_name: name of FPGA image firmware file * @overlay: device node of the overlay - * Program an FPGA using information in the device tree. - * Function assumes that there is a firmware-name property. + * Program an FPGA using information in the region's fpga image info. * Return 0 for success or negative error code. */ static int fpga_region_program_fpga(struct fpga_region *region, - const char *firmware_name, struct device_node *overlay) { struct fpga_manager *mgr; @@ -264,7 +261,7 @@ static int fpga_region_program_fpga(struct fpga_region *region, goto err_put_br; } - ret = fpga_mgr_firmware_load(mgr, region->info, firmware_name); + ret = fpga_mgr_load(mgr, region->info); if (ret) { pr_err("failed to load fpga image\n"); goto err_put_br; @@ -357,16 +354,15 @@ static int child_regions_with_firmware(struct device_node *overlay) static int fpga_region_notify_pre_apply(struct fpga_region *region, struct of_overlay_notify_data *nd) { - const char *firmware_name = NULL; + struct device *dev = ®ion->dev; struct fpga_image_info *info; + const char *firmware_name; int ret; - info = devm_kzalloc(®ion->dev, sizeof(*info), GFP_KERNEL); + info = fpga_image_info_alloc(dev); if (!info) return -ENOMEM; - region->info = info; - /* Reject overlay if child FPGA Regions have firmware-name property */ ret = child_regions_with_firmware(nd->overlay); if (ret) @@ -382,7 +378,13 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, if (of_property_read_bool(nd->overlay, "encrypted-fpga-config")) info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM; - of_property_read_string(nd->overlay, "firmware-name", &firmware_name); + if (!of_property_read_string(nd->overlay, "firmware-name", + &firmware_name)) { + info->firmware_name = devm_kstrdup(dev, firmware_name, + GFP_KERNEL); + if (!info->firmware_name) + return -ENOMEM; + } of_property_read_u32(nd->overlay, "region-unfreeze-timeout-us", &info->enable_timeout_us); @@ -394,22 +396,33 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, &info->config_complete_timeout_us); /* If FPGA was externally programmed, don't specify firmware */ - if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && firmware_name) { + if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && info->firmware_name) { pr_err("error: specified firmware and external-fpga-config"); + fpga_image_info_free(info); return -EINVAL; } /* FPGA is already configured externally. We're done. */ - if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) + if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) { + fpga_image_info_free(info); return 0; + } /* If we got this far, we should be programming the FPGA */ - if (!firmware_name) { + if (!info->firmware_name) { pr_err("should specify firmware-name or external-fpga-config\n"); + fpga_image_info_free(info); return -EINVAL; } - return fpga_region_program_fpga(region, firmware_name, nd->overlay); + region->info = info; + ret = fpga_region_program_fpga(region, nd->overlay); + if (ret) { + fpga_image_info_free(info); + region->info = NULL; + } + + return ret; } /** @@ -426,7 +439,7 @@ static void fpga_region_notify_post_remove(struct fpga_region *region, { fpga_bridges_disable(®ion->bridge_list); fpga_bridges_put(®ion->bridge_list); - devm_kfree(®ion->dev, region->info); + fpga_image_info_free(region->info); region->info = NULL; } diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h index bfa14bc023fb..6b791348023b 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -1,7 +1,8 @@ /* * FPGA Framework * - * Copyright (C) 2013-2015 Altera Corporation + * Copyright (C) 2013-2016 Altera Corporation + * Copyright (C) 2017 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -15,12 +16,12 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -#include -#include - #ifndef _LINUX_FPGA_MGR_H #define _LINUX_FPGA_MGR_H +#include +#include + struct fpga_manager; struct sg_table; @@ -83,12 +84,22 @@ enum fpga_mgr_states { * @disable_timeout_us: maximum time to disable traffic through bridge (uSec) * @config_complete_timeout_us: maximum time for FPGA to switch to operating * status in the write_complete op. + * @firmware_name: name of FPGA image firmware file + * @sgt: scatter/gather table containing FPGA image + * @buf: contiguous buffer containing FPGA image + * @count: size of buf + * @dev: device that owns this */ struct fpga_image_info { u32 flags; u32 enable_timeout_us; u32 disable_timeout_us; u32 config_complete_timeout_us; + char *firmware_name; + struct sg_table *sgt; + const char *buf; + size_t count; + struct device *dev; }; /** @@ -138,14 +149,11 @@ struct fpga_manager { #define to_fpga_manager(d) container_of(d, struct fpga_manager, dev) -int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, - const char *buf, size_t count); -int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info, - struct sg_table *sgt); +struct fpga_image_info *fpga_image_info_alloc(struct device *dev); + +void fpga_image_info_free(struct fpga_image_info *info); -int fpga_mgr_firmware_load(struct fpga_manager *mgr, - struct fpga_image_info *info, - const char *image_name); +int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info); struct fpga_manager *of_fpga_mgr_get(struct device_node *node); -- cgit v1.2.3 From ebf877a51ad7b65e4ab024f021b60a4f7928864a Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:13 -0600 Subject: fpga: mgr: separate getting/locking FPGA manager Previously when the user gets a FPGA manager, it was locked and nobody else could use it for programming. This commit makes it straightforward to save a reference to an FPGA manager and only lock it when programming the FPGA. Add functions that get an FPGA manager's mutex for exclusive use: * fpga_mgr_lock * fpga_mgr_unlock The following functions no longer lock an FPGA manager's mutex: * of_fpga_mgr_get * fpga_mgr_get * fpga_mgr_put Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- Documentation/fpga/fpga-mgr.txt | 35 ++++++++++++++++++++------- drivers/fpga/fpga-mgr.c | 52 ++++++++++++++++++++++++++++------------- drivers/fpga/fpga-region.c | 14 +++++++++-- include/linux/fpga/fpga-mgr.h | 3 +++ 4 files changed, 77 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/Documentation/fpga/fpga-mgr.txt b/Documentation/fpga/fpga-mgr.txt index 6ebc714f4b03..cc6413ed6fc9 100644 --- a/Documentation/fpga/fpga-mgr.txt +++ b/Documentation/fpga/fpga-mgr.txt @@ -48,8 +48,20 @@ To get/put a reference to a FPGA manager: struct fpga_manager *fpga_mgr_get(struct device *dev); void fpga_mgr_put(struct fpga_manager *mgr); -Given a DT node or device, get an exclusive reference to a FPGA manager. -fpga_mgr_put releases the reference. +Given a DT node or device, get a reference to a FPGA manager. This pointer +can be saved until you are ready to program the FPGA. fpga_mgr_put releases +the reference. + + +To get exclusive control of a FPGA manager: +------------------------------------------- + + int fpga_mgr_lock(struct fpga_manager *mgr); + void fpga_mgr_unlock(struct fpga_manager *mgr); + +The user should call fpga_mgr_lock and verify that it returns 0 before +attempting to program the FPGA. Likewise, the user should call +fpga_mgr_unlock when done programming the FPGA. To register or unregister the low level FPGA-specific driver: @@ -67,13 +79,21 @@ device." How to write an image buffer to a supported FPGA ================================================ -/* Include to get the API */ #include struct fpga_manager *mgr; struct fpga_image_info *info; int ret; +/* + * Get a reference to FPGA manager. The manager is not locked, so you can + * hold onto this reference without it preventing programming. + * + * This example uses the device node of the manager. Alternatively, use + * fpga_mgr_get(dev) instead if you have the device. + */ +mgr = of_fpga_mgr_get(mgr_node); + /* struct with information about the FPGA image to program. */ info = fpga_image_info_alloc(dev); @@ -99,17 +119,14 @@ if (image is in a scatter gather table) { } -/* - * Get a reference to FPGA manager. This example uses the device node of the - * manager. You could use fpga_mgr_get() instead if you have the device instead - * of the device node. - */ -mgr = of_fpga_mgr_get(mgr_node); +/* Get exclusive control of FPGA manager */ +ret = fpga_mgr_lock(mgr); /* Load the buffer to the FPGA */ ret = fpga_mgr_buf_load(mgr, &info, buf, count); /* Release the FPGA manager */ +fpga_mgr_unlock(mgr); fpga_mgr_put(mgr); /* Deallocate the image info if you're done with it */ diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index a8dd54945470..d27e8d2a149c 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -410,28 +410,19 @@ ATTRIBUTE_GROUPS(fpga_mgr); static struct fpga_manager *__fpga_mgr_get(struct device *dev) { struct fpga_manager *mgr; - int ret = -ENODEV; mgr = to_fpga_manager(dev); if (!mgr) goto err_dev; - /* Get exclusive use of fpga manager */ - if (!mutex_trylock(&mgr->ref_mutex)) { - ret = -EBUSY; - goto err_dev; - } - if (!try_module_get(dev->parent->driver->owner)) - goto err_ll_mod; + goto err_dev; return mgr; -err_ll_mod: - mutex_unlock(&mgr->ref_mutex); err_dev: put_device(dev); - return ERR_PTR(ret); + return ERR_PTR(-ENODEV); } static int fpga_mgr_dev_match(struct device *dev, const void *data) @@ -440,10 +431,10 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) } /** - * fpga_mgr_get - get an exclusive reference to a fpga mgr + * fpga_mgr_get - get a reference to a fpga mgr * @dev: parent device that fpga mgr was registered with * - * Given a device, get an exclusive reference to a fpga mgr. + * Given a device, get a reference to a fpga mgr. * * Return: fpga manager struct or IS_ERR() condition containing error code. */ @@ -464,10 +455,10 @@ static int fpga_mgr_of_node_match(struct device *dev, const void *data) } /** - * of_fpga_mgr_get - get an exclusive reference to a fpga mgr + * of_fpga_mgr_get - get a reference to a fpga mgr * @node: device node * - * Given a device node, get an exclusive reference to a fpga mgr. + * Given a device node, get a reference to a fpga mgr. * * Return: fpga manager struct or IS_ERR() condition containing error code. */ @@ -491,11 +482,40 @@ EXPORT_SYMBOL_GPL(of_fpga_mgr_get); void fpga_mgr_put(struct fpga_manager *mgr) { module_put(mgr->dev.parent->driver->owner); - mutex_unlock(&mgr->ref_mutex); put_device(&mgr->dev); } EXPORT_SYMBOL_GPL(fpga_mgr_put); +/** + * fpga_mgr_lock - Lock FPGA manager for exclusive use + * @mgr: fpga manager + * + * Given a pointer to FPGA Manager (from fpga_mgr_get() or + * of_fpga_mgr_put()) attempt to get the mutex. + * + * Return: 0 for success or -EBUSY + */ +int fpga_mgr_lock(struct fpga_manager *mgr) +{ + if (!mutex_trylock(&mgr->ref_mutex)) { + dev_err(&mgr->dev, "FPGA manager is in use.\n"); + return -EBUSY; + } + + return 0; +} +EXPORT_SYMBOL_GPL(fpga_mgr_lock); + +/** + * fpga_mgr_unlock - Unlock FPGA manager + * @mgr: fpga manager + */ +void fpga_mgr_unlock(struct fpga_manager *mgr) +{ + mutex_unlock(&mgr->ref_mutex); +} +EXPORT_SYMBOL_GPL(fpga_mgr_unlock); + /** * fpga_mgr_register - register a low level fpga manager driver * @dev: fpga manager device from pdev diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 120c496eb7bd..1e1640a29306 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -125,7 +125,7 @@ static void fpga_region_put(struct fpga_region *region) } /** - * fpga_region_get_manager - get exclusive reference for FPGA manager + * fpga_region_get_manager - get reference for FPGA manager * @region: FPGA region * * Get FPGA Manager from "fpga-mgr" property or from ancestor region. @@ -233,6 +233,7 @@ static int fpga_region_get_bridges(struct fpga_region *region, static int fpga_region_program_fpga(struct fpga_region *region, struct device_node *overlay) { + struct device *dev = ®ion->dev; struct fpga_manager *mgr; int ret; @@ -249,10 +250,16 @@ static int fpga_region_program_fpga(struct fpga_region *region, goto err_put_region; } + ret = fpga_mgr_lock(mgr); + if (ret) { + dev_err(dev, "FPGA manager is busy\n"); + goto err_put_mgr; + } + ret = fpga_region_get_bridges(region, overlay); if (ret) { pr_err("failed to get fpga region bridges\n"); - goto err_put_mgr; + goto err_unlock_mgr; } ret = fpga_bridges_disable(®ion->bridge_list); @@ -273,6 +280,7 @@ static int fpga_region_program_fpga(struct fpga_region *region, goto err_put_br; } + fpga_mgr_unlock(mgr); fpga_mgr_put(mgr); fpga_region_put(region); @@ -280,6 +288,8 @@ static int fpga_region_program_fpga(struct fpga_region *region, err_put_br: fpga_bridges_put(®ion->bridge_list); +err_unlock_mgr: + fpga_mgr_unlock(mgr); err_put_mgr: fpga_mgr_put(mgr); err_put_region: diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h index 6b791348023b..cb5615c87504 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -155,6 +155,9 @@ void fpga_image_info_free(struct fpga_image_info *info); int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info); +int fpga_mgr_lock(struct fpga_manager *mgr); +void fpga_mgr_unlock(struct fpga_manager *mgr); + struct fpga_manager *of_fpga_mgr_get(struct device_node *node); struct fpga_manager *fpga_mgr_get(struct device *dev); -- cgit v1.2.3 From c3d971ad32fc19af638ac6f6ffe041aa1ff722b5 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:14 -0600 Subject: fpga: region: use dev_err instead of pr_err Use dev_err messages instead of pr_err. Also s/®ion->dev/dev/ in two places where we already have dev = ®ion->dev. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 1e1640a29306..6b4f9abed043 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -102,7 +102,7 @@ static struct fpga_region *fpga_region_get(struct fpga_region *region) return ERR_PTR(-ENODEV); } - dev_dbg(®ion->dev, "get\n"); + dev_dbg(dev, "get\n"); return region; } @@ -116,7 +116,7 @@ static void fpga_region_put(struct fpga_region *region) { struct device *dev = ®ion->dev; - dev_dbg(®ion->dev, "put\n"); + dev_dbg(dev, "put\n"); module_put(dev->parent->driver->owner); of_node_put(dev->of_node); @@ -239,13 +239,13 @@ static int fpga_region_program_fpga(struct fpga_region *region, region = fpga_region_get(region); if (IS_ERR(region)) { - pr_err("failed to get fpga region\n"); + dev_err(dev, "failed to get FPGA region\n"); return PTR_ERR(region); } mgr = fpga_region_get_manager(region); if (IS_ERR(mgr)) { - pr_err("failed to get fpga region manager\n"); + dev_err(dev, "failed to get FPGA manager\n"); ret = PTR_ERR(mgr); goto err_put_region; } @@ -258,25 +258,25 @@ static int fpga_region_program_fpga(struct fpga_region *region, ret = fpga_region_get_bridges(region, overlay); if (ret) { - pr_err("failed to get fpga region bridges\n"); + dev_err(dev, "failed to get FPGA bridges\n"); goto err_unlock_mgr; } ret = fpga_bridges_disable(®ion->bridge_list); if (ret) { - pr_err("failed to disable region bridges\n"); + dev_err(dev, "failed to disable bridges\n"); goto err_put_br; } ret = fpga_mgr_load(mgr, region->info); if (ret) { - pr_err("failed to load fpga image\n"); + dev_err(dev, "failed to load FPGA image\n"); goto err_put_br; } ret = fpga_bridges_enable(®ion->bridge_list); if (ret) { - pr_err("failed to enable region bridges\n"); + dev_err(dev, "failed to enable region bridges\n"); goto err_put_br; } @@ -407,7 +407,7 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, /* If FPGA was externally programmed, don't specify firmware */ if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && info->firmware_name) { - pr_err("error: specified firmware and external-fpga-config"); + dev_err(dev, "error: specified firmware and external-fpga-config"); fpga_image_info_free(info); return -EINVAL; } @@ -420,7 +420,7 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, /* If we got this far, we should be programming the FPGA */ if (!info->firmware_name) { - pr_err("should specify firmware-name or external-fpga-config\n"); + dev_err(dev, "should specify firmware-name or external-fpga-config\n"); fpga_image_info_free(info); return -EINVAL; } -- cgit v1.2.3 From 08bcb4b1a7615762e1e2c87a5c8cc5d9709b60f6 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:15 -0600 Subject: fpga: region: remove unneeded of_node_get and put Remove of_node_get/put in fpga_region_get/put. Not needed and will get in the way when I separate out the common FPGA region code from Device Tree support code. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 6b4f9abed043..352661fc6b14 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -94,9 +94,7 @@ static struct fpga_region *fpga_region_get(struct fpga_region *region) } get_device(dev); - of_node_get(dev->of_node); if (!try_module_get(dev->parent->driver->owner)) { - of_node_put(dev->of_node); put_device(dev); mutex_unlock(®ion->mutex); return ERR_PTR(-ENODEV); @@ -119,7 +117,6 @@ static void fpga_region_put(struct fpga_region *region) dev_dbg(dev, "put\n"); module_put(dev->parent->driver->owner); - of_node_put(dev->of_node); put_device(dev); mutex_unlock(®ion->mutex); } -- cgit v1.2.3 From 1df2dd7f587107ebf3c8e3733410627cf5c3b3ec Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:16 -0600 Subject: fpga: region: get mgr early on Get the FPGA manager during region creation. This is a baby step in refactoring the FPGA region code to separate out common FPGA region code from FPGA region Device Tree overlay support. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 352661fc6b14..d78f444c1350 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -31,12 +31,14 @@ * @dev: FPGA Region device * @mutex: enforces exclusive reference to region * @bridge_list: list of FPGA bridges specified in region + * @mgr: FPGA manager * @info: fpga image specific information */ struct fpga_region { struct device dev; struct mutex mutex; /* for exclusive reference to region */ struct list_head bridge_list; + struct fpga_manager *mgr; struct fpga_image_info *info; }; @@ -123,7 +125,7 @@ static void fpga_region_put(struct fpga_region *region) /** * fpga_region_get_manager - get reference for FPGA manager - * @region: FPGA region + * @np: device node of FPGA region * * Get FPGA Manager from "fpga-mgr" property or from ancestor region. * @@ -131,10 +133,8 @@ static void fpga_region_put(struct fpga_region *region) * * Return: fpga manager struct or IS_ERR() condition containing error code. */ -static struct fpga_manager *fpga_region_get_manager(struct fpga_region *region) +static struct fpga_manager *fpga_region_get_manager(struct device_node *np) { - struct device *dev = ®ion->dev; - struct device_node *np = dev->of_node; struct device_node *mgr_node; struct fpga_manager *mgr; @@ -231,7 +231,6 @@ static int fpga_region_program_fpga(struct fpga_region *region, struct device_node *overlay) { struct device *dev = ®ion->dev; - struct fpga_manager *mgr; int ret; region = fpga_region_get(region); @@ -240,17 +239,10 @@ static int fpga_region_program_fpga(struct fpga_region *region, return PTR_ERR(region); } - mgr = fpga_region_get_manager(region); - if (IS_ERR(mgr)) { - dev_err(dev, "failed to get FPGA manager\n"); - ret = PTR_ERR(mgr); - goto err_put_region; - } - - ret = fpga_mgr_lock(mgr); + ret = fpga_mgr_lock(region->mgr); if (ret) { dev_err(dev, "FPGA manager is busy\n"); - goto err_put_mgr; + goto err_put_region; } ret = fpga_region_get_bridges(region, overlay); @@ -265,7 +257,7 @@ static int fpga_region_program_fpga(struct fpga_region *region, goto err_put_br; } - ret = fpga_mgr_load(mgr, region->info); + ret = fpga_mgr_load(region->mgr, region->info); if (ret) { dev_err(dev, "failed to load FPGA image\n"); goto err_put_br; @@ -277,8 +269,7 @@ static int fpga_region_program_fpga(struct fpga_region *region, goto err_put_br; } - fpga_mgr_unlock(mgr); - fpga_mgr_put(mgr); + fpga_mgr_unlock(region->mgr); fpga_region_put(region); return 0; @@ -286,9 +277,7 @@ static int fpga_region_program_fpga(struct fpga_region *region, err_put_br: fpga_bridges_put(®ion->bridge_list); err_unlock_mgr: - fpga_mgr_unlock(mgr); -err_put_mgr: - fpga_mgr_put(mgr); + fpga_mgr_unlock(region->mgr); err_put_region: fpga_region_put(region); @@ -517,11 +506,20 @@ static int fpga_region_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct fpga_region *region; + struct fpga_manager *mgr; int id, ret = 0; + mgr = fpga_region_get_manager(np); + if (IS_ERR(mgr)) + return -EPROBE_DEFER; + region = kzalloc(sizeof(*region), GFP_KERNEL); - if (!region) - return -ENOMEM; + if (!region) { + ret = -ENOMEM; + goto err_put_mgr; + } + + region->mgr = mgr; id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); if (id < 0) { @@ -557,6 +555,8 @@ err_remove: ida_simple_remove(&fpga_region_ida, id); err_kfree: kfree(region); +err_put_mgr: + fpga_mgr_put(mgr); return ret; } @@ -566,6 +566,7 @@ static int fpga_region_remove(struct platform_device *pdev) struct fpga_region *region = platform_get_drvdata(pdev); device_unregister(®ion->dev); + fpga_mgr_put(region->mgr); return 0; } -- cgit v1.2.3 From 1743df83ae5a949037eb86a12f225abd4374d176 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:17 -0600 Subject: fpga: region: check for child regions before allocing image info During a device tree overlay pre-apply notification, the check for child FPGA regions can happen slightly earlier. This saves us from allocating the FPGA image info that just gets thrown away. This is a baby step in refactoring the FPGA region code to separate out common FPGA region code from FPGA region Device Tree overlay support. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index d78f444c1350..afac5433978b 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -355,15 +355,19 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, const char *firmware_name; int ret; - info = fpga_image_info_alloc(dev); - if (!info) - return -ENOMEM; - - /* Reject overlay if child FPGA Regions have firmware-name property */ + /* + * Reject overlay if child FPGA Regions added in the overlay have + * firmware-name property (would mean that an FPGA region that has + * not been added to the live tree yet is doing FPGA programming). + */ ret = child_regions_with_firmware(nd->overlay); if (ret) return ret; + info = fpga_image_info_alloc(dev); + if (!info) + return -ENOMEM; + /* Read FPGA region properties from the overlay */ if (of_property_read_bool(nd->overlay, "partial-fpga-config")) info->flags |= FPGA_MGR_PARTIAL_RECONFIG; -- cgit v1.2.3 From ed81f5fc3c35c22d0fc62813cfa4e11b6aea0a64 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:18 -0600 Subject: fpga: region: fix slow warning with more than one overlay When DT overlays are applied, each FPGA region keeps track of the fpga image info as region->info. This pointer is assigned only if an overlay causes the FPGA to be programmed. As it stands, this pointer can be overwritten, causing a slow warning later when overlays are removed. This patch fixes this by changing the allowed behaviour. If a region has received an overlay that programmed the FPGA, reject other overlays that try to program the FPGA. To reprogram the FPGA, first remove the overlay. This makes sense as removing the overlay also removes the devices cleanly. Note that overlays that make DT changes without reprogramming the FPGA are exempt from this restriction. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index afac5433978b..35af952a889a 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -355,6 +355,11 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, const char *firmware_name; int ret; + if (region->info) { + dev_err(dev, "Region already has overlay applied.\n"); + return -EINVAL; + } + /* * Reject overlay if child FPGA Regions added in the overlay have * firmware-name property (would mean that an FPGA region that has -- cgit v1.2.3 From 61c32102391ff38dfd4aba835dd0f99db6b46908 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:19 -0600 Subject: fpga: region: use image info as parameter for programming region Use FPGA image info (region->info) when region code is programming the FPGA to pass in multiple parameters. This is a baby step in refactoring the FPGA region code to separate out common FPGA region code from FPGA region Device Tree overlay support. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 16 +++++++++------- include/linux/fpga/fpga-mgr.h | 4 ++++ 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 35af952a889a..eaacf5049381 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -223,14 +223,13 @@ static int fpga_region_get_bridges(struct fpga_region *region, /** * fpga_region_program_fpga - program FPGA * @region: FPGA region - * @overlay: device node of the overlay - * Program an FPGA using information in the region's fpga image info. + * Program an FPGA using fpga image info (region->info). * Return 0 for success or negative error code. */ -static int fpga_region_program_fpga(struct fpga_region *region, - struct device_node *overlay) +static int fpga_region_program_fpga(struct fpga_region *region) { struct device *dev = ®ion->dev; + struct fpga_image_info *info = region->info; int ret; region = fpga_region_get(region); @@ -245,7 +244,7 @@ static int fpga_region_program_fpga(struct fpga_region *region, goto err_put_region; } - ret = fpga_region_get_bridges(region, overlay); + ret = fpga_region_get_bridges(region, info->overlay); if (ret) { dev_err(dev, "failed to get FPGA bridges\n"); goto err_unlock_mgr; @@ -257,7 +256,7 @@ static int fpga_region_program_fpga(struct fpga_region *region, goto err_put_br; } - ret = fpga_mgr_load(region->mgr, region->info); + ret = fpga_mgr_load(region->mgr, info); if (ret) { dev_err(dev, "failed to load FPGA image\n"); goto err_put_br; @@ -373,6 +372,8 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, if (!info) return -ENOMEM; + info->overlay = nd->overlay; + /* Read FPGA region properties from the overlay */ if (of_property_read_bool(nd->overlay, "partial-fpga-config")) info->flags |= FPGA_MGR_PARTIAL_RECONFIG; @@ -421,7 +422,8 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, } region->info = info; - ret = fpga_region_program_fpga(region, nd->overlay); + + ret = fpga_region_program_fpga(region); if (ret) { fpga_image_info_free(info); region->info = NULL; diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h index cb5615c87504..4fb706bd9aba 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -89,6 +89,7 @@ enum fpga_mgr_states { * @buf: contiguous buffer containing FPGA image * @count: size of buf * @dev: device that owns this + * @overlay: Device Tree overlay */ struct fpga_image_info { u32 flags; @@ -100,6 +101,9 @@ struct fpga_image_info { const char *buf; size_t count; struct device *dev; +#ifdef CONFIG_OF + struct device_node *overlay; +#endif }; /** -- cgit v1.2.3 From c8898eda81e0b949ca214e1a45ce1b56677eb849 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:20 -0600 Subject: fpga: region: separate out code that parses the overlay New function of_fpga_region_parse_ov added, moving code from fpga_region_notify_pre_apply. This function gets the FPGA image info from the overlay and is able to simplify some of the logic involved. This is a baby step in refactoring the FPGA region code to separate out common code from Device Tree overlay support. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 122 +++++++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index eaacf5049381..2a8621db5f5b 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -321,33 +321,22 @@ static int child_regions_with_firmware(struct device_node *overlay) } /** - * fpga_region_notify_pre_apply - pre-apply overlay notification - * - * @region: FPGA region that the overlay was applied to - * @nd: overlay notification data - * - * Called after when an overlay targeted to a FPGA Region is about to be - * applied. Function will check the properties that will be added to the FPGA - * region. If the checks pass, it will program the FPGA. - * - * The checks are: - * The overlay must add either firmware-name or external-fpga-config property - * to the FPGA Region. - * - * firmware-name : program the FPGA - * external-fpga-config : FPGA is already programmed - * encrypted-fpga-config : FPGA bitstream is encrypted + * of_fpga_region_parse_ov - parse and check overlay applied to region * - * The overlay can add other FPGA regions, but child FPGA regions cannot have a - * firmware-name property since those regions don't exist yet. + * @region: FPGA region + * @overlay: overlay applied to the FPGA region * - * If the overlay that breaks the rules, notifier returns an error and the - * overlay is rejected before it goes into the main tree. + * Given an overlay applied to a FPGA region, parse the FPGA image specific + * info in the overlay and do some checking. * - * Returns 0 for success or negative error code for failure. + * Returns: + * NULL if overlay doesn't direct us to program the FPGA. + * fpga_image_info struct if there is an image to program. + * error code for invalid overlay. */ -static int fpga_region_notify_pre_apply(struct fpga_region *region, - struct of_overlay_notify_data *nd) +static struct fpga_image_info *of_fpga_region_parse_ov( + struct fpga_region *region, + struct device_node *overlay) { struct device *dev = ®ion->dev; struct fpga_image_info *info; @@ -356,7 +345,7 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, if (region->info) { dev_err(dev, "Region already has overlay applied.\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } /* @@ -364,67 +353,102 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, * firmware-name property (would mean that an FPGA region that has * not been added to the live tree yet is doing FPGA programming). */ - ret = child_regions_with_firmware(nd->overlay); + ret = child_regions_with_firmware(overlay); if (ret) - return ret; + return ERR_PTR(ret); info = fpga_image_info_alloc(dev); if (!info) - return -ENOMEM; + return ERR_PTR(-ENOMEM); - info->overlay = nd->overlay; + info->overlay = overlay; /* Read FPGA region properties from the overlay */ - if (of_property_read_bool(nd->overlay, "partial-fpga-config")) + if (of_property_read_bool(overlay, "partial-fpga-config")) info->flags |= FPGA_MGR_PARTIAL_RECONFIG; - if (of_property_read_bool(nd->overlay, "external-fpga-config")) + if (of_property_read_bool(overlay, "external-fpga-config")) info->flags |= FPGA_MGR_EXTERNAL_CONFIG; - if (of_property_read_bool(nd->overlay, "encrypted-fpga-config")) + if (of_property_read_bool(overlay, "encrypted-fpga-config")) info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM; - if (!of_property_read_string(nd->overlay, "firmware-name", + if (!of_property_read_string(overlay, "firmware-name", &firmware_name)) { info->firmware_name = devm_kstrdup(dev, firmware_name, GFP_KERNEL); if (!info->firmware_name) - return -ENOMEM; + return ERR_PTR(-ENOMEM); } - of_property_read_u32(nd->overlay, "region-unfreeze-timeout-us", + of_property_read_u32(overlay, "region-unfreeze-timeout-us", &info->enable_timeout_us); - of_property_read_u32(nd->overlay, "region-freeze-timeout-us", + of_property_read_u32(overlay, "region-freeze-timeout-us", &info->disable_timeout_us); - of_property_read_u32(nd->overlay, "config-complete-timeout-us", + of_property_read_u32(overlay, "config-complete-timeout-us", &info->config_complete_timeout_us); - /* If FPGA was externally programmed, don't specify firmware */ - if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && info->firmware_name) { - dev_err(dev, "error: specified firmware and external-fpga-config"); - fpga_image_info_free(info); - return -EINVAL; + /* If overlay is not programming the FPGA, don't need FPGA image info */ + if (!info->firmware_name) { + ret = 0; + goto ret_no_info; } - /* FPGA is already configured externally. We're done. */ + /* + * If overlay informs us FPGA was externally programmed, specifying + * firmware here would be ambiguous. + */ if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) { - fpga_image_info_free(info); - return 0; + dev_err(dev, "error: specified firmware and external-fpga-config"); + ret = -EINVAL; + goto ret_no_info; } - /* If we got this far, we should be programming the FPGA */ - if (!info->firmware_name) { - dev_err(dev, "should specify firmware-name or external-fpga-config\n"); - fpga_image_info_free(info); + return info; +ret_no_info: + fpga_image_info_free(info); + return ERR_PTR(ret); +} + +/** + * fpga_region_notify_pre_apply - pre-apply overlay notification + * + * @region: FPGA region that the overlay was applied to + * @nd: overlay notification data + * + * Called when an overlay targeted to a FPGA Region is about to be applied. + * Parses the overlay for properties that influence how the FPGA will be + * programmed and does some checking. If the checks pass, programs the FPGA. + * If the checks fail, overlay is rejected and does not get added to the + * live tree. + * + * Returns 0 for success or negative error code for failure. + */ +static int fpga_region_notify_pre_apply(struct fpga_region *region, + struct of_overlay_notify_data *nd) +{ + struct device *dev = ®ion->dev; + struct fpga_image_info *info; + int ret; + + if (region->info) { + dev_err(dev, "Region already has overlay applied.\n"); return -EINVAL; } - region->info = info; + info = of_fpga_region_parse_ov(region, nd->overlay); + if (IS_ERR(info)) + return PTR_ERR(info); + + if (!info) + return 0; + region->info = info; ret = fpga_region_program_fpga(region); if (ret) { + /* error; reject overlay */ fpga_image_info_free(info); region->info = NULL; } -- cgit v1.2.3 From 59460a9305458ac3e7f2415b602dbaa6cfcb8a3b Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:21 -0600 Subject: fpga: region: add fpga-region.h header * Create fpga-region.h. * Export fpga_region_program_fpga. * Move struct fpga_region and other things to the header. This is a step in separating FPGA region common code from Device Tree support. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 24 ++++-------------------- include/linux/fpga/fpga-region.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 20 deletions(-) create mode 100644 include/linux/fpga/fpga-region.h (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 2a8621db5f5b..402d0b68b97a 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -26,24 +27,6 @@ #include #include -/** - * struct fpga_region - FPGA Region structure - * @dev: FPGA Region device - * @mutex: enforces exclusive reference to region - * @bridge_list: list of FPGA bridges specified in region - * @mgr: FPGA manager - * @info: fpga image specific information - */ -struct fpga_region { - struct device dev; - struct mutex mutex; /* for exclusive reference to region */ - struct list_head bridge_list; - struct fpga_manager *mgr; - struct fpga_image_info *info; -}; - -#define to_fpga_region(d) container_of(d, struct fpga_region, dev) - static DEFINE_IDA(fpga_region_ida); static struct class *fpga_region_class; @@ -226,7 +209,7 @@ static int fpga_region_get_bridges(struct fpga_region *region, * Program an FPGA using fpga image info (region->info). * Return 0 for success or negative error code. */ -static int fpga_region_program_fpga(struct fpga_region *region) +int fpga_region_program_fpga(struct fpga_region *region) { struct device *dev = ®ion->dev; struct fpga_image_info *info = region->info; @@ -282,6 +265,7 @@ err_put_region: return ret; } +EXPORT_SYMBOL_GPL(fpga_region_program_fpga); /** * child_regions_with_firmware @@ -667,5 +651,5 @@ subsys_initcall(fpga_region_init); module_exit(fpga_region_exit); MODULE_DESCRIPTION("FPGA Region"); -MODULE_AUTHOR("Alan Tull "); +MODULE_AUTHOR("Alan Tull "); MODULE_LICENSE("GPL v2"); diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h new file mode 100644 index 000000000000..8a355171406b --- /dev/null +++ b/include/linux/fpga/fpga-region.h @@ -0,0 +1,28 @@ +#ifndef _FPGA_REGION_H +#define _FPGA_REGION_H + +#include +#include +#include + +/** + * struct fpga_region - FPGA Region structure + * @dev: FPGA Region device + * @mutex: enforces exclusive reference to region + * @bridge_list: list of FPGA bridges specified in region + * @mgr: FPGA manager + * @info: FPGA image info + */ +struct fpga_region { + struct device dev; + struct mutex mutex; /* for exclusive reference to region */ + struct list_head bridge_list; + struct fpga_manager *mgr; + struct fpga_image_info *info; +}; + +#define to_fpga_region(d) container_of(d, struct fpga_region, dev) + +int fpga_region_program_fpga(struct fpga_region *region); + +#endif /* _FPGA_REGION_H */ -- cgit v1.2.3 From 3b49537f8084af15ccaac542eaf317e01c6869e6 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:22 -0600 Subject: fpga: region: rename some functions prior to moving Rename some functions that will be moved to of-fpga-region.c. Also change some parameters and export a function to help with refactoring. This is a step towards the larger goal of separating device tree support from FPGA region common code. * fpga_region_get_manager -> of_fpga_region_get_mgr * add 'of_' prefix to the following: * fpga_region_find * fpga_region_get_bridges * fpga_region_notify_pre_apply * fpga_region_notify_post_remove), * fpga_region_probe/remove Parameter changes: * of_fpga_region_find change parameter to be the device node of the region. * of_fpga_region_get_bridges change second parameter to FPGA image info. Export of_fpga_region_find as well. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 60 ++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 402d0b68b97a..92ab21651aeb 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -42,12 +42,14 @@ static int fpga_region_of_node_match(struct device *dev, const void *data) } /** - * fpga_region_find - find FPGA region + * of_fpga_region_find - find FPGA region * @np: device node of FPGA Region + * * Caller will need to put_device(®ion->dev) when done. + * * Returns FPGA Region struct or NULL */ -static struct fpga_region *fpga_region_find(struct device_node *np) +static struct fpga_region *of_fpga_region_find(struct device_node *np) { struct device *dev; @@ -107,7 +109,7 @@ static void fpga_region_put(struct fpga_region *region) } /** - * fpga_region_get_manager - get reference for FPGA manager + * of_fpga_region_get_mgr - get reference for FPGA manager * @np: device node of FPGA region * * Get FPGA Manager from "fpga-mgr" property or from ancestor region. @@ -116,7 +118,7 @@ static void fpga_region_put(struct fpga_region *region) * * Return: fpga manager struct or IS_ERR() condition containing error code. */ -static struct fpga_manager *fpga_region_get_manager(struct device_node *np) +static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) { struct device_node *mgr_node; struct fpga_manager *mgr; @@ -139,9 +141,9 @@ static struct fpga_manager *fpga_region_get_manager(struct device_node *np) } /** - * fpga_region_get_bridges - create a list of bridges + * of_fpga_region_get_bridges - create a list of bridges * @region: FPGA region - * @overlay: device node of the overlay + * @info: FPGA image info * * Create a list of bridges including the parent bridge and the bridges * specified by "fpga-bridges" property. Note that the @@ -154,8 +156,8 @@ static struct fpga_manager *fpga_region_get_manager(struct device_node *np) * Return 0 for success (even if there are no bridges specified) * or -EBUSY if any of the bridges are in use. */ -static int fpga_region_get_bridges(struct fpga_region *region, - struct device_node *overlay) +static int of_fpga_region_get_bridges(struct fpga_region *region, + struct fpga_image_info *info) { struct device *dev = ®ion->dev; struct device_node *region_np = dev->of_node; @@ -163,7 +165,7 @@ static int fpga_region_get_bridges(struct fpga_region *region, int i, ret; /* If parent is a bridge, add to list */ - ret = of_fpga_bridge_get_to_list(region_np->parent, region->info, + ret = of_fpga_bridge_get_to_list(region_np->parent, info, ®ion->bridge_list); /* -EBUSY means parent is a bridge that is under use. Give up. */ @@ -175,8 +177,8 @@ static int fpga_region_get_bridges(struct fpga_region *region, parent_br = region_np->parent; /* If overlay has a list of bridges, use it. */ - if (of_parse_phandle(overlay, "fpga-bridges", 0)) - np = overlay; + if (of_parse_phandle(info->overlay, "fpga-bridges", 0)) + np = info->overlay; else np = region_np; @@ -227,7 +229,7 @@ int fpga_region_program_fpga(struct fpga_region *region) goto err_put_region; } - ret = fpga_region_get_bridges(region, info->overlay); + ret = of_fpga_region_get_bridges(region, info); if (ret) { dev_err(dev, "failed to get FPGA bridges\n"); goto err_unlock_mgr; @@ -397,7 +399,7 @@ ret_no_info: } /** - * fpga_region_notify_pre_apply - pre-apply overlay notification + * of_fpga_region_notify_pre_apply - pre-apply overlay notification * * @region: FPGA region that the overlay was applied to * @nd: overlay notification data @@ -410,8 +412,8 @@ ret_no_info: * * Returns 0 for success or negative error code for failure. */ -static int fpga_region_notify_pre_apply(struct fpga_region *region, - struct of_overlay_notify_data *nd) +static int of_fpga_region_notify_pre_apply(struct fpga_region *region, + struct of_overlay_notify_data *nd) { struct device *dev = ®ion->dev; struct fpga_image_info *info; @@ -441,7 +443,7 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, } /** - * fpga_region_notify_post_remove - post-remove overlay notification + * of_fpga_region_notify_post_remove - post-remove overlay notification * * @region: FPGA region that was targeted by the overlay that was removed * @nd: overlay notification data @@ -449,8 +451,8 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, * Called after an overlay has been removed if the overlay's target was a * FPGA region. */ -static void fpga_region_notify_post_remove(struct fpga_region *region, - struct of_overlay_notify_data *nd) +static void of_fpga_region_notify_post_remove(struct fpga_region *region, + struct of_overlay_notify_data *nd) { fpga_bridges_disable(®ion->bridge_list); fpga_bridges_put(®ion->bridge_list); @@ -493,18 +495,18 @@ static int of_fpga_region_notify(struct notifier_block *nb, return NOTIFY_OK; } - region = fpga_region_find(nd->target); + region = of_fpga_region_find(nd->target); if (!region) return NOTIFY_OK; ret = 0; switch (action) { case OF_OVERLAY_PRE_APPLY: - ret = fpga_region_notify_pre_apply(region, nd); + ret = of_fpga_region_notify_pre_apply(region, nd); break; case OF_OVERLAY_POST_REMOVE: - fpga_region_notify_post_remove(region, nd); + of_fpga_region_notify_post_remove(region, nd); break; } @@ -520,7 +522,7 @@ static struct notifier_block fpga_region_of_nb = { .notifier_call = of_fpga_region_notify, }; -static int fpga_region_probe(struct platform_device *pdev) +static int of_fpga_region_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -528,7 +530,7 @@ static int fpga_region_probe(struct platform_device *pdev) struct fpga_manager *mgr; int id, ret = 0; - mgr = fpga_region_get_manager(np); + mgr = of_fpga_region_get_mgr(np); if (IS_ERR(mgr)) return -EPROBE_DEFER; @@ -580,7 +582,7 @@ err_put_mgr: return ret; } -static int fpga_region_remove(struct platform_device *pdev) +static int of_fpga_region_remove(struct platform_device *pdev) { struct fpga_region *region = platform_get_drvdata(pdev); @@ -590,9 +592,9 @@ static int fpga_region_remove(struct platform_device *pdev) return 0; } -static struct platform_driver fpga_region_driver = { - .probe = fpga_region_probe, - .remove = fpga_region_remove, +static struct platform_driver of_fpga_region_driver = { + .probe = of_fpga_region_probe, + .remove = of_fpga_region_remove, .driver = { .name = "fpga-region", .of_match_table = of_match_ptr(fpga_region_of_match), @@ -625,7 +627,7 @@ static int __init fpga_region_init(void) if (ret) goto err_class; - ret = platform_driver_register(&fpga_region_driver); + ret = platform_driver_register(&of_fpga_region_driver); if (ret) goto err_plat; @@ -641,7 +643,7 @@ err_class: static void __exit fpga_region_exit(void) { - platform_driver_unregister(&fpga_region_driver); + platform_driver_unregister(&of_fpga_region_driver); of_overlay_notifier_unregister(&fpga_region_of_nb); class_destroy(fpga_region_class); ida_destroy(&fpga_region_ida); -- cgit v1.2.3 From 52a3a7ccce07e73323fc1bae9eb0b0b63375391c Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:23 -0600 Subject: fpga: region: add register/unregister functions Another step in separating common code from device tree specific code for FPGA regions. * add FPGA region register/unregister functions. * add the register/unregister functions to the header * use devm_kzalloc to alloc the region. * add a method for getting bridges to the region struct * add priv to the region struct * use region->info in of_fpga_region_get_bridges Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 105 ++++++++++++++++++++++++--------------- include/linux/fpga/fpga-region.h | 7 +++ 2 files changed, 72 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 92ab21651aeb..76db81de2cc0 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -143,7 +143,6 @@ static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) /** * of_fpga_region_get_bridges - create a list of bridges * @region: FPGA region - * @info: FPGA image info * * Create a list of bridges including the parent bridge and the bridges * specified by "fpga-bridges" property. Note that the @@ -156,11 +155,11 @@ static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) * Return 0 for success (even if there are no bridges specified) * or -EBUSY if any of the bridges are in use. */ -static int of_fpga_region_get_bridges(struct fpga_region *region, - struct fpga_image_info *info) +static int of_fpga_region_get_bridges(struct fpga_region *region) { struct device *dev = ®ion->dev; struct device_node *region_np = dev->of_node; + struct fpga_image_info *info = region->info; struct device_node *br, *np, *parent_br = NULL; int i, ret; @@ -192,7 +191,7 @@ static int of_fpga_region_get_bridges(struct fpga_region *region, continue; /* If node is a bridge, get it and add to list */ - ret = of_fpga_bridge_get_to_list(br, region->info, + ret = of_fpga_bridge_get_to_list(br, info, ®ion->bridge_list); /* If any of the bridges are in use, give up */ @@ -229,10 +228,16 @@ int fpga_region_program_fpga(struct fpga_region *region) goto err_put_region; } - ret = of_fpga_region_get_bridges(region, info); - if (ret) { - dev_err(dev, "failed to get FPGA bridges\n"); - goto err_unlock_mgr; + /* + * In some cases, we already have a list of bridges in the + * fpga region struct. Or we don't have any bridges. + */ + if (region->get_bridges) { + ret = region->get_bridges(region); + if (ret) { + dev_err(dev, "failed to get fpga region bridges\n"); + goto err_unlock_mgr; + } } ret = fpga_bridges_disable(®ion->bridge_list); @@ -259,7 +264,8 @@ int fpga_region_program_fpga(struct fpga_region *region) return 0; err_put_br: - fpga_bridges_put(®ion->bridge_list); + if (region->get_bridges) + fpga_bridges_put(®ion->bridge_list); err_unlock_mgr: fpga_mgr_unlock(region->mgr); err_put_region: @@ -522,39 +528,20 @@ static struct notifier_block fpga_region_of_nb = { .notifier_call = of_fpga_region_notify, }; -static int of_fpga_region_probe(struct platform_device *pdev) +int fpga_region_register(struct device *dev, struct fpga_region *region) { - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct fpga_region *region; - struct fpga_manager *mgr; int id, ret = 0; - mgr = of_fpga_region_get_mgr(np); - if (IS_ERR(mgr)) - return -EPROBE_DEFER; - - region = kzalloc(sizeof(*region), GFP_KERNEL); - if (!region) { - ret = -ENOMEM; - goto err_put_mgr; - } - - region->mgr = mgr; - id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); - if (id < 0) { - ret = id; - goto err_kfree; - } + if (id < 0) + return id; mutex_init(®ion->mutex); INIT_LIST_HEAD(®ion->bridge_list); - device_initialize(®ion->dev); region->dev.class = fpga_region_class; region->dev.parent = dev; - region->dev.of_node = np; + region->dev.of_node = dev->of_node; region->dev.id = id; dev_set_drvdata(dev, region); @@ -566,19 +553,58 @@ static int of_fpga_region_probe(struct platform_device *pdev) if (ret) goto err_remove; + return 0; + +err_remove: + ida_simple_remove(&fpga_region_ida, id); + return ret; +} +EXPORT_SYMBOL_GPL(fpga_region_register); + +int fpga_region_unregister(struct fpga_region *region) +{ + device_unregister(®ion->dev); + + return 0; +} +EXPORT_SYMBOL_GPL(fpga_region_unregister); + +static int of_fpga_region_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct fpga_region *region; + struct fpga_manager *mgr; + int ret; + + /* Find the FPGA mgr specified by region or parent region. */ + mgr = of_fpga_region_get_mgr(np); + if (IS_ERR(mgr)) + return -EPROBE_DEFER; + + region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); + if (!region) { + ret = -ENOMEM; + goto eprobe_mgr_put; + } + + region->mgr = mgr; + + /* Specify how to get bridges for this type of region. */ + region->get_bridges = of_fpga_region_get_bridges; + + ret = fpga_region_register(dev, region); + if (ret) + goto eprobe_mgr_put; + of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); dev_info(dev, "FPGA Region probed\n"); return 0; -err_remove: - ida_simple_remove(&fpga_region_ida, id); -err_kfree: - kfree(region); -err_put_mgr: +eprobe_mgr_put: fpga_mgr_put(mgr); - return ret; } @@ -586,7 +612,7 @@ static int of_fpga_region_remove(struct platform_device *pdev) { struct fpga_region *region = platform_get_drvdata(pdev); - device_unregister(®ion->dev); + fpga_region_unregister(region); fpga_mgr_put(region->mgr); return 0; @@ -606,7 +632,6 @@ static void fpga_region_dev_release(struct device *dev) struct fpga_region *region = to_fpga_region(dev); ida_simple_remove(&fpga_region_ida, region->dev.id); - kfree(region); } /** diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h index 8a355171406b..8c8a3249f96c 100644 --- a/include/linux/fpga/fpga-region.h +++ b/include/linux/fpga/fpga-region.h @@ -12,6 +12,8 @@ * @bridge_list: list of FPGA bridges specified in region * @mgr: FPGA manager * @info: FPGA image info + * @priv: private data + * @get_bridges: optional function to get bridges to a list */ struct fpga_region { struct device dev; @@ -19,10 +21,15 @@ struct fpga_region { struct list_head bridge_list; struct fpga_manager *mgr; struct fpga_image_info *info; + void *priv; + int (*get_bridges)(struct fpga_region *region); }; #define to_fpga_region(d) container_of(d, struct fpga_region, dev) int fpga_region_program_fpga(struct fpga_region *region); +int fpga_region_register(struct device *dev, struct fpga_region *region); +int fpga_region_unregister(struct fpga_region *region); + #endif /* _FPGA_REGION_H */ -- cgit v1.2.3 From 503d4b7a446b3838785fa7f21e339941a5d1c2d5 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:24 -0600 Subject: fpga: region: add fpga_region_class_find Add a function for searching the fpga-region class. This will be useful when device tree code is no longer in the same file that declares the fpga-region class. Another step in separating common FPGA region code from device tree support. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-region.c | 23 +++++++++++++++-------- include/linux/fpga/fpga-region.h | 5 ++++- 2 files changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 76db81de2cc0..5c0869576cd1 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -30,6 +30,20 @@ static DEFINE_IDA(fpga_region_ida); static struct class *fpga_region_class; +struct fpga_region *fpga_region_class_find( + struct device *start, const void *data, + int (*match)(struct device *, const void *)) +{ + struct device *dev; + + dev = class_find_device(fpga_region_class, start, data, match); + if (!dev) + return NULL; + + return to_fpga_region(dev); +} +EXPORT_SYMBOL_GPL(fpga_region_class_find); + static const struct of_device_id fpga_region_of_match[] = { { .compatible = "fpga-region", }, {}, @@ -51,14 +65,7 @@ static int fpga_region_of_node_match(struct device *dev, const void *data) */ static struct fpga_region *of_fpga_region_find(struct device_node *np) { - struct device *dev; - - dev = class_find_device(fpga_region_class, NULL, np, - fpga_region_of_node_match); - if (!dev) - return NULL; - - return to_fpga_region(dev); + return fpga_region_class_find(NULL, np, fpga_region_of_node_match); } /** diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h index 8c8a3249f96c..704844944631 100644 --- a/include/linux/fpga/fpga-region.h +++ b/include/linux/fpga/fpga-region.h @@ -27,8 +27,11 @@ struct fpga_region { #define to_fpga_region(d) container_of(d, struct fpga_region, dev) -int fpga_region_program_fpga(struct fpga_region *region); +struct fpga_region *fpga_region_class_find( + struct device *start, const void *data, + int (*match)(struct device *, const void *)); +int fpga_region_program_fpga(struct fpga_region *region); int fpga_region_register(struct device *dev, struct fpga_region *region); int fpga_region_unregister(struct fpga_region *region); -- cgit v1.2.3 From ef3acdd820752e0abb5f1ec899025967d0dccf3d Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:25 -0600 Subject: fpga: region: move device tree support to of-fpga-region.c Create of-fpga-region.c and move the following functions without modification from fpga-region.c. * of_fpga_region_find * of_fpga_region_get_mgr * of_fpga_region_get_bridges * child_regions_with_firmware * of_fpga_region_parse_ov * of_fpga_region_notify_pre_apply * of_fpga_region_notify_post_remove * of_fpga_region_notify * of_fpga_region_probe * of_fpga_region_remove Create two new functions with some code from fpga_region_init/exit. * of_fpga_region_init * of_fpga_region_exit Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/Kconfig | 15 +- drivers/fpga/Makefile | 1 + drivers/fpga/fpga-region.c | 452 +------------------------------------- drivers/fpga/of-fpga-region.c | 496 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 509 insertions(+), 455 deletions(-) create mode 100644 drivers/fpga/of-fpga-region.c (limited to 'drivers') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index ad5448f718b3..12bd1c760c32 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -13,10 +13,18 @@ if FPGA config FPGA_REGION tristate "FPGA Region" - depends on OF && FPGA_BRIDGE + depends on FPGA_BRIDGE + help + FPGA Region common code. A FPGA Region controls a FPGA Manager + and the FPGA Bridges associated with either a reconfigurable + region of an FPGA or a whole FPGA. + +config OF_FPGA_REGION + tristate "FPGA Region Device Tree Overlay Support" + depends on OF && FPGA_REGION help - FPGA Regions allow loading FPGA images under control of - the Device Tree. + Support for loading FPGA images by applying a Device Tree + overlay. config FPGA_MGR_ICE40_SPI tristate "Lattice iCE40 SPI" @@ -74,7 +82,6 @@ config FPGA_MGR_ZYNQ_FPGA config FPGA_BRIDGE tristate "FPGA Bridge Framework" - depends on OF help Say Y here if you want to support bridges connected between host processors and FPGAs or between FPGAs. diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index f98dcf1d89e1..3cb276a0f88d 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -26,3 +26,4 @@ obj-$(CONFIG_XILINX_PR_DECOUPLER) += xilinx-pr-decoupler.o # High Level Interfaces obj-$(CONFIG_FPGA_REGION) += fpga-region.o +obj-$(CONFIG_OF_FPGA_REGION) += of-fpga-region.o diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 5c0869576cd1..afc61885a601 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -2,6 +2,7 @@ * FPGA Region - Device Tree support for FPGA programming under Linux * * Copyright (C) 2013-2016 Altera Corporation + * Copyright (C) 2017 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -23,7 +24,6 @@ #include #include #include -#include #include #include @@ -44,30 +44,6 @@ struct fpga_region *fpga_region_class_find( } EXPORT_SYMBOL_GPL(fpga_region_class_find); -static const struct of_device_id fpga_region_of_match[] = { - { .compatible = "fpga-region", }, - {}, -}; -MODULE_DEVICE_TABLE(of, fpga_region_of_match); - -static int fpga_region_of_node_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - -/** - * of_fpga_region_find - find FPGA region - * @np: device node of FPGA Region - * - * Caller will need to put_device(®ion->dev) when done. - * - * Returns FPGA Region struct or NULL - */ -static struct fpga_region *of_fpga_region_find(struct device_node *np) -{ - return fpga_region_class_find(NULL, np, fpga_region_of_node_match); -} - /** * fpga_region_get - get an exclusive reference to a fpga region * @region: FPGA Region struct @@ -115,102 +91,6 @@ static void fpga_region_put(struct fpga_region *region) mutex_unlock(®ion->mutex); } -/** - * of_fpga_region_get_mgr - get reference for FPGA manager - * @np: device node of FPGA region - * - * Get FPGA Manager from "fpga-mgr" property or from ancestor region. - * - * Caller should call fpga_mgr_put() when done with manager. - * - * Return: fpga manager struct or IS_ERR() condition containing error code. - */ -static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) -{ - struct device_node *mgr_node; - struct fpga_manager *mgr; - - of_node_get(np); - while (np) { - if (of_device_is_compatible(np, "fpga-region")) { - mgr_node = of_parse_phandle(np, "fpga-mgr", 0); - if (mgr_node) { - mgr = of_fpga_mgr_get(mgr_node); - of_node_put(np); - return mgr; - } - } - np = of_get_next_parent(np); - } - of_node_put(np); - - return ERR_PTR(-EINVAL); -} - -/** - * of_fpga_region_get_bridges - create a list of bridges - * @region: FPGA region - * - * Create a list of bridges including the parent bridge and the bridges - * specified by "fpga-bridges" property. Note that the - * fpga_bridges_enable/disable/put functions are all fine with an empty list - * if that happens. - * - * Caller should call fpga_bridges_put(®ion->bridge_list) when - * done with the bridges. - * - * Return 0 for success (even if there are no bridges specified) - * or -EBUSY if any of the bridges are in use. - */ -static int of_fpga_region_get_bridges(struct fpga_region *region) -{ - struct device *dev = ®ion->dev; - struct device_node *region_np = dev->of_node; - struct fpga_image_info *info = region->info; - struct device_node *br, *np, *parent_br = NULL; - int i, ret; - - /* If parent is a bridge, add to list */ - ret = of_fpga_bridge_get_to_list(region_np->parent, info, - ®ion->bridge_list); - - /* -EBUSY means parent is a bridge that is under use. Give up. */ - if (ret == -EBUSY) - return ret; - - /* Zero return code means parent was a bridge and was added to list. */ - if (!ret) - parent_br = region_np->parent; - - /* If overlay has a list of bridges, use it. */ - if (of_parse_phandle(info->overlay, "fpga-bridges", 0)) - np = info->overlay; - else - np = region_np; - - for (i = 0; ; i++) { - br = of_parse_phandle(np, "fpga-bridges", i); - if (!br) - break; - - /* If parent bridge is in list, skip it. */ - if (br == parent_br) - continue; - - /* If node is a bridge, get it and add to list */ - ret = of_fpga_bridge_get_to_list(br, info, - ®ion->bridge_list); - - /* If any of the bridges are in use, give up */ - if (ret == -EBUSY) { - fpga_bridges_put(®ion->bridge_list); - return -EBUSY; - } - } - - return 0; -} - /** * fpga_region_program_fpga - program FPGA * @region: FPGA region @@ -282,259 +162,6 @@ err_put_region: } EXPORT_SYMBOL_GPL(fpga_region_program_fpga); -/** - * child_regions_with_firmware - * @overlay: device node of the overlay - * - * If the overlay adds child FPGA regions, they are not allowed to have - * firmware-name property. - * - * Return 0 for OK or -EINVAL if child FPGA region adds firmware-name. - */ -static int child_regions_with_firmware(struct device_node *overlay) -{ - struct device_node *child_region; - const char *child_firmware_name; - int ret = 0; - - of_node_get(overlay); - - child_region = of_find_matching_node(overlay, fpga_region_of_match); - while (child_region) { - if (!of_property_read_string(child_region, "firmware-name", - &child_firmware_name)) { - ret = -EINVAL; - break; - } - child_region = of_find_matching_node(child_region, - fpga_region_of_match); - } - - of_node_put(child_region); - - if (ret) - pr_err("firmware-name not allowed in child FPGA region: %pOF", - child_region); - - return ret; -} - -/** - * of_fpga_region_parse_ov - parse and check overlay applied to region - * - * @region: FPGA region - * @overlay: overlay applied to the FPGA region - * - * Given an overlay applied to a FPGA region, parse the FPGA image specific - * info in the overlay and do some checking. - * - * Returns: - * NULL if overlay doesn't direct us to program the FPGA. - * fpga_image_info struct if there is an image to program. - * error code for invalid overlay. - */ -static struct fpga_image_info *of_fpga_region_parse_ov( - struct fpga_region *region, - struct device_node *overlay) -{ - struct device *dev = ®ion->dev; - struct fpga_image_info *info; - const char *firmware_name; - int ret; - - if (region->info) { - dev_err(dev, "Region already has overlay applied.\n"); - return ERR_PTR(-EINVAL); - } - - /* - * Reject overlay if child FPGA Regions added in the overlay have - * firmware-name property (would mean that an FPGA region that has - * not been added to the live tree yet is doing FPGA programming). - */ - ret = child_regions_with_firmware(overlay); - if (ret) - return ERR_PTR(ret); - - info = fpga_image_info_alloc(dev); - if (!info) - return ERR_PTR(-ENOMEM); - - info->overlay = overlay; - - /* Read FPGA region properties from the overlay */ - if (of_property_read_bool(overlay, "partial-fpga-config")) - info->flags |= FPGA_MGR_PARTIAL_RECONFIG; - - if (of_property_read_bool(overlay, "external-fpga-config")) - info->flags |= FPGA_MGR_EXTERNAL_CONFIG; - - if (of_property_read_bool(overlay, "encrypted-fpga-config")) - info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM; - - if (!of_property_read_string(overlay, "firmware-name", - &firmware_name)) { - info->firmware_name = devm_kstrdup(dev, firmware_name, - GFP_KERNEL); - if (!info->firmware_name) - return ERR_PTR(-ENOMEM); - } - - of_property_read_u32(overlay, "region-unfreeze-timeout-us", - &info->enable_timeout_us); - - of_property_read_u32(overlay, "region-freeze-timeout-us", - &info->disable_timeout_us); - - of_property_read_u32(overlay, "config-complete-timeout-us", - &info->config_complete_timeout_us); - - /* If overlay is not programming the FPGA, don't need FPGA image info */ - if (!info->firmware_name) { - ret = 0; - goto ret_no_info; - } - - /* - * If overlay informs us FPGA was externally programmed, specifying - * firmware here would be ambiguous. - */ - if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) { - dev_err(dev, "error: specified firmware and external-fpga-config"); - ret = -EINVAL; - goto ret_no_info; - } - - return info; -ret_no_info: - fpga_image_info_free(info); - return ERR_PTR(ret); -} - -/** - * of_fpga_region_notify_pre_apply - pre-apply overlay notification - * - * @region: FPGA region that the overlay was applied to - * @nd: overlay notification data - * - * Called when an overlay targeted to a FPGA Region is about to be applied. - * Parses the overlay for properties that influence how the FPGA will be - * programmed and does some checking. If the checks pass, programs the FPGA. - * If the checks fail, overlay is rejected and does not get added to the - * live tree. - * - * Returns 0 for success or negative error code for failure. - */ -static int of_fpga_region_notify_pre_apply(struct fpga_region *region, - struct of_overlay_notify_data *nd) -{ - struct device *dev = ®ion->dev; - struct fpga_image_info *info; - int ret; - - if (region->info) { - dev_err(dev, "Region already has overlay applied.\n"); - return -EINVAL; - } - - info = of_fpga_region_parse_ov(region, nd->overlay); - if (IS_ERR(info)) - return PTR_ERR(info); - - if (!info) - return 0; - - region->info = info; - ret = fpga_region_program_fpga(region); - if (ret) { - /* error; reject overlay */ - fpga_image_info_free(info); - region->info = NULL; - } - - return ret; -} - -/** - * of_fpga_region_notify_post_remove - post-remove overlay notification - * - * @region: FPGA region that was targeted by the overlay that was removed - * @nd: overlay notification data - * - * Called after an overlay has been removed if the overlay's target was a - * FPGA region. - */ -static void of_fpga_region_notify_post_remove(struct fpga_region *region, - struct of_overlay_notify_data *nd) -{ - fpga_bridges_disable(®ion->bridge_list); - fpga_bridges_put(®ion->bridge_list); - fpga_image_info_free(region->info); - region->info = NULL; -} - -/** - * of_fpga_region_notify - reconfig notifier for dynamic DT changes - * @nb: notifier block - * @action: notifier action - * @arg: reconfig data - * - * This notifier handles programming a FPGA when a "firmware-name" property is - * added to a fpga-region. - * - * Returns NOTIFY_OK or error if FPGA programming fails. - */ -static int of_fpga_region_notify(struct notifier_block *nb, - unsigned long action, void *arg) -{ - struct of_overlay_notify_data *nd = arg; - struct fpga_region *region; - int ret; - - switch (action) { - case OF_OVERLAY_PRE_APPLY: - pr_debug("%s OF_OVERLAY_PRE_APPLY\n", __func__); - break; - case OF_OVERLAY_POST_APPLY: - pr_debug("%s OF_OVERLAY_POST_APPLY\n", __func__); - return NOTIFY_OK; /* not for us */ - case OF_OVERLAY_PRE_REMOVE: - pr_debug("%s OF_OVERLAY_PRE_REMOVE\n", __func__); - return NOTIFY_OK; /* not for us */ - case OF_OVERLAY_POST_REMOVE: - pr_debug("%s OF_OVERLAY_POST_REMOVE\n", __func__); - break; - default: /* should not happen */ - return NOTIFY_OK; - } - - region = of_fpga_region_find(nd->target); - if (!region) - return NOTIFY_OK; - - ret = 0; - switch (action) { - case OF_OVERLAY_PRE_APPLY: - ret = of_fpga_region_notify_pre_apply(region, nd); - break; - - case OF_OVERLAY_POST_REMOVE: - of_fpga_region_notify_post_remove(region, nd); - break; - } - - put_device(®ion->dev); - - if (ret) - return notifier_from_errno(ret); - - return NOTIFY_OK; -} - -static struct notifier_block fpga_region_of_nb = { - .notifier_call = of_fpga_region_notify, -}; - int fpga_region_register(struct device *dev, struct fpga_region *region) { int id, ret = 0; @@ -576,64 +203,6 @@ int fpga_region_unregister(struct fpga_region *region) } EXPORT_SYMBOL_GPL(fpga_region_unregister); -static int of_fpga_region_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct fpga_region *region; - struct fpga_manager *mgr; - int ret; - - /* Find the FPGA mgr specified by region or parent region. */ - mgr = of_fpga_region_get_mgr(np); - if (IS_ERR(mgr)) - return -EPROBE_DEFER; - - region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); - if (!region) { - ret = -ENOMEM; - goto eprobe_mgr_put; - } - - region->mgr = mgr; - - /* Specify how to get bridges for this type of region. */ - region->get_bridges = of_fpga_region_get_bridges; - - ret = fpga_region_register(dev, region); - if (ret) - goto eprobe_mgr_put; - - of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); - - dev_info(dev, "FPGA Region probed\n"); - - return 0; - -eprobe_mgr_put: - fpga_mgr_put(mgr); - return ret; -} - -static int of_fpga_region_remove(struct platform_device *pdev) -{ - struct fpga_region *region = platform_get_drvdata(pdev); - - fpga_region_unregister(region); - fpga_mgr_put(region->mgr); - - return 0; -} - -static struct platform_driver of_fpga_region_driver = { - .probe = of_fpga_region_probe, - .remove = of_fpga_region_remove, - .driver = { - .name = "fpga-region", - .of_match_table = of_match_ptr(fpga_region_of_match), - }, -}; - static void fpga_region_dev_release(struct device *dev) { struct fpga_region *region = to_fpga_region(dev); @@ -647,36 +216,17 @@ static void fpga_region_dev_release(struct device *dev) */ static int __init fpga_region_init(void) { - int ret; - fpga_region_class = class_create(THIS_MODULE, "fpga_region"); if (IS_ERR(fpga_region_class)) return PTR_ERR(fpga_region_class); fpga_region_class->dev_release = fpga_region_dev_release; - ret = of_overlay_notifier_register(&fpga_region_of_nb); - if (ret) - goto err_class; - - ret = platform_driver_register(&of_fpga_region_driver); - if (ret) - goto err_plat; - return 0; - -err_plat: - of_overlay_notifier_unregister(&fpga_region_of_nb); -err_class: - class_destroy(fpga_region_class); - ida_destroy(&fpga_region_ida); - return ret; } static void __exit fpga_region_exit(void) { - platform_driver_unregister(&of_fpga_region_driver); - of_overlay_notifier_unregister(&fpga_region_of_nb); class_destroy(fpga_region_class); ida_destroy(&fpga_region_ida); } diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c new file mode 100644 index 000000000000..1533506ef0e4 --- /dev/null +++ b/drivers/fpga/of-fpga-region.c @@ -0,0 +1,496 @@ +/* + * FPGA Region - Device Tree support for FPGA programming under Linux + * + * Copyright (C) 2013-2016 Altera Corporation + * Copyright (C) 2017 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct of_device_id fpga_region_of_match[] = { + { .compatible = "fpga-region", }, + {}, +}; +MODULE_DEVICE_TABLE(of, fpga_region_of_match); + +static int fpga_region_of_node_match(struct device *dev, const void *data) +{ + return dev->of_node == data; +} + +/** + * of_fpga_region_find - find FPGA region + * @np: device node of FPGA Region + * + * Caller will need to put_device(®ion->dev) when done. + * + * Returns FPGA Region struct or NULL + */ +static struct fpga_region *of_fpga_region_find(struct device_node *np) +{ + return fpga_region_class_find(NULL, np, fpga_region_of_node_match); +} + +/** + * of_fpga_region_get_mgr - get reference for FPGA manager + * @np: device node of FPGA region + * + * Get FPGA Manager from "fpga-mgr" property or from ancestor region. + * + * Caller should call fpga_mgr_put() when done with manager. + * + * Return: fpga manager struct or IS_ERR() condition containing error code. + */ +static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) +{ + struct device_node *mgr_node; + struct fpga_manager *mgr; + + of_node_get(np); + while (np) { + if (of_device_is_compatible(np, "fpga-region")) { + mgr_node = of_parse_phandle(np, "fpga-mgr", 0); + if (mgr_node) { + mgr = of_fpga_mgr_get(mgr_node); + of_node_put(np); + return mgr; + } + } + np = of_get_next_parent(np); + } + of_node_put(np); + + return ERR_PTR(-EINVAL); +} + +/** + * of_fpga_region_get_bridges - create a list of bridges + * @region: FPGA region + * + * Create a list of bridges including the parent bridge and the bridges + * specified by "fpga-bridges" property. Note that the + * fpga_bridges_enable/disable/put functions are all fine with an empty list + * if that happens. + * + * Caller should call fpga_bridges_put(®ion->bridge_list) when + * done with the bridges. + * + * Return 0 for success (even if there are no bridges specified) + * or -EBUSY if any of the bridges are in use. + */ +static int of_fpga_region_get_bridges(struct fpga_region *region) +{ + struct device *dev = ®ion->dev; + struct device_node *region_np = dev->of_node; + struct fpga_image_info *info = region->info; + struct device_node *br, *np, *parent_br = NULL; + int i, ret; + + /* If parent is a bridge, add to list */ + ret = of_fpga_bridge_get_to_list(region_np->parent, info, + ®ion->bridge_list); + + /* -EBUSY means parent is a bridge that is under use. Give up. */ + if (ret == -EBUSY) + return ret; + + /* Zero return code means parent was a bridge and was added to list. */ + if (!ret) + parent_br = region_np->parent; + + /* If overlay has a list of bridges, use it. */ + if (of_parse_phandle(info->overlay, "fpga-bridges", 0)) + np = info->overlay; + else + np = region_np; + + for (i = 0; ; i++) { + br = of_parse_phandle(np, "fpga-bridges", i); + if (!br) + break; + + /* If parent bridge is in list, skip it. */ + if (br == parent_br) + continue; + + /* If node is a bridge, get it and add to list */ + ret = of_fpga_bridge_get_to_list(br, info, + ®ion->bridge_list); + + /* If any of the bridges are in use, give up */ + if (ret == -EBUSY) { + fpga_bridges_put(®ion->bridge_list); + return -EBUSY; + } + } + + return 0; +} + +/** + * child_regions_with_firmware + * @overlay: device node of the overlay + * + * If the overlay adds child FPGA regions, they are not allowed to have + * firmware-name property. + * + * Return 0 for OK or -EINVAL if child FPGA region adds firmware-name. + */ +static int child_regions_with_firmware(struct device_node *overlay) +{ + struct device_node *child_region; + const char *child_firmware_name; + int ret = 0; + + of_node_get(overlay); + + child_region = of_find_matching_node(overlay, fpga_region_of_match); + while (child_region) { + if (!of_property_read_string(child_region, "firmware-name", + &child_firmware_name)) { + ret = -EINVAL; + break; + } + child_region = of_find_matching_node(child_region, + fpga_region_of_match); + } + + of_node_put(child_region); + + if (ret) + pr_err("firmware-name not allowed in child FPGA region: %pOF", + child_region); + + return ret; +} + +/** + * of_fpga_region_parse_ov - parse and check overlay applied to region + * + * @region: FPGA region + * @overlay: overlay applied to the FPGA region + * + * Given an overlay applied to a FPGA region, parse the FPGA image specific + * info in the overlay and do some checking. + * + * Returns: + * NULL if overlay doesn't direct us to program the FPGA. + * fpga_image_info struct if there is an image to program. + * error code for invalid overlay. + */ +static struct fpga_image_info *of_fpga_region_parse_ov( + struct fpga_region *region, + struct device_node *overlay) +{ + struct device *dev = ®ion->dev; + struct fpga_image_info *info; + const char *firmware_name; + int ret; + + if (region->info) { + dev_err(dev, "Region already has overlay applied.\n"); + return ERR_PTR(-EINVAL); + } + + /* + * Reject overlay if child FPGA Regions added in the overlay have + * firmware-name property (would mean that an FPGA region that has + * not been added to the live tree yet is doing FPGA programming). + */ + ret = child_regions_with_firmware(overlay); + if (ret) + return ERR_PTR(ret); + + info = fpga_image_info_alloc(dev); + if (!info) + return ERR_PTR(-ENOMEM); + + info->overlay = overlay; + + /* Read FPGA region properties from the overlay */ + if (of_property_read_bool(overlay, "partial-fpga-config")) + info->flags |= FPGA_MGR_PARTIAL_RECONFIG; + + if (of_property_read_bool(overlay, "external-fpga-config")) + info->flags |= FPGA_MGR_EXTERNAL_CONFIG; + + if (of_property_read_bool(overlay, "encrypted-fpga-config")) + info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM; + + if (!of_property_read_string(overlay, "firmware-name", + &firmware_name)) { + info->firmware_name = devm_kstrdup(dev, firmware_name, + GFP_KERNEL); + if (!info->firmware_name) + return ERR_PTR(-ENOMEM); + } + + of_property_read_u32(overlay, "region-unfreeze-timeout-us", + &info->enable_timeout_us); + + of_property_read_u32(overlay, "region-freeze-timeout-us", + &info->disable_timeout_us); + + of_property_read_u32(overlay, "config-complete-timeout-us", + &info->config_complete_timeout_us); + + /* If overlay is not programming the FPGA, don't need FPGA image info */ + if (!info->firmware_name) { + ret = 0; + goto ret_no_info; + } + + /* + * If overlay informs us FPGA was externally programmed, specifying + * firmware here would be ambiguous. + */ + if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) { + dev_err(dev, "error: specified firmware and external-fpga-config"); + ret = -EINVAL; + goto ret_no_info; + } + + return info; +ret_no_info: + fpga_image_info_free(info); + return ERR_PTR(ret); +} + +/** + * of_fpga_region_notify_pre_apply - pre-apply overlay notification + * + * @region: FPGA region that the overlay was applied to + * @nd: overlay notification data + * + * Called when an overlay targeted to a FPGA Region is about to be applied. + * Parses the overlay for properties that influence how the FPGA will be + * programmed and does some checking. If the checks pass, programs the FPGA. + * If the checks fail, overlay is rejected and does not get added to the + * live tree. + * + * Returns 0 for success or negative error code for failure. + */ +static int of_fpga_region_notify_pre_apply(struct fpga_region *region, + struct of_overlay_notify_data *nd) +{ + struct device *dev = ®ion->dev; + struct fpga_image_info *info; + int ret; + + if (region->info) { + dev_err(dev, "Region already has overlay applied.\n"); + return -EINVAL; + } + + info = of_fpga_region_parse_ov(region, nd->overlay); + if (IS_ERR(info)) + return PTR_ERR(info); + + if (!info) + return 0; + + region->info = info; + ret = fpga_region_program_fpga(region); + if (ret) { + /* error; reject overlay */ + fpga_image_info_free(info); + region->info = NULL; + } + + return ret; +} + +/** + * of_fpga_region_notify_post_remove - post-remove overlay notification + * + * @region: FPGA region that was targeted by the overlay that was removed + * @nd: overlay notification data + * + * Called after an overlay has been removed if the overlay's target was a + * FPGA region. + */ +static void of_fpga_region_notify_post_remove(struct fpga_region *region, + struct of_overlay_notify_data *nd) +{ + fpga_bridges_disable(®ion->bridge_list); + fpga_bridges_put(®ion->bridge_list); + fpga_image_info_free(region->info); + region->info = NULL; +} + +/** + * of_fpga_region_notify - reconfig notifier for dynamic DT changes + * @nb: notifier block + * @action: notifier action + * @arg: reconfig data + * + * This notifier handles programming a FPGA when a "firmware-name" property is + * added to a fpga-region. + * + * Returns NOTIFY_OK or error if FPGA programming fails. + */ +static int of_fpga_region_notify(struct notifier_block *nb, + unsigned long action, void *arg) +{ + struct of_overlay_notify_data *nd = arg; + struct fpga_region *region; + int ret; + + switch (action) { + case OF_OVERLAY_PRE_APPLY: + pr_debug("%s OF_OVERLAY_PRE_APPLY\n", __func__); + break; + case OF_OVERLAY_POST_APPLY: + pr_debug("%s OF_OVERLAY_POST_APPLY\n", __func__); + return NOTIFY_OK; /* not for us */ + case OF_OVERLAY_PRE_REMOVE: + pr_debug("%s OF_OVERLAY_PRE_REMOVE\n", __func__); + return NOTIFY_OK; /* not for us */ + case OF_OVERLAY_POST_REMOVE: + pr_debug("%s OF_OVERLAY_POST_REMOVE\n", __func__); + break; + default: /* should not happen */ + return NOTIFY_OK; + } + + region = of_fpga_region_find(nd->target); + if (!region) + return NOTIFY_OK; + + ret = 0; + switch (action) { + case OF_OVERLAY_PRE_APPLY: + ret = of_fpga_region_notify_pre_apply(region, nd); + break; + + case OF_OVERLAY_POST_REMOVE: + of_fpga_region_notify_post_remove(region, nd); + break; + } + + put_device(®ion->dev); + + if (ret) + return notifier_from_errno(ret); + + return NOTIFY_OK; +} + +static struct notifier_block fpga_region_of_nb = { + .notifier_call = of_fpga_region_notify, +}; + +static int of_fpga_region_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct fpga_region *region; + struct fpga_manager *mgr; + int ret; + + /* Find the FPGA mgr specified by region or parent region. */ + mgr = of_fpga_region_get_mgr(np); + if (IS_ERR(mgr)) + return -EPROBE_DEFER; + + region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); + if (!region) { + ret = -ENOMEM; + goto eprobe_mgr_put; + } + + region->mgr = mgr; + + /* Specify how to get bridges for this type of region. */ + region->get_bridges = of_fpga_region_get_bridges; + + ret = fpga_region_register(dev, region); + if (ret) + goto eprobe_mgr_put; + + of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); + + dev_info(dev, "FPGA Region probed\n"); + + return 0; + +eprobe_mgr_put: + fpga_mgr_put(mgr); + return ret; +} + +static int of_fpga_region_remove(struct platform_device *pdev) +{ + struct fpga_region *region = platform_get_drvdata(pdev); + + fpga_region_unregister(region); + fpga_mgr_put(region->mgr); + + return 0; +} + +static struct platform_driver of_fpga_region_driver = { + .probe = of_fpga_region_probe, + .remove = of_fpga_region_remove, + .driver = { + .name = "of-fpga-region", + .of_match_table = of_match_ptr(fpga_region_of_match), + }, +}; + +/** + * fpga_region_init - init function for fpga_region class + * Creates the fpga_region class and registers a reconfig notifier. + */ +static int __init of_fpga_region_init(void) +{ + int ret; + + ret = of_overlay_notifier_register(&fpga_region_of_nb); + if (ret) + return ret; + + ret = platform_driver_register(&of_fpga_region_driver); + if (ret) + goto err_plat; + + return 0; + +err_plat: + of_overlay_notifier_unregister(&fpga_region_of_nb); + return ret; +} + +static void __exit of_fpga_region_exit(void) +{ + platform_driver_unregister(&of_fpga_region_driver); + of_overlay_notifier_unregister(&fpga_region_of_nb); +} + +subsys_initcall(of_fpga_region_init); +module_exit(of_fpga_region_exit); + +MODULE_DESCRIPTION("FPGA Region"); +MODULE_AUTHOR("Alan Tull "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 8a54167925341ab2a9c3133618dbddfc1a46f8aa Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:26 -0600 Subject: fpga: of-fpga-region: accept overlays that don't program FPGA The FPGA may already have a static image programmed when Linux boots. In that case a DT overlay may be used to add the devices that already exist. This commit allows that by shuffling the order of some checks. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/of-fpga-region.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index 1533506ef0e4..c6b21194dcbc 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -298,18 +298,19 @@ static int of_fpga_region_notify_pre_apply(struct fpga_region *region, struct fpga_image_info *info; int ret; - if (region->info) { - dev_err(dev, "Region already has overlay applied.\n"); - return -EINVAL; - } - info = of_fpga_region_parse_ov(region, nd->overlay); if (IS_ERR(info)) return PTR_ERR(info); + /* If overlay doesn't program the FPGA, accept it anyway. */ if (!info) return 0; + if (region->info) { + dev_err(dev, "Region already has overlay applied.\n"); + return -EINVAL; + } + region->info = info; ret = fpga_region_program_fpga(region); if (ret) { -- cgit v1.2.3 From 84e93f1d4f45a510926cb9225e49a4ccff5dd868 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:27 -0600 Subject: fpga: clean up fpga Kconfig The fpga menuconfig has gotten messy. The bridges and managers are mixed together. * Separate the bridges and things dependent on CONFIG_FPGA_BRIDGE from the managers. * Group the managers by vendor in order that they were added to the kernel. The following is what the menuconfig ends up looking like more or less (platform dependencies are hiding some of these on any given platform). --- FPGA Configuration Framework <*> Altera SOCFPGA FPGA Manager <*> Altera SoCFPGA Arria10 <*> Altera Partial Reconfiguration IP Core <*> Platform support of Altera Partial Reconfiguration IP Core <*> Altera FPGA Passive Serial over SPI <*> Altera Arria-V/Cyclone-V/Stratix-V CvP FPGA Manager <*> Xilinx Zynq FPGA <*> Xilinx Configuration over Slave Serial (SPI) <*> Lattice iCE40 SPI <*> Technologic Systems TS-73xx SBC FPGA Manager <*> FPGA Bridge Framework <*> Altera SoCFPGA FPGA Bridges <*> Altera FPGA Freeze Bridge <*> Xilinx LogiCORE PR Decoupler <*> FPGA Region <*> FPGA Region Device Tree Overlay Support Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/Kconfig | 108 +++++++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 12bd1c760c32..f47ef848bcd0 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -11,33 +11,30 @@ menuconfig FPGA if FPGA -config FPGA_REGION - tristate "FPGA Region" - depends on FPGA_BRIDGE +config FPGA_MGR_SOCFPGA + tristate "Altera SOCFPGA FPGA Manager" + depends on ARCH_SOCFPGA || COMPILE_TEST help - FPGA Region common code. A FPGA Region controls a FPGA Manager - and the FPGA Bridges associated with either a reconfigurable - region of an FPGA or a whole FPGA. + FPGA manager driver support for Altera SOCFPGA. -config OF_FPGA_REGION - tristate "FPGA Region Device Tree Overlay Support" - depends on OF && FPGA_REGION +config FPGA_MGR_SOCFPGA_A10 + tristate "Altera SoCFPGA Arria10" + depends on ARCH_SOCFPGA || COMPILE_TEST + select REGMAP_MMIO help - Support for loading FPGA images by applying a Device Tree - overlay. + FPGA manager driver support for Altera Arria10 SoCFPGA. -config FPGA_MGR_ICE40_SPI - tristate "Lattice iCE40 SPI" - depends on OF && SPI - help - FPGA manager driver support for Lattice iCE40 FPGAs over SPI. +config ALTERA_PR_IP_CORE + tristate "Altera Partial Reconfiguration IP Core" + help + Core driver support for Altera Partial Reconfiguration IP component -config FPGA_MGR_ALTERA_CVP - tristate "Altera Arria-V/Cyclone-V/Stratix-V CvP FPGA Manager" - depends on PCI +config ALTERA_PR_IP_CORE_PLAT + tristate "Platform support of Altera Partial Reconfiguration IP Core" + depends on ALTERA_PR_IP_CORE && OF && HAS_IOMEM help - FPGA manager driver support for Arria-V, Cyclone-V, Stratix-V - and Arria 10 Altera FPGAs using the CvP interface over PCIe. + Platform driver support for Altera Partial Reconfiguration IP + component config FPGA_MGR_ALTERA_PS_SPI tristate "Altera FPGA Passive Serial over SPI" @@ -46,25 +43,19 @@ config FPGA_MGR_ALTERA_PS_SPI FPGA manager driver support for Altera Arria/Cyclone/Stratix using the passive serial interface over SPI. -config FPGA_MGR_SOCFPGA - tristate "Altera SOCFPGA FPGA Manager" - depends on ARCH_SOCFPGA || COMPILE_TEST - help - FPGA manager driver support for Altera SOCFPGA. - -config FPGA_MGR_SOCFPGA_A10 - tristate "Altera SoCFPGA Arria10" - depends on ARCH_SOCFPGA || COMPILE_TEST - select REGMAP_MMIO +config FPGA_MGR_ALTERA_CVP + tristate "Altera Arria-V/Cyclone-V/Stratix-V CvP FPGA Manager" + depends on PCI help - FPGA manager driver support for Altera Arria10 SoCFPGA. + FPGA manager driver support for Arria-V, Cyclone-V, Stratix-V + and Arria 10 Altera FPGAs using the CvP interface over PCIe. -config FPGA_MGR_TS73XX - tristate "Technologic Systems TS-73xx SBC FPGA Manager" - depends on ARCH_EP93XX && MACH_TS72XX +config FPGA_MGR_ZYNQ_FPGA + tristate "Xilinx Zynq FPGA" + depends on ARCH_ZYNQ || COMPILE_TEST + depends on HAS_DMA help - FPGA manager driver support for the Altera Cyclone II FPGA - present on the TS-73xx SBC boards. + FPGA manager driver support for Xilinx Zynq FPGAs. config FPGA_MGR_XILINX_SPI tristate "Xilinx Configuration over Slave Serial (SPI)" @@ -73,12 +64,18 @@ config FPGA_MGR_XILINX_SPI FPGA manager driver support for Xilinx FPGA configuration over slave serial interface. -config FPGA_MGR_ZYNQ_FPGA - tristate "Xilinx Zynq FPGA" - depends on ARCH_ZYNQ || COMPILE_TEST - depends on HAS_DMA +config FPGA_MGR_ICE40_SPI + tristate "Lattice iCE40 SPI" + depends on OF && SPI help - FPGA manager driver support for Xilinx Zynq FPGAs. + FPGA manager driver support for Lattice iCE40 FPGAs over SPI. + +config FPGA_MGR_TS73XX + tristate "Technologic Systems TS-73xx SBC FPGA Manager" + depends on ARCH_EP93XX && MACH_TS72XX + help + FPGA manager driver support for the Altera Cyclone II FPGA + present on the TS-73xx SBC boards. config FPGA_BRIDGE tristate "FPGA Bridge Framework" @@ -102,18 +99,6 @@ config ALTERA_FREEZE_BRIDGE isolate one region of the FPGA from the busses while that region is being reprogrammed. -config ALTERA_PR_IP_CORE - tristate "Altera Partial Reconfiguration IP Core" - help - Core driver support for Altera Partial Reconfiguration IP component - -config ALTERA_PR_IP_CORE_PLAT - tristate "Platform support of Altera Partial Reconfiguration IP Core" - depends on ALTERA_PR_IP_CORE && OF && HAS_IOMEM - help - Platform driver support for Altera Partial Reconfiguration IP - component - config XILINX_PR_DECOUPLER tristate "Xilinx LogiCORE PR Decoupler" depends on FPGA_BRIDGE @@ -124,4 +109,19 @@ config XILINX_PR_DECOUPLER region of the FPGA from the busses while that region is being reprogrammed during partial reconfig. +config FPGA_REGION + tristate "FPGA Region" + depends on FPGA_BRIDGE + help + FPGA Region common code. A FPGA Region controls a FPGA Manager + and the FPGA Bridges associated with either a reconfigurable + region of an FPGA or a whole FPGA. + +config OF_FPGA_REGION + tristate "FPGA Region Device Tree Overlay Support" + depends on OF && FPGA_REGION + help + Support for loading FPGA images by applying a Device Tree + overlay. + endif # FPGA -- cgit v1.2.3 From 845089bbf589be75143d0c9fb326d5595c1b5787 Mon Sep 17 00:00:00 2001 From: Alan Tull Date: Wed, 15 Nov 2017 14:20:28 -0600 Subject: fpga: add attribute groups Make it easy to add attributes to low level FPGA drivers the right way. Add attribute groups pointers to structures that are used when registering a manager, bridge, or group. When the low level driver registers, set the device attribute group. The attributes are created in device_add. Signed-off-by: Alan Tull Acked-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-bridge.c | 1 + drivers/fpga/fpga-mgr.c | 1 + drivers/fpga/fpga-region.c | 1 + include/linux/fpga/fpga-bridge.h | 2 ++ include/linux/fpga/fpga-mgr.h | 2 ++ include/linux/fpga/fpga-region.h | 2 ++ 6 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 0dfe9d78cee2..e693c3607a14 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -367,6 +367,7 @@ int fpga_bridge_register(struct device *dev, const char *name, bridge->priv = priv; device_initialize(&bridge->dev); + bridge->dev.groups = br_ops->groups; bridge->dev.class = fpga_bridge_class; bridge->dev.parent = dev; bridge->dev.of_node = dev->of_node; diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index d27e8d2a149c..223f2401939b 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -569,6 +569,7 @@ int fpga_mgr_register(struct device *dev, const char *name, device_initialize(&mgr->dev); mgr->dev.class = fpga_mgr_class; + mgr->dev.groups = mops->groups; mgr->dev.parent = dev; mgr->dev.of_node = dev->of_node; mgr->dev.id = id; diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index afc61885a601..edab2a2e03ef 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -173,6 +173,7 @@ int fpga_region_register(struct device *dev, struct fpga_region *region) mutex_init(®ion->mutex); INIT_LIST_HEAD(®ion->bridge_list); device_initialize(®ion->dev); + region->dev.groups = region->groups; region->dev.class = fpga_region_class; region->dev.parent = dev; region->dev.of_node = dev->of_node; diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h index 6ca41f8f949f..3694821a6d2d 100644 --- a/include/linux/fpga/fpga-bridge.h +++ b/include/linux/fpga/fpga-bridge.h @@ -13,11 +13,13 @@ struct fpga_bridge; * @enable_show: returns the FPGA bridge's status * @enable_set: set a FPGA bridge as enabled or disabled * @fpga_bridge_remove: set FPGA into a specific state during driver remove + * @groups: optional attribute groups. */ struct fpga_bridge_ops { int (*enable_show)(struct fpga_bridge *bridge); int (*enable_set)(struct fpga_bridge *bridge, bool enable); void (*fpga_bridge_remove)(struct fpga_bridge *bridge); + const struct attribute_group **groups; }; /** diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h index 4fb706bd9aba..3c6de23aabdf 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -115,6 +115,7 @@ struct fpga_image_info { * @write_sg: write the scatter list of configuration data to the FPGA * @write_complete: set FPGA to operating state after writing is done * @fpga_remove: optional: Set FPGA into a specific state during driver remove + * @groups: optional attribute groups. * * fpga_manager_ops are the low level functions implemented by a specific * fpga manager driver. The optional ones are tested for NULL before being @@ -131,6 +132,7 @@ struct fpga_manager_ops { int (*write_complete)(struct fpga_manager *mgr, struct fpga_image_info *info); void (*fpga_remove)(struct fpga_manager *mgr); + const struct attribute_group **groups; }; /** diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h index 704844944631..b6520318ab9c 100644 --- a/include/linux/fpga/fpga-region.h +++ b/include/linux/fpga/fpga-region.h @@ -14,6 +14,7 @@ * @info: FPGA image info * @priv: private data * @get_bridges: optional function to get bridges to a list + * @groups: optional attribute groups. */ struct fpga_region { struct device dev; @@ -23,6 +24,7 @@ struct fpga_region { struct fpga_image_info *info; void *priv; int (*get_bridges)(struct fpga_region *region); + const struct attribute_group **groups; }; #define to_fpga_region(d) container_of(d, struct fpga_region, dev) -- cgit v1.2.3 From 5f76c6f313bffbf372c0722582e7bd509f0d3510 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 15 Nov 2017 16:33:10 -0600 Subject: fpga: fpga-mgr: remove unnecessary code in __fpga_mgr_get Notice that mgr = to_fpga_manager(dev); expands to: mgr = container_of(dev, struct fpga_manager, dev); and container_of is never null, so this null check is unnecessary. Addresses-Coverity-ID: 1397916 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-mgr.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 223f2401939b..9939d2cbc9a6 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -412,8 +412,6 @@ static struct fpga_manager *__fpga_mgr_get(struct device *dev) struct fpga_manager *mgr; mgr = to_fpga_manager(dev); - if (!mgr) - goto err_dev; if (!try_module_get(dev->parent->driver->owner)) goto err_dev; -- cgit v1.2.3 From 397f33cb0a7d60b3d061e70b66baee36a690351a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 15 Nov 2017 16:33:11 -0600 Subject: fpga: fpga-bridge: remove unnecessary null check in of_fpga_bridge_get Notice that bridge = to_fpga_bridge(dev); expands to: bridge = container_of(dev, struct fpga_bridge, dev); and container_of is never null, so this null check is unnecessary. Addresses-Coverity-ID: 1397912 Reported-by: Alan Tull Signed-off-by: Gustavo A. R. Silva Reviewed-by: Moritz Fischer Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/fpga-bridge.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index e693c3607a14..31bd2c59c305 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -78,8 +78,6 @@ static struct fpga_bridge *__fpga_bridge_get(struct device *dev, int ret = -ENODEV; bridge = to_fpga_bridge(dev); - if (!bridge) - goto err_dev; bridge->info = info; -- cgit v1.2.3 From 0f5eb1545907edeea7672a9c1652c4231150ff22 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 15 Nov 2017 16:33:12 -0600 Subject: fpga: region: release of_parse_phandle nodes after use Both fpga_region_get_manager() and fpga_region_get_bridges() call of_parse_phandle(), but nothing calls of_node_put() on the returned struct device_node pointers. Make sure to do that to stop their reference counters getting out of whack. Fixes: 0fa20cdfcc1f ("fpga: fpga-region: device tree control for FPGA") Cc: # 4.10+ Signed-off-by: Ian Abbott Signed-off-by: Alan Tull Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/of-fpga-region.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index c6b21194dcbc..119ff75522f1 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -73,6 +73,7 @@ static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np) mgr_node = of_parse_phandle(np, "fpga-mgr", 0); if (mgr_node) { mgr = of_fpga_mgr_get(mgr_node); + of_node_put(mgr_node); of_node_put(np); return mgr; } @@ -120,10 +121,13 @@ static int of_fpga_region_get_bridges(struct fpga_region *region) parent_br = region_np->parent; /* If overlay has a list of bridges, use it. */ - if (of_parse_phandle(info->overlay, "fpga-bridges", 0)) + br = of_parse_phandle(info->overlay, "fpga-bridges", 0); + if (br) { + of_node_put(br); np = info->overlay; - else + } else { np = region_np; + } for (i = 0; ; i++) { br = of_parse_phandle(np, "fpga-bridges", i); @@ -131,12 +135,15 @@ static int of_fpga_region_get_bridges(struct fpga_region *region) break; /* If parent bridge is in list, skip it. */ - if (br == parent_br) + if (br == parent_br) { + of_node_put(br); continue; + } /* If node is a bridge, get it and add to list */ ret = of_fpga_bridge_get_to_list(br, info, ®ion->bridge_list); + of_node_put(br); /* If any of the bridges are in use, give up */ if (ret == -EBUSY) { -- cgit v1.2.3 From 8d9a3ab6c17e9473ab31484da382914537e60152 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Mon, 13 Nov 2017 10:06:56 +0100 Subject: ANDROID: binder: show high watermark of alloc->pages. Show the high watermark of the index into the alloc->pages array, to facilitate sizing the buffer on a per-process basis. Signed-off-by: Martijn Coenen Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder_alloc.c | 4 ++++ drivers/android/binder_alloc.h | 2 ++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 6f6f745605af..0dba2308125c 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -281,6 +281,9 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, goto err_vm_insert_page_failed; } + if (index + 1 > alloc->pages_high) + alloc->pages_high = index + 1; + trace_binder_alloc_page_end(alloc, index); /* vm_insert_page does not seem to increment the refcount */ } @@ -853,6 +856,7 @@ void binder_alloc_print_pages(struct seq_file *m, } mutex_unlock(&alloc->mutex); seq_printf(m, " pages: %d:%d:%d\n", active, lru, free); + seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high); } /** diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 2dd33b6df104..0b145307f1fd 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -92,6 +92,7 @@ struct binder_lru_page { * @pages: array of binder_lru_page * @buffer_size: size of address space specified via mmap * @pid: pid for associated binder_proc (invariant after init) + * @pages_high: high watermark of offset in @pages * * Bookkeeping structure for per-proc address space management for binder * buffers. It is normally initialized during binder_init() and binder_mmap() @@ -112,6 +113,7 @@ struct binder_alloc { size_t buffer_size; uint32_t buffer_free; int pid; + size_t pages_high; }; #ifdef CONFIG_ANDROID_BINDER_IPC_SELFTEST -- cgit v1.2.3 From 148ade2c4d4f46b3ecc1ddad1c762371e8708e35 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 15 Nov 2017 09:21:35 +0100 Subject: ANDROID: binder: Add thread->process_todo flag. This flag determines whether the thread should currently process the work in the thread->todo worklist. The prime usecase for this is improving the performance of synchronous transactions: all synchronous transactions post a BR_TRANSACTION_COMPLETE to the calling thread, but there's no reason to return that command to userspace right away - userspace anyway needs to wait for the reply. Likewise, a synchronous transaction that contains a binder object can cause a BC_ACQUIRE/BC_INCREFS to be returned to userspace; since the caller must anyway hold a strong/weak ref for the duration of the call, postponing these commands until the reply comes in is not a problem. Note that this flag is not used to determine whether a thread can handle process work; a thread should never pick up process work when thread work is still pending. Before patch: ------------------------------------------------------------------ Benchmark Time CPU Iterations ------------------------------------------------------------------ BM_sendVec_binderize/4 45959 ns 20288 ns 34351 BM_sendVec_binderize/8 45603 ns 20080 ns 34909 BM_sendVec_binderize/16 45528 ns 20113 ns 34863 BM_sendVec_binderize/32 45551 ns 20122 ns 34881 BM_sendVec_binderize/64 45701 ns 20183 ns 34864 BM_sendVec_binderize/128 45824 ns 20250 ns 34576 BM_sendVec_binderize/256 45695 ns 20171 ns 34759 BM_sendVec_binderize/512 45743 ns 20211 ns 34489 BM_sendVec_binderize/1024 46169 ns 20430 ns 34081 After patch: ------------------------------------------------------------------ Benchmark Time CPU Iterations ------------------------------------------------------------------ BM_sendVec_binderize/4 42939 ns 17262 ns 40653 BM_sendVec_binderize/8 42823 ns 17243 ns 40671 BM_sendVec_binderize/16 42898 ns 17243 ns 40594 BM_sendVec_binderize/32 42838 ns 17267 ns 40527 BM_sendVec_binderize/64 42854 ns 17249 ns 40379 BM_sendVec_binderize/128 42881 ns 17288 ns 40427 BM_sendVec_binderize/256 42917 ns 17297 ns 40429 BM_sendVec_binderize/512 43184 ns 17395 ns 40411 BM_sendVec_binderize/1024 43119 ns 17357 ns 40432 Signed-off-by: Martijn Coenen Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 151 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index a73596a4f804..e9d22dd85a19 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -577,6 +577,8 @@ enum { * (protected by @proc->inner_lock) * @todo: list of work to do for this thread * (protected by @proc->inner_lock) + * @process_todo: whether work in @todo should be processed + * (protected by @proc->inner_lock) * @return_error: transaction errors reported by this thread * (only accessed by this thread) * @reply_error: transaction errors reported by target thread @@ -602,6 +604,7 @@ struct binder_thread { bool looper_need_return; /* can be written by other thread */ struct binder_transaction *transaction_stack; struct list_head todo; + bool process_todo; struct binder_error return_error; struct binder_error reply_error; wait_queue_head_t wait; @@ -787,6 +790,16 @@ static bool binder_worklist_empty(struct binder_proc *proc, return ret; } +/** + * binder_enqueue_work_ilocked() - Add an item to the work list + * @work: struct binder_work to add to list + * @target_list: list to add work to + * + * Adds the work to the specified list. Asserts that work + * is not already on a list. + * + * Requires the proc->inner_lock to be held. + */ static void binder_enqueue_work_ilocked(struct binder_work *work, struct list_head *target_list) @@ -797,22 +810,56 @@ binder_enqueue_work_ilocked(struct binder_work *work, } /** - * binder_enqueue_work() - Add an item to the work list - * @proc: binder_proc associated with list + * binder_enqueue_deferred_thread_work_ilocked() - Add deferred thread work + * @thread: thread to queue work to * @work: struct binder_work to add to list - * @target_list: list to add work to * - * Adds the work to the specified list. Asserts that work - * is not already on a list. + * Adds the work to the todo list of the thread. Doesn't set the process_todo + * flag, which means that (if it wasn't already set) the thread will go to + * sleep without handling this work when it calls read. + * + * Requires the proc->inner_lock to be held. */ static void -binder_enqueue_work(struct binder_proc *proc, - struct binder_work *work, - struct list_head *target_list) +binder_enqueue_deferred_thread_work_ilocked(struct binder_thread *thread, + struct binder_work *work) { - binder_inner_proc_lock(proc); - binder_enqueue_work_ilocked(work, target_list); - binder_inner_proc_unlock(proc); + binder_enqueue_work_ilocked(work, &thread->todo); +} + +/** + * binder_enqueue_thread_work_ilocked() - Add an item to the thread work list + * @thread: thread to queue work to + * @work: struct binder_work to add to list + * + * Adds the work to the todo list of the thread, and enables processing + * of the todo queue. + * + * Requires the proc->inner_lock to be held. + */ +static void +binder_enqueue_thread_work_ilocked(struct binder_thread *thread, + struct binder_work *work) +{ + binder_enqueue_work_ilocked(work, &thread->todo); + thread->process_todo = true; +} + +/** + * binder_enqueue_thread_work() - Add an item to the thread work list + * @thread: thread to queue work to + * @work: struct binder_work to add to list + * + * Adds the work to the todo list of the thread, and enables processing + * of the todo queue. + */ +static void +binder_enqueue_thread_work(struct binder_thread *thread, + struct binder_work *work) +{ + binder_inner_proc_lock(thread->proc); + binder_enqueue_thread_work_ilocked(thread, work); + binder_inner_proc_unlock(thread->proc); } static void @@ -927,7 +974,7 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd) static bool binder_has_work_ilocked(struct binder_thread *thread, bool do_proc_work) { - return !binder_worklist_empty_ilocked(&thread->todo) || + return thread->process_todo || thread->looper_need_return || (do_proc_work && !binder_worklist_empty_ilocked(&thread->proc->todo)); @@ -1215,6 +1262,17 @@ static int binder_inc_node_nilocked(struct binder_node *node, int strong, node->local_strong_refs++; if (!node->has_strong_ref && target_list) { binder_dequeue_work_ilocked(&node->work); + /* + * Note: this function is the only place where we queue + * directly to a thread->todo without using the + * corresponding binder_enqueue_thread_work() helper + * functions; in this case it's ok to not set the + * process_todo flag, since we know this node work will + * always be followed by other work that starts queue + * processing: in case of synchronous transactions, a + * BR_REPLY or BR_ERROR; in case of oneway + * transactions, a BR_TRANSACTION_COMPLETE. + */ binder_enqueue_work_ilocked(&node->work, target_list); } } else { @@ -1226,6 +1284,9 @@ static int binder_inc_node_nilocked(struct binder_node *node, int strong, node->debug_id); return -EINVAL; } + /* + * See comment above + */ binder_enqueue_work_ilocked(&node->work, target_list); } } @@ -1915,9 +1976,9 @@ static void binder_send_failed_reply(struct binder_transaction *t, binder_pop_transaction_ilocked(target_thread, t); if (target_thread->reply_error.cmd == BR_OK) { target_thread->reply_error.cmd = error_code; - binder_enqueue_work_ilocked( - &target_thread->reply_error.work, - &target_thread->todo); + binder_enqueue_thread_work_ilocked( + target_thread, + &target_thread->reply_error.work); wake_up_interruptible(&target_thread->wait); } else { WARN(1, "Unexpected reply error: %u\n", @@ -2536,18 +2597,16 @@ static bool binder_proc_transaction(struct binder_transaction *t, struct binder_proc *proc, struct binder_thread *thread) { - struct list_head *target_list = NULL; struct binder_node *node = t->buffer->target_node; bool oneway = !!(t->flags & TF_ONE_WAY); - bool wakeup = true; + bool pending_async = false; BUG_ON(!node); binder_node_lock(node); if (oneway) { BUG_ON(thread); if (node->has_async_transaction) { - target_list = &node->async_todo; - wakeup = false; + pending_async = true; } else { node->has_async_transaction = 1; } @@ -2561,19 +2620,17 @@ static bool binder_proc_transaction(struct binder_transaction *t, return false; } - if (!thread && !target_list) + if (!thread && !pending_async) thread = binder_select_thread_ilocked(proc); if (thread) - target_list = &thread->todo; - else if (!target_list) - target_list = &proc->todo; + binder_enqueue_thread_work_ilocked(thread, &t->work); + else if (!pending_async) + binder_enqueue_work_ilocked(&t->work, &proc->todo); else - BUG_ON(target_list != &node->async_todo); - - binder_enqueue_work_ilocked(&t->work, target_list); + binder_enqueue_work_ilocked(&t->work, &node->async_todo); - if (wakeup) + if (!pending_async) binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); binder_inner_proc_unlock(proc); @@ -3068,10 +3125,10 @@ static void binder_transaction(struct binder_proc *proc, } } tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; - binder_enqueue_work(proc, tcomplete, &thread->todo); t->work.type = BINDER_WORK_TRANSACTION; if (reply) { + binder_enqueue_thread_work(thread, tcomplete); binder_inner_proc_lock(target_proc); if (target_thread->is_dead) { binder_inner_proc_unlock(target_proc); @@ -3079,13 +3136,21 @@ static void binder_transaction(struct binder_proc *proc, } BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction_ilocked(target_thread, in_reply_to); - binder_enqueue_work_ilocked(&t->work, &target_thread->todo); + binder_enqueue_thread_work_ilocked(target_thread, &t->work); binder_inner_proc_unlock(target_proc); wake_up_interruptible_sync(&target_thread->wait); binder_free_transaction(in_reply_to); } else if (!(t->flags & TF_ONE_WAY)) { BUG_ON(t->buffer->async_transaction != 0); binder_inner_proc_lock(proc); + /* + * Defer the TRANSACTION_COMPLETE, so we don't return to + * userspace immediately; this allows the target process to + * immediately start processing this transaction, reducing + * latency. We will then return the TRANSACTION_COMPLETE when + * the target replies (or there is an error). + */ + binder_enqueue_deferred_thread_work_ilocked(thread, tcomplete); t->need_reply = 1; t->from_parent = thread->transaction_stack; thread->transaction_stack = t; @@ -3099,6 +3164,7 @@ static void binder_transaction(struct binder_proc *proc, } else { BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); + binder_enqueue_thread_work(thread, tcomplete); if (!binder_proc_transaction(t, target_proc, NULL)) goto err_dead_proc_or_thread; } @@ -3177,15 +3243,11 @@ err_invalid_target_handle: BUG_ON(thread->return_error.cmd != BR_OK); if (in_reply_to) { thread->return_error.cmd = BR_TRANSACTION_COMPLETE; - binder_enqueue_work(thread->proc, - &thread->return_error.work, - &thread->todo); + binder_enqueue_thread_work(thread, &thread->return_error.work); binder_send_failed_reply(in_reply_to, return_error); } else { thread->return_error.cmd = return_error; - binder_enqueue_work(thread->proc, - &thread->return_error.work, - &thread->todo); + binder_enqueue_thread_work(thread, &thread->return_error.work); } } @@ -3489,10 +3551,9 @@ static int binder_thread_write(struct binder_proc *proc, WARN_ON(thread->return_error.cmd != BR_OK); thread->return_error.cmd = BR_ERROR; - binder_enqueue_work( - thread->proc, - &thread->return_error.work, - &thread->todo); + binder_enqueue_thread_work( + thread, + &thread->return_error.work); binder_debug( BINDER_DEBUG_FAILED_TRANSACTION, "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", @@ -3572,9 +3633,9 @@ static int binder_thread_write(struct binder_proc *proc, if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) - binder_enqueue_work_ilocked( - &death->work, - &thread->todo); + binder_enqueue_thread_work_ilocked( + thread, + &death->work); else { binder_enqueue_work_ilocked( &death->work, @@ -3629,8 +3690,8 @@ static int binder_thread_write(struct binder_proc *proc, if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) - binder_enqueue_work_ilocked( - &death->work, &thread->todo); + binder_enqueue_thread_work_ilocked( + thread, &death->work); else { binder_enqueue_work_ilocked( &death->work, @@ -3804,6 +3865,8 @@ retry: break; } w = binder_dequeue_work_head_ilocked(list); + if (binder_worklist_empty_ilocked(&thread->todo)) + thread->process_todo = false; switch (w->type) { case BINDER_WORK_TRANSACTION: { -- cgit v1.2.3 From 02543a4e96760a347fb9733bc8a0506a19270ec2 Mon Sep 17 00:00:00 2001 From: Vasyl Gomonovych Date: Thu, 23 Nov 2017 17:00:42 +0100 Subject: lkdtm: Missing kmalloc check Handling a possible memory allocation failure. Signed-off-by: Vasyl Gomonovych Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm_heap.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/lkdtm_heap.c b/drivers/misc/lkdtm_heap.c index f5494a6d4be5..65026d7de130 100644 --- a/drivers/misc/lkdtm_heap.c +++ b/drivers/misc/lkdtm_heap.c @@ -16,6 +16,8 @@ void lkdtm_OVERWRITE_ALLOCATION(void) { size_t len = 1020; u32 *data = kmalloc(len, GFP_KERNEL); + if (!data) + return; data[1024 / sizeof(u32)] = 0x12345678; kfree(data); @@ -33,6 +35,8 @@ void lkdtm_WRITE_AFTER_FREE(void) size_t offset = (len / sizeof(*base)) / 2; base = kmalloc(len, GFP_KERNEL); + if (!base) + return; pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]); pr_info("Attempting bad write to freed memory at %p\n", &base[offset]); -- cgit v1.2.3 From 9a450484089dfa8b6348eff2a918f3c8f38585b9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Nov 2017 12:29:50 +0100 Subject: lp: support 64-bit time_t user space Once we get a glibc with 64-bit time_t, the LPSETTIMEOUT ioctl stops working, since the command number and data structure no longer match. To work around that, this introduces a new command number LPSETTIMEOUT_NEW that is used whenever the modified user space evaluates the LPSETTIMEOUT macro. The trick we use is a bit convoluted but necessary: we cannot check for any macros set by the C library in linux/lp.h, because this particular header can be included before including sys/time.h. However, we can assume that by the time that LPSETTIMEOUT is seen in the code, the definition for 'timeval' and 'time_t' has been seen as well, so we can use the sizeof() operator to determine whether we should use the old or the new definition. We use the old one not only for traditional 32-bit user space with 32-bit time_t, but also for all 64-bit architectures and x32, which always use a 64-bit time_t, the new definition will be used only for 32-bit user space with 64-bit time_t, which also requires a newer kernel. The compat_ioctl() handler now implements both commands, but has to use a special case for existing x32 binaries. The native ioctl handler now implements both command numbers on both 32-bit and 64-bit, though the latter version use the same interpretation for both. This is based on an earlier patch from Bamvor. Cc: Bamvor Jian Zhang Link: http://www.spinics.net/lists/y2038/msg01162.html Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/char/lp.c | 67 +++++++++++++++++++++++++++++++++++++------------ include/uapi/linux/lp.h | 12 ++++++++- 2 files changed, 62 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 8249762192d5..be14abf70da1 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -659,17 +659,31 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd, return retval; } -static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout) +static int lp_set_timeout(unsigned int minor, s64 tv_sec, long tv_usec) { long to_jiffies; /* Convert to jiffies, place in lp_table */ - if ((par_timeout->tv_sec < 0) || - (par_timeout->tv_usec < 0)) { + if (tv_sec < 0 || tv_usec < 0) return -EINVAL; + + /* + * we used to not check, so let's not make this fatal, + * but deal with user space passing a 32-bit tv_nsec in + * a 64-bit field, capping the timeout to 1 second + * worth of microseconds, and capping the total at + * MAX_JIFFY_OFFSET. + */ + if (tv_usec > 999999) + tv_usec = 999999; + + if (tv_sec >= MAX_SEC_IN_JIFFIES - 1) { + to_jiffies = MAX_JIFFY_OFFSET; + } else { + to_jiffies = DIV_ROUND_UP(tv_usec, 1000000/HZ); + to_jiffies += tv_sec * (long) HZ; } - to_jiffies = DIV_ROUND_UP(par_timeout->tv_usec, 1000000/HZ); - to_jiffies += par_timeout->tv_sec * (long) HZ; + if (to_jiffies <= 0) { return -EINVAL; } @@ -677,23 +691,43 @@ static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout) return 0; } +static int lp_set_timeout32(unsigned int minor, void __user *arg) +{ + s32 karg[2]; + + if (copy_from_user(karg, arg, sizeof(karg))) + return -EFAULT; + + return lp_set_timeout(minor, karg[0], karg[1]); +} + +static int lp_set_timeout64(unsigned int minor, void __user *arg) +{ + s64 karg[2]; + + if (copy_from_user(karg, arg, sizeof(karg))) + return -EFAULT; + + return lp_set_timeout(minor, karg[0], karg[1]); +} + static long lp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned int minor; - struct timeval par_timeout; int ret; minor = iminor(file_inode(file)); mutex_lock(&lp_mutex); switch (cmd) { - case LPSETTIMEOUT: - if (copy_from_user(&par_timeout, (void __user *)arg, - sizeof (struct timeval))) { - ret = -EFAULT; + case LPSETTIMEOUT_OLD: + if (BITS_PER_LONG == 32) { + ret = lp_set_timeout32(minor, (void __user *)arg); break; } - ret = lp_set_timeout(minor, &par_timeout); + /* fallthrough for 64-bit */ + case LPSETTIMEOUT_NEW: + ret = lp_set_timeout64(minor, (void __user *)arg); break; default: ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg); @@ -709,18 +743,19 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned int minor; - struct timeval par_timeout; int ret; minor = iminor(file_inode(file)); mutex_lock(&lp_mutex); switch (cmd) { - case LPSETTIMEOUT: - if (compat_get_timeval(&par_timeout, compat_ptr(arg))) { - ret = -EFAULT; + case LPSETTIMEOUT_OLD: + if (!COMPAT_USE_64BIT_TIME) { + ret = lp_set_timeout32(minor, (void __user *)arg); break; } - ret = lp_set_timeout(minor, &par_timeout); + /* fallthrough for x32 mode */ + case LPSETTIMEOUT_NEW: + ret = lp_set_timeout64(minor, (void __user *)arg); break; #ifdef LP_STATS case LPGETSTATS: diff --git a/include/uapi/linux/lp.h b/include/uapi/linux/lp.h index dafcfe4e4834..8589a27037d7 100644 --- a/include/uapi/linux/lp.h +++ b/include/uapi/linux/lp.h @@ -8,6 +8,8 @@ #ifndef _UAPI_LINUX_LP_H #define _UAPI_LINUX_LP_H +#include +#include /* * Per POSIX guidelines, this module reserves the LP and lp prefixes @@ -88,7 +90,15 @@ #define LPGETSTATS 0x060d /* get statistics (struct lp_stats) */ #endif #define LPGETFLAGS 0x060e /* get status flags */ -#define LPSETTIMEOUT 0x060f /* set parport timeout */ +#define LPSETTIMEOUT_OLD 0x060f /* set parport timeout */ +#define LPSETTIMEOUT_NEW \ + _IOW(0x6, 0xf, __s64[2]) /* set parport timeout */ +#if __BITS_PER_LONG == 64 +#define LPSETTIMEOUT LPSETTIMEOUT_OLD +#else +#define LPSETTIMEOUT (sizeof(time_t) > sizeof(__kernel_long_t) ? \ + LPSETTIMEOUT_NEW : LPSETTIMEOUT_OLD) +#endif /* timeout for printk'ing a timeout, in jiffies (100ths of a second). This is also used for re-checking error conditions if LP_ABORT is -- cgit v1.2.3 From afc9a42b7464f76e1388cad87d8543c69f6f74ed Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 3 Jul 2017 06:39:46 -0400 Subject: the rest of drivers/*: annotate ->poll() instances Signed-off-by: Al Viro --- drivers/android/binder.c | 2 +- drivers/bluetooth/hci_ldisc.c | 2 +- drivers/bluetooth/hci_vhci.c | 2 +- drivers/char/apm-emulation.c | 2 +- drivers/char/dsp56k.c | 2 +- drivers/char/dtlk.c | 6 +++--- drivers/char/hpet.c | 2 +- drivers/char/ipmi/bt-bmc.c | 4 ++-- drivers/char/ipmi/ipmi_devintf.c | 4 ++-- drivers/char/ipmi/ipmi_watchdog.c | 4 ++-- drivers/char/pcmcia/cm4040_cs.c | 4 ++-- drivers/char/ppdev.c | 4 ++-- drivers/char/random.c | 4 ++-- drivers/char/rtc.c | 4 ++-- drivers/char/snsc.c | 4 ++-- drivers/char/sonypi.c | 2 +- drivers/char/tpm/tpm_vtpm_proxy.c | 4 ++-- drivers/char/virtio_console.c | 4 ++-- drivers/char/xillybus/xillybus_core.c | 4 ++-- drivers/dma-buf/dma-buf.c | 4 ++-- drivers/dma-buf/sync_file.c | 2 +- drivers/firewire/core-cdev.c | 4 ++-- drivers/firewire/nosy.c | 4 ++-- drivers/gpio/gpiolib.c | 4 ++-- drivers/gpu/drm/drm_file.c | 4 ++-- drivers/gpu/drm/i915/i915_perf.c | 8 ++++---- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 2 +- drivers/gpu/vga/vgaarb.c | 2 +- drivers/hid/hid-debug.c | 2 +- drivers/hid/hid-roccat.c | 2 +- drivers/hid/hid-sensor-custom.c | 4 ++-- drivers/hid/hidraw.c | 2 +- drivers/hid/uhid.c | 2 +- drivers/hid/usbhid/hiddev.c | 2 +- drivers/hsi/clients/cmt_speech.c | 4 ++-- drivers/hv/hv_utils_transport.c | 2 +- drivers/iio/iio_core.h | 2 +- drivers/iio/industrialio-buffer.c | 2 +- drivers/iio/industrialio-event.c | 4 ++-- drivers/infiniband/core/ucm.c | 4 ++-- drivers/infiniband/core/ucma.c | 4 ++-- drivers/infiniband/core/user_mad.c | 4 ++-- drivers/infiniband/core/uverbs_main.c | 8 ++++---- drivers/infiniband/hw/hfi1/file_ops.c | 18 +++++++++--------- drivers/infiniband/hw/qib/qib_file_ops.c | 14 +++++++------- drivers/input/evdev.c | 4 ++-- drivers/input/input.c | 2 +- drivers/input/joydev.c | 2 +- drivers/input/misc/hp_sdc_rtc.c | 2 +- drivers/input/misc/uinput.c | 2 +- drivers/input/mousedev.c | 4 ++-- drivers/input/serio/serio_raw.c | 4 ++-- drivers/input/serio/userio.c | 2 +- drivers/isdn/capi/capi.c | 4 ++-- drivers/isdn/divert/divert_procfs.c | 4 ++-- drivers/isdn/hardware/eicon/divamnt.c | 4 ++-- drivers/isdn/hardware/eicon/divasi.c | 4 ++-- drivers/isdn/hardware/eicon/divasmain.c | 2 +- drivers/isdn/hardware/eicon/divasproc.c | 2 +- drivers/isdn/hysdn/hysdn_proclog.c | 4 ++-- drivers/isdn/i4l/isdn_common.c | 4 ++-- drivers/isdn/i4l/isdn_ppp.c | 4 ++-- drivers/isdn/i4l/isdn_ppp.h | 2 +- drivers/isdn/mISDN/timerdev.c | 4 ++-- drivers/leds/uleds.c | 2 +- drivers/macintosh/smu.c | 4 ++-- drivers/macintosh/via-pmu.c | 4 ++-- drivers/mailbox/mailbox-test.c | 2 +- drivers/md/dm-ioctl.c | 4 ++-- drivers/md/md.c | 4 ++-- drivers/misc/cxl/api.c | 2 +- drivers/misc/cxl/cxl.h | 2 +- drivers/misc/cxl/file.c | 4 ++-- drivers/misc/hpilo.c | 2 +- drivers/misc/lis3lv02d/lis3lv02d.c | 2 +- drivers/misc/mei/main.c | 4 ++-- drivers/misc/mic/scif/scif_api.c | 7 ++++--- drivers/misc/mic/scif/scif_epd.h | 2 +- drivers/misc/mic/scif/scif_fd.c | 2 +- drivers/misc/mic/vop/vop_vringh.c | 4 ++-- drivers/misc/phantom.c | 4 ++-- drivers/misc/vmw_vmci/vmci_host.c | 4 ++-- drivers/net/ieee802154/ca8210.c | 4 ++-- drivers/net/ppp/ppp_async.c | 2 +- drivers/net/ppp/ppp_generic.c | 4 ++-- drivers/net/ppp/ppp_synctty.c | 2 +- drivers/net/tap.c | 4 ++-- drivers/net/tun.c | 4 ++-- drivers/net/wan/cosa.c | 2 +- drivers/net/wireless/ralink/rt2x00/rt2x00debug.c | 2 +- drivers/pci/switch/switchtec.c | 4 ++-- drivers/platform/chrome/cros_ec_debugfs.c | 4 ++-- drivers/platform/goldfish/goldfish_pipe.c | 4 ++-- drivers/platform/x86/sony-laptop.c | 2 +- drivers/pps/pps.c | 2 +- drivers/ptp/ptp_chardev.c | 2 +- drivers/ptp/ptp_private.h | 2 +- drivers/rapidio/devices/rio_mport_cdev.c | 2 +- drivers/rpmsg/qcom_smd.c | 4 ++-- drivers/rpmsg/rpmsg_char.c | 4 ++-- drivers/rpmsg/rpmsg_core.c | 2 +- drivers/rpmsg/rpmsg_internal.h | 2 +- drivers/rtc/rtc-dev.c | 2 +- drivers/s390/block/dasd_eer.c | 4 ++-- drivers/s390/char/monreader.c | 2 +- drivers/scsi/megaraid/megaraid_sas_base.c | 4 ++-- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 2 +- drivers/scsi/sg.c | 4 ++-- drivers/staging/comedi/comedi_fops.c | 4 ++-- drivers/staging/most/aim-cdev/cdev.c | 4 ++-- drivers/staging/most/aim-v4l2/video.c | 4 ++-- drivers/staging/speakup/speakup_soft.c | 4 ++-- drivers/tty/n_gsm.c | 4 ++-- drivers/tty/n_hdlc.c | 6 +++--- drivers/tty/n_r3964.c | 6 +++--- drivers/tty/n_tty.c | 4 ++-- drivers/tty/tty_io.c | 6 +++--- drivers/tty/vt/vc_screen.c | 4 ++-- drivers/uio/uio.c | 2 +- drivers/usb/class/cdc-wdm.c | 4 ++-- drivers/usb/class/usblp.c | 4 ++-- drivers/usb/class/usbtmc.c | 4 ++-- drivers/usb/core/devices.c | 2 +- drivers/usb/core/devio.c | 4 ++-- drivers/usb/gadget/function/f_fs.c | 4 ++-- drivers/usb/gadget/function/f_hid.c | 4 ++-- drivers/usb/gadget/function/f_printer.c | 4 ++-- drivers/usb/gadget/legacy/inode.c | 4 ++-- drivers/usb/misc/iowarrior.c | 4 ++-- drivers/usb/misc/ldusb.c | 4 ++-- drivers/usb/misc/legousbtower.c | 6 +++--- drivers/usb/mon/mon_bin.c | 4 ++-- drivers/vhost/net.c | 2 +- drivers/vhost/vhost.c | 4 ++-- drivers/vhost/vhost.h | 2 +- drivers/virt/fsl_hypervisor.c | 4 ++-- drivers/xen/evtchn.c | 4 ++-- drivers/xen/mcelog.c | 2 +- drivers/xen/pvcalls-front.c | 10 +++++----- drivers/xen/xenbus/xenbus_dev_frontend.c | 2 +- include/drm/drm_file.h | 2 +- include/linux/rpmsg.h | 4 ++-- include/misc/cxl.h | 2 +- 144 files changed, 257 insertions(+), 256 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index a73596a4f804..fdc951083b07 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -4276,7 +4276,7 @@ static int binder_thread_release(struct binder_proc *proc, return active_transactions; } -static unsigned int binder_poll(struct file *filp, +static __poll_t binder_poll(struct file *filp, struct poll_table_struct *wait) { struct binder_proc *proc = filp->private_data; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index c823914b3a80..b6a71705b7d6 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -794,7 +794,7 @@ static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, return 0; } -static unsigned int hci_uart_tty_poll(struct tty_struct *tty, +static __poll_t hci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait) { return 0; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index e6f6dbc04131..0521748a1972 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -299,7 +299,7 @@ static ssize_t vhci_write(struct kiocb *iocb, struct iov_iter *from) return vhci_get_user(data, from); } -static unsigned int vhci_poll(struct file *file, poll_table *wait) +static __poll_t vhci_poll(struct file *file, poll_table *wait) { struct vhci_data *data = file->private_data; diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c index 1dfb9f8de171..a2a1c1478cd0 100644 --- a/drivers/char/apm-emulation.c +++ b/drivers/char/apm-emulation.c @@ -236,7 +236,7 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t return ret; } -static unsigned int apm_poll(struct file *fp, poll_table * wait) +static __poll_t apm_poll(struct file *fp, poll_table * wait) { struct apm_user *as = fp->private_data; diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 0d7b577e0ff0..2f92cc46698b 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -406,7 +406,7 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd, * Do I need this function at all??? */ #if 0 -static unsigned int dsp56k_poll(struct file *file, poll_table *wait) +static __poll_t dsp56k_poll(struct file *file, poll_table *wait) { int dev = iminor(file_inode(file)) & 0x0f; diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index 839ee61d352a..2697c22e3be2 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -91,7 +91,7 @@ static ssize_t dtlk_read(struct file *, char __user *, size_t nbytes, loff_t * ppos); static ssize_t dtlk_write(struct file *, const char __user *, size_t nbytes, loff_t * ppos); -static unsigned int dtlk_poll(struct file *, poll_table *); +static __poll_t dtlk_poll(struct file *, poll_table *); static int dtlk_open(struct inode *, struct file *); static int dtlk_release(struct inode *, struct file *); static long dtlk_ioctl(struct file *file, @@ -228,9 +228,9 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf, return -EAGAIN; } -static unsigned int dtlk_poll(struct file *file, poll_table * wait) +static __poll_t dtlk_poll(struct file *file, poll_table * wait) { - int mask = 0; + __poll_t mask = 0; unsigned long expires; TRACE_TEXT(" dtlk_poll"); diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index b941e6d59fd6..dbed4953f86c 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -342,7 +342,7 @@ out: return retval; } -static unsigned int hpet_poll(struct file *file, poll_table * wait) +static __poll_t hpet_poll(struct file *file, poll_table * wait) { unsigned long v; struct hpet_dev *devp; diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c index 6edfaa72b98b..7992c870b0a2 100644 --- a/drivers/char/ipmi/bt-bmc.c +++ b/drivers/char/ipmi/bt-bmc.c @@ -338,10 +338,10 @@ static int bt_bmc_release(struct inode *inode, struct file *file) return 0; } -static unsigned int bt_bmc_poll(struct file *file, poll_table *wait) +static __poll_t bt_bmc_poll(struct file *file, poll_table *wait) { struct bt_bmc *bt_bmc = file_bt_bmc(file); - unsigned int mask = 0; + __poll_t mask = 0; u8 ctrl; poll_wait(file, &bt_bmc->queue, wait); diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 2ffca4232686..a011a7739f5e 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -78,10 +78,10 @@ static void file_receive_handler(struct ipmi_recv_msg *msg, spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); } -static unsigned int ipmi_poll(struct file *file, poll_table *wait) +static __poll_t ipmi_poll(struct file *file, poll_table *wait) { struct ipmi_file_private *priv = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; unsigned long flags; poll_wait(file, &priv->wait, wait); diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 76b270678b50..95d8e9a53e91 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -887,9 +887,9 @@ static int ipmi_open(struct inode *ino, struct file *filep) } } -static unsigned int ipmi_poll(struct file *file, poll_table *wait) +static __poll_t ipmi_poll(struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &read_q, wait); diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 9a1aaf538758..819fe37a3683 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -415,10 +415,10 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, return count; } -static unsigned int cm4040_poll(struct file *filp, poll_table *wait) +static __poll_t cm4040_poll(struct file *filp, poll_table *wait) { struct reader_dev *dev = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(filp, &dev->poll_wait, wait); diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index d256110ba672..7a56d1a13ec3 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -769,10 +769,10 @@ static int pp_release(struct inode *inode, struct file *file) } /* No kernel lock held - fine */ -static unsigned int pp_poll(struct file *file, poll_table *wait) +static __poll_t pp_poll(struct file *file, poll_table *wait) { struct pp_struct *pp = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &pp->irq_wait, wait); if (atomic_read(&pp->irqc)) diff --git a/drivers/char/random.c b/drivers/char/random.c index ec42c8bb9b0d..64b59562c872 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1784,10 +1784,10 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) return ret; } -static unsigned int +static __poll_t random_poll(struct file *file, poll_table * wait) { - unsigned int mask; + __poll_t mask; poll_wait(file, &random_read_wait, wait); poll_wait(file, &random_write_wait, wait); diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 5542a438bbd0..c6a317120a55 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -147,7 +147,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static void rtc_get_rtc_time(struct rtc_time *rtc_tm); #ifdef RTC_IRQ -static unsigned int rtc_poll(struct file *file, poll_table *wait); +static __poll_t rtc_poll(struct file *file, poll_table *wait); #endif static void get_rtc_alm_time(struct rtc_time *alm_tm); @@ -790,7 +790,7 @@ no_irq: } #ifdef RTC_IRQ -static unsigned int rtc_poll(struct file *file, poll_table *wait) +static __poll_t rtc_poll(struct file *file, poll_table *wait) { unsigned long l; diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 6aa32679fd58..7f49fa0f41d7 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -321,10 +321,10 @@ scdrv_write(struct file *file, const char __user *buf, return status; } -static unsigned int +static __poll_t scdrv_poll(struct file *file, struct poll_table_struct *wait) { - unsigned int mask = 0; + __poll_t mask = 0; int status = 0; struct subch_data_s *sd = (struct subch_data_s *) file->private_data; unsigned long flags; diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index d3a979e25724..fc041c462aa4 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -940,7 +940,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, return ret; } -static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) +static __poll_t sonypi_misc_poll(struct file *file, poll_table *wait) { poll_wait(file, &sonypi_device.fifo_proc_list, wait); if (kfifo_len(&sonypi_device.fifo)) diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index 1d877cc9af97..674218b50b13 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -173,10 +173,10 @@ static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf, * * Return: Poll flags */ -static unsigned int vtpm_proxy_fops_poll(struct file *filp, poll_table *wait) +static __poll_t vtpm_proxy_fops_poll(struct file *filp, poll_table *wait) { struct proxy_dev *proxy_dev = filp->private_data; - unsigned ret; + __poll_t ret; poll_wait(filp, &proxy_dev->wq, wait); diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index d1aed2513bd9..813a2e46824d 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -982,10 +982,10 @@ error_out: return ret; } -static unsigned int port_fops_poll(struct file *filp, poll_table *wait) +static __poll_t port_fops_poll(struct file *filp, poll_table *wait) { struct port *port; - unsigned int ret; + __poll_t ret; port = filp->private_data; poll_wait(filp, &port->waitqueue, wait); diff --git a/drivers/char/xillybus/xillybus_core.c b/drivers/char/xillybus/xillybus_core.c index b6c9cdead7f3..88e1cf475d3f 100644 --- a/drivers/char/xillybus/xillybus_core.c +++ b/drivers/char/xillybus/xillybus_core.c @@ -1736,10 +1736,10 @@ end: return pos; } -static unsigned int xillybus_poll(struct file *filp, poll_table *wait) +static __poll_t xillybus_poll(struct file *filp, poll_table *wait) { struct xilly_channel *channel = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; unsigned long flags; poll_wait(filp, &channel->endpoint->ep_wait, wait); diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 4f313593caf5..12b62d0aac27 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -157,7 +157,7 @@ static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb) spin_unlock_irqrestore(&dcb->poll->lock, flags); } -static unsigned int dma_buf_poll(struct file *file, poll_table *poll) +static __poll_t dma_buf_poll(struct file *file, poll_table *poll) { struct dma_buf *dmabuf; struct reservation_object *resv; @@ -195,7 +195,7 @@ retry: if (fence_excl && (!(events & POLLOUT) || shared_count == 0)) { struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl; - unsigned long pevents = POLLIN; + __poll_t pevents = POLLIN; if (shared_count == 0) pevents |= POLLOUT; diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 03830634e141..8e8c4a12a0bc 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -312,7 +312,7 @@ static int sync_file_release(struct inode *inode, struct file *file) return 0; } -static unsigned int sync_file_poll(struct file *file, poll_table *wait) +static __poll_t sync_file_poll(struct file *file, poll_table *wait) { struct sync_file *sync_file = file->private_data; diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index a301fcf46e88..523391bb3fbe 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1784,10 +1784,10 @@ static int fw_device_op_release(struct inode *inode, struct file *file) return 0; } -static unsigned int fw_device_op_poll(struct file *file, poll_table * pt) +static __poll_t fw_device_op_poll(struct file *file, poll_table * pt) { struct client *client = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &client->wait, pt); diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 180f0a96528c..fee2e9e7ea20 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -328,11 +328,11 @@ nosy_release(struct inode *inode, struct file *file) return 0; } -static unsigned int +static __poll_t nosy_poll(struct file *file, poll_table *pt) { struct client *client = file->private_data; - unsigned int ret = 0; + __poll_t ret = 0; poll_wait(file, &client->buffer.wait, pt); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index aad84a6306c4..46824c486e1e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -603,11 +603,11 @@ struct lineevent_state { (GPIOEVENT_REQUEST_RISING_EDGE | \ GPIOEVENT_REQUEST_FALLING_EDGE) -static unsigned int lineevent_poll(struct file *filep, +static __poll_t lineevent_poll(struct file *filep, struct poll_table_struct *wait) { struct lineevent_state *le = filep->private_data; - unsigned int events = 0; + __poll_t events = 0; poll_wait(filep, &le->wait, wait); diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index b3c6e997ccdb..9a17bd3639d1 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -559,10 +559,10 @@ EXPORT_SYMBOL(drm_read); * * Mask of POLL flags indicating the current status of the file. */ -unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) +__poll_t drm_poll(struct file *filp, struct poll_table_struct *wait) { struct drm_file *file_priv = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(filp, &file_priv->event_wait, wait); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 59ee808f8fd9..d453756ca128 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2331,12 +2331,12 @@ static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer) * * Returns: any poll events that are ready without sleeping */ -static unsigned int i915_perf_poll_locked(struct drm_i915_private *dev_priv, +static __poll_t i915_perf_poll_locked(struct drm_i915_private *dev_priv, struct i915_perf_stream *stream, struct file *file, poll_table *wait) { - unsigned int events = 0; + __poll_t events = 0; stream->ops->poll_wait(stream, file, wait); @@ -2365,11 +2365,11 @@ static unsigned int i915_perf_poll_locked(struct drm_i915_private *dev_priv, * * Returns: any poll events that are ready without sleeping */ -static unsigned int i915_perf_poll(struct file *file, poll_table *wait) +static __poll_t i915_perf_poll(struct file *file, poll_table *wait) { struct i915_perf_stream *stream = file->private_data; struct drm_i915_private *dev_priv = stream->dev_priv; - int ret; + __poll_t ret; mutex_lock(&dev_priv->perf.lock); ret = i915_perf_poll_locked(dev_priv, stream, file, wait); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 7e5f30e234b1..d08753e8fd94 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -713,7 +713,7 @@ extern int vmw_present_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern unsigned int vmw_fops_poll(struct file *filp, +extern __poll_t vmw_fops_poll(struct file *filp, struct poll_table_struct *wait); extern ssize_t vmw_fops_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 01be355525e4..67f844678ac8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -412,7 +412,7 @@ out_clips: * Wrapper around the drm_poll function that makes sure the device is * processing the fifo if drm_poll decides to wait. */ -unsigned int vmw_fops_poll(struct file *filp, struct poll_table_struct *wait) +__poll_t vmw_fops_poll(struct file *filp, struct poll_table_struct *wait) { struct drm_file *file_priv = filp->private_data; struct vmw_private *dev_priv = diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index d35d6d271f3f..dfd8d0048980 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c @@ -1266,7 +1266,7 @@ done: return ret_val; } -static unsigned int vga_arb_fpoll(struct file *file, poll_table *wait) +static __poll_t vga_arb_fpoll(struct file *file, poll_table *wait) { pr_debug("%s\n", __func__); diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 5271db593478..c783fd5ef809 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -1179,7 +1179,7 @@ out: return ret; } -static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait) +static __poll_t hid_debug_events_poll(struct file *file, poll_table *wait) { struct hid_debug_list *list = file->private_data; diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index fb77dec720a4..b7e86aba6f33 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c @@ -137,7 +137,7 @@ exit_unlock: return retval; } -static unsigned int roccat_poll(struct file *file, poll_table *wait) +static __poll_t roccat_poll(struct file *file, poll_table *wait) { struct roccat_reader *reader = file->private_data; poll_wait(file, &reader->device->wait, wait); diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c index 0bcf041368c7..21ed6c55c40a 100644 --- a/drivers/hid/hid-sensor-custom.c +++ b/drivers/hid/hid-sensor-custom.c @@ -702,11 +702,11 @@ static int hid_sensor_custom_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); } -static unsigned int hid_sensor_custom_poll(struct file *file, +static __poll_t hid_sensor_custom_poll(struct file *file, struct poll_table_struct *wait) { struct hid_sensor_custom *sensor_inst; - unsigned int mask = 0; + __poll_t mask = 0; sensor_inst = container_of(file->private_data, struct hid_sensor_custom, custom_dev); diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 5fbe0f81ab2e..be210219f982 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -249,7 +249,7 @@ out: return ret; } -static unsigned int hidraw_poll(struct file *file, poll_table *wait) +static __poll_t hidraw_poll(struct file *file, poll_table *wait) { struct hidraw_list *list = file->private_data; diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 6f819f144cb4..fc43850a155e 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -753,7 +753,7 @@ unlock: return ret ? ret : count; } -static unsigned int uhid_char_poll(struct file *file, poll_table *wait) +static __poll_t uhid_char_poll(struct file *file, poll_table *wait) { struct uhid_device *uhid = file->private_data; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 7d749b19c27c..0ff3e7e70c8d 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -422,7 +422,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun * "poll" file op * No kernel lock - fine */ -static unsigned int hiddev_poll(struct file *file, poll_table *wait) +static __poll_t hiddev_poll(struct file *file, poll_table *wait) { struct hiddev_list *list = file->private_data; diff --git a/drivers/hsi/clients/cmt_speech.c b/drivers/hsi/clients/cmt_speech.c index 727f968ac1cb..e6ad3de6c975 100644 --- a/drivers/hsi/clients/cmt_speech.c +++ b/drivers/hsi/clients/cmt_speech.c @@ -1124,10 +1124,10 @@ static int cs_char_fasync(int fd, struct file *file, int on) return 0; } -static unsigned int cs_char_poll(struct file *file, poll_table *wait) +static __poll_t cs_char_poll(struct file *file, poll_table *wait) { struct cs_char *csdata = file->private_data; - unsigned int ret = 0; + __poll_t ret = 0; poll_wait(file, &cs_char_data.wait, wait); spin_lock_bh(&csdata->lock); diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c index 4402a71e23f7..047959e74bb1 100644 --- a/drivers/hv/hv_utils_transport.c +++ b/drivers/hv/hv_utils_transport.c @@ -104,7 +104,7 @@ static ssize_t hvt_op_write(struct file *file, const char __user *buf, return ret ? ret : count; } -static unsigned int hvt_op_poll(struct file *file, poll_table *wait) +static __poll_t hvt_op_poll(struct file *file, poll_table *wait) { struct hvutil_transport *hvt; diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 4c45488e3a7f..c775fedbcaf6 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -43,7 +43,7 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals); #ifdef CONFIG_IIO_BUFFER struct poll_table_struct; -unsigned int iio_buffer_poll(struct file *filp, +__poll_t iio_buffer_poll(struct file *filp, struct poll_table_struct *wait); ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, size_t n, loff_t *f_ps); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index d2b465140a6b..0bc2fe31f211 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -169,7 +169,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, * Return: (POLLIN | POLLRDNORM) if data is available for reading * or 0 for other cases */ -unsigned int iio_buffer_poll(struct file *filp, +__poll_t iio_buffer_poll(struct file *filp, struct poll_table_struct *wait) { struct iio_dev *indio_dev = filp->private_data; diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 90fac8ec63c9..0bcf073e46db 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -95,12 +95,12 @@ EXPORT_SYMBOL(iio_push_event); * Return: (POLLIN | POLLRDNORM) if data is available for reading * or a negative error code on failure */ -static unsigned int iio_event_poll(struct file *filep, +static __poll_t iio_event_poll(struct file *filep, struct poll_table_struct *wait) { struct iio_dev *indio_dev = filep->private_data; struct iio_event_interface *ev_int = indio_dev->event_interface; - unsigned int events = 0; + __poll_t events = 0; if (!indio_dev->info) return events; diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index f2a7f62c2834..f7adae0adc19 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -1130,11 +1130,11 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf, return result; } -static unsigned int ib_ucm_poll(struct file *filp, +static __poll_t ib_ucm_poll(struct file *filp, struct poll_table_struct *wait) { struct ib_ucm_file *file = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(filp, &file->poll_wait, wait); diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index eb85b546e223..e4be89d1f3d8 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -1630,10 +1630,10 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf, return ret; } -static unsigned int ucma_poll(struct file *filp, struct poll_table_struct *wait) +static __poll_t ucma_poll(struct file *filp, struct poll_table_struct *wait) { struct ucma_file *file = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(filp, &file->poll_wait, wait); diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 4b64dd02e090..0c32d10f23ff 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -617,12 +617,12 @@ err: return ret; } -static unsigned int ib_umad_poll(struct file *filp, struct poll_table_struct *wait) +static __poll_t ib_umad_poll(struct file *filp, struct poll_table_struct *wait) { struct ib_umad_file *file = filp->private_data; /* we will always be able to post a MAD send */ - unsigned int mask = POLLOUT | POLLWRNORM; + __poll_t mask = POLLOUT | POLLWRNORM; poll_wait(filp, &file->recv_wait, wait); diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 381fd9c096ae..5f216ffb465a 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -339,11 +339,11 @@ static ssize_t ib_uverbs_comp_event_read(struct file *filp, char __user *buf, sizeof(struct ib_uverbs_comp_event_desc)); } -static unsigned int ib_uverbs_event_poll(struct ib_uverbs_event_queue *ev_queue, +static __poll_t ib_uverbs_event_poll(struct ib_uverbs_event_queue *ev_queue, struct file *filp, struct poll_table_struct *wait) { - unsigned int pollflags = 0; + __poll_t pollflags = 0; poll_wait(filp, &ev_queue->poll_wait, wait); @@ -355,13 +355,13 @@ static unsigned int ib_uverbs_event_poll(struct ib_uverbs_event_queue *ev_queue, return pollflags; } -static unsigned int ib_uverbs_async_event_poll(struct file *filp, +static __poll_t ib_uverbs_async_event_poll(struct file *filp, struct poll_table_struct *wait) { return ib_uverbs_event_poll(filp->private_data, filp, wait); } -static unsigned int ib_uverbs_comp_event_poll(struct file *filp, +static __poll_t ib_uverbs_comp_event_poll(struct file *filp, struct poll_table_struct *wait) { struct ib_uverbs_completion_event_file *comp_ev_file = diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c index 7750a9c38b06..82086241aac3 100644 --- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -74,7 +74,7 @@ static int hfi1_file_open(struct inode *inode, struct file *fp); static int hfi1_file_close(struct inode *inode, struct file *fp); static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from); -static unsigned int hfi1_poll(struct file *fp, struct poll_table_struct *pt); +static __poll_t hfi1_poll(struct file *fp, struct poll_table_struct *pt); static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma); static u64 kvirt_to_phys(void *addr); @@ -102,8 +102,8 @@ static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd, struct hfi1_user_info *uinfo, struct hfi1_ctxtdata **cd); static void deallocate_ctxt(struct hfi1_ctxtdata *uctxt); -static unsigned int poll_urgent(struct file *fp, struct poll_table_struct *pt); -static unsigned int poll_next(struct file *fp, struct poll_table_struct *pt); +static __poll_t poll_urgent(struct file *fp, struct poll_table_struct *pt); +static __poll_t poll_next(struct file *fp, struct poll_table_struct *pt); static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt, unsigned long arg); static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, unsigned long arg); @@ -607,10 +607,10 @@ static int vma_fault(struct vm_fault *vmf) return 0; } -static unsigned int hfi1_poll(struct file *fp, struct poll_table_struct *pt) +static __poll_t hfi1_poll(struct file *fp, struct poll_table_struct *pt) { struct hfi1_ctxtdata *uctxt; - unsigned pollflag; + __poll_t pollflag; uctxt = ((struct hfi1_filedata *)fp->private_data)->uctxt; if (!uctxt) @@ -1425,13 +1425,13 @@ static int user_exp_rcv_invalid(struct hfi1_filedata *fd, unsigned long arg, return ret; } -static unsigned int poll_urgent(struct file *fp, +static __poll_t poll_urgent(struct file *fp, struct poll_table_struct *pt) { struct hfi1_filedata *fd = fp->private_data; struct hfi1_ctxtdata *uctxt = fd->uctxt; struct hfi1_devdata *dd = uctxt->dd; - unsigned pollflag; + __poll_t pollflag; poll_wait(fp, &uctxt->wait, pt); @@ -1448,13 +1448,13 @@ static unsigned int poll_urgent(struct file *fp, return pollflag; } -static unsigned int poll_next(struct file *fp, +static __poll_t poll_next(struct file *fp, struct poll_table_struct *pt) { struct hfi1_filedata *fd = fp->private_data; struct hfi1_ctxtdata *uctxt = fd->uctxt; struct hfi1_devdata *dd = uctxt->dd; - unsigned pollflag; + __poll_t pollflag; poll_wait(fp, &uctxt->wait, pt); diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 2d6a191afec0..b67df63bd64b 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -58,7 +58,7 @@ static int qib_open(struct inode *, struct file *); static int qib_close(struct inode *, struct file *); static ssize_t qib_write(struct file *, const char __user *, size_t, loff_t *); static ssize_t qib_write_iter(struct kiocb *, struct iov_iter *); -static unsigned int qib_poll(struct file *, struct poll_table_struct *); +static __poll_t qib_poll(struct file *, struct poll_table_struct *); static int qib_mmapf(struct file *, struct vm_area_struct *); /* @@ -1092,12 +1092,12 @@ bail: return ret; } -static unsigned int qib_poll_urgent(struct qib_ctxtdata *rcd, +static __poll_t qib_poll_urgent(struct qib_ctxtdata *rcd, struct file *fp, struct poll_table_struct *pt) { struct qib_devdata *dd = rcd->dd; - unsigned pollflag; + __poll_t pollflag; poll_wait(fp, &rcd->wait, pt); @@ -1114,12 +1114,12 @@ static unsigned int qib_poll_urgent(struct qib_ctxtdata *rcd, return pollflag; } -static unsigned int qib_poll_next(struct qib_ctxtdata *rcd, +static __poll_t qib_poll_next(struct qib_ctxtdata *rcd, struct file *fp, struct poll_table_struct *pt) { struct qib_devdata *dd = rcd->dd; - unsigned pollflag; + __poll_t pollflag; poll_wait(fp, &rcd->wait, pt); @@ -1135,10 +1135,10 @@ static unsigned int qib_poll_next(struct qib_ctxtdata *rcd, return pollflag; } -static unsigned int qib_poll(struct file *fp, struct poll_table_struct *pt) +static __poll_t qib_poll(struct file *fp, struct poll_table_struct *pt) { struct qib_ctxtdata *rcd; - unsigned pollflag; + __poll_t pollflag; rcd = ctxt_fp(fp); if (!rcd) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 925571475005..0193dd4f0452 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -635,11 +635,11 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, } /* No kernel lock - fine */ -static unsigned int evdev_poll(struct file *file, poll_table *wait) +static __poll_t evdev_poll(struct file *file, poll_table *wait) { struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; - unsigned int mask; + __poll_t mask; poll_wait(file, &evdev->wait, wait); diff --git a/drivers/input/input.c b/drivers/input/input.c index e30642db50d5..0d0b2ab1bb6b 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1048,7 +1048,7 @@ static inline void input_wakeup_procfs_readers(void) wake_up(&input_devices_poll_wait); } -static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) +static __poll_t input_proc_devices_poll(struct file *file, poll_table *wait) { poll_wait(file, &input_devices_poll_wait, wait); if (file->f_version != input_devices_state) { diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 7b29a8944039..fe3255572886 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -436,7 +436,7 @@ static ssize_t joydev_read(struct file *file, char __user *buf, } /* No kernel lock - fine */ -static unsigned int joydev_poll(struct file *file, poll_table *wait) +static __poll_t joydev_poll(struct file *file, poll_table *wait) { struct joydev_client *client = file->private_data; struct joydev *joydev = client->joydev; diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index 1c8c56efc995..9c3f7ec3bd3d 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c @@ -408,7 +408,7 @@ static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, return retval; } -static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait) +static __poll_t hp_sdc_rtc_poll(struct file *file, poll_table *wait) { unsigned long l; diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 39ddd9a73feb..91df0df15e68 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -694,7 +694,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, return retval; } -static unsigned int uinput_poll(struct file *file, poll_table *wait) +static __poll_t uinput_poll(struct file *file, poll_table *wait) { struct uinput_device *udev = file->private_data; diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 2d7f691ec71c..731d84ae5101 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -757,11 +757,11 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer, } /* No kernel lock - fine */ -static unsigned int mousedev_poll(struct file *file, poll_table *wait) +static __poll_t mousedev_poll(struct file *file, poll_table *wait) { struct mousedev_client *client = file->private_data; struct mousedev *mousedev = client->mousedev; - unsigned int mask; + __poll_t mask; poll_wait(file, &mousedev->wait, wait); diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 516f9fe77a17..fccf55a380b2 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -239,11 +239,11 @@ out: return retval; } -static unsigned int serio_raw_poll(struct file *file, poll_table *wait) +static __poll_t serio_raw_poll(struct file *file, poll_table *wait) { struct serio_raw_client *client = file->private_data; struct serio_raw *serio_raw = client->serio_raw; - unsigned int mask; + __poll_t mask; poll_wait(file, &serio_raw->wait, wait); diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c index df1fd41860ac..a63de06b08bc 100644 --- a/drivers/input/serio/userio.c +++ b/drivers/input/serio/userio.c @@ -248,7 +248,7 @@ out: return error ?: count; } -static unsigned int userio_char_poll(struct file *file, poll_table *wait) +static __poll_t userio_char_poll(struct file *file, poll_table *wait) { struct userio_device *userio = file->private_data; diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index dde8f46bc254..e268811dc544 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -724,11 +724,11 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos return count; } -static unsigned int +static __poll_t capi_poll(struct file *file, poll_table *wait) { struct capidev *cdev = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; if (!cdev->ap.applid) return POLLERR; diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 1c5dc345e7c5..34b7704042a4 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -119,10 +119,10 @@ isdn_divert_write(struct file *file, const char __user *buf, size_t count, loff_ /***************************************/ /* select routines for various kernels */ /***************************************/ -static unsigned int +static __poll_t isdn_divert_poll(struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &(rd_queue), wait); /* mask = POLLOUT | POLLWRNORM; */ diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c index 72e58bf07577..70f16102a001 100644 --- a/drivers/isdn/hardware/eicon/divamnt.c +++ b/drivers/isdn/hardware/eicon/divamnt.c @@ -98,9 +98,9 @@ void diva_os_get_time(dword *sec, dword *usec) /* * device node operations */ -static unsigned int maint_poll(struct file *file, poll_table *wait) +static __poll_t maint_poll(struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &msgwaitq, wait); mask = POLLOUT | POLLWRNORM; diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c index 0033d74a7291..da5cc5ab7e2d 100644 --- a/drivers/isdn/hardware/eicon/divasi.c +++ b/drivers/isdn/hardware/eicon/divasi.c @@ -74,7 +74,7 @@ static ssize_t um_idi_read(struct file *file, char __user *buf, size_t count, loff_t *offset); static ssize_t um_idi_write(struct file *file, const char __user *buf, size_t count, loff_t *offset); -static unsigned int um_idi_poll(struct file *file, poll_table *wait); +static __poll_t um_idi_poll(struct file *file, poll_table *wait); static int um_idi_open(struct inode *inode, struct file *file); static int um_idi_release(struct inode *inode, struct file *file); static int remove_entity(void *entity); @@ -365,7 +365,7 @@ um_idi_write(struct file *file, const char __user *buf, size_t count, return (ret); } -static unsigned int um_idi_poll(struct file *file, poll_table *wait) +static __poll_t um_idi_poll(struct file *file, poll_table *wait) { diva_um_idi_os_context_t *p_os; diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index b2023e08dcd2..fbc788e6f0db 100644 --- a/drivers/isdn/hardware/eicon/divasmain.c +++ b/drivers/isdn/hardware/eicon/divasmain.c @@ -650,7 +650,7 @@ static ssize_t divas_read(struct file *file, char __user *buf, return (ret); } -static unsigned int divas_poll(struct file *file, poll_table *wait) +static __poll_t divas_poll(struct file *file, poll_table *wait) { if (!file->private_data) { return (POLLERR); diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c index b57efd6ad916..3478f6f099eb 100644 --- a/drivers/isdn/hardware/eicon/divasproc.c +++ b/drivers/isdn/hardware/eicon/divasproc.c @@ -99,7 +99,7 @@ divas_write(struct file *file, const char __user *buf, size_t count, loff_t *off return (-ENODEV); } -static unsigned int divas_poll(struct file *file, poll_table *wait) +static __poll_t divas_poll(struct file *file, poll_table *wait) { return (POLLERR); } diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index aaca0b3d662e..6abea6915f49 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -281,10 +281,10 @@ hysdn_log_close(struct inode *ino, struct file *filep) /*************************************************/ /* select/poll routine to be able using select() */ /*************************************************/ -static unsigned int +static __poll_t hysdn_log_poll(struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; hysdn_card *card = PDE_DATA(file_inode(file)); struct procdata *pd = card->proclog; diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 8b03d618185e..0521c32949d4 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1227,10 +1227,10 @@ out: return retval; } -static unsigned int +static __poll_t isdn_poll(struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; unsigned int minor = iminor(file_inode(file)); int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index e07aefb9151d..57884319b4b1 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -685,10 +685,10 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) return 0; } -unsigned int +__poll_t isdn_ppp_poll(struct file *file, poll_table *wait) { - u_int mask; + __poll_t mask; struct ippp_buf_queue *bf, *bl; u_long flags; struct ippp_struct *is; diff --git a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h index 4e9b8935a4eb..34b8a2ce84f3 100644 --- a/drivers/isdn/i4l/isdn_ppp.h +++ b/drivers/isdn/i4l/isdn_ppp.h @@ -23,7 +23,7 @@ extern int isdn_ppp_autodial_filter(struct sk_buff *, isdn_net_local *); extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *); extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *); extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int); -extern unsigned int isdn_ppp_poll(struct file *, struct poll_table_struct *); +extern __poll_t isdn_ppp_poll(struct file *, struct poll_table_struct *); extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long); extern void isdn_ppp_release(int, struct file *); extern int isdn_ppp_dial_slave(char *); diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index c50a34340f67..f4272d4e0a26 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c @@ -141,11 +141,11 @@ mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off) return ret; } -static unsigned int +static __poll_t mISDN_poll(struct file *filep, poll_table *wait) { struct mISDNtimerdev *dev = filep->private_data; - unsigned int mask = POLLERR; + __poll_t mask = POLLERR; if (*debug & DEBUG_TIMER) printk(KERN_DEBUG "%s(%p, %p)\n", __func__, filep, wait); diff --git a/drivers/leds/uleds.c b/drivers/leds/uleds.c index 5e9e8a1fdefb..5beacab05ed7 100644 --- a/drivers/leds/uleds.c +++ b/drivers/leds/uleds.c @@ -176,7 +176,7 @@ static ssize_t uleds_read(struct file *file, char __user *buffer, size_t count, return retval; } -static unsigned int uleds_poll(struct file *file, poll_table *wait) +static __poll_t uleds_poll(struct file *file, poll_table *wait) { struct uleds_device *udev = file->private_data; diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 899ec1f4c833..346e6f5f77be 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -1245,10 +1245,10 @@ static ssize_t smu_read(struct file *file, char __user *buf, return -EBADFD; } -static unsigned int smu_fpoll(struct file *file, poll_table *wait) +static __poll_t smu_fpoll(struct file *file, poll_table *wait) { struct smu_private *pp = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; unsigned long flags; if (pp == 0) diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index c4c2b3b85ebc..e8b29fc532e1 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2157,11 +2157,11 @@ pmu_write(struct file *file, const char __user *buf, return 0; } -static unsigned int +static __poll_t pmu_fpoll(struct file *filp, poll_table *wait) { struct pmu_private *pp = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; unsigned long flags; if (pp == 0) diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c index 93f3d4d61fa7..f84730d63b1f 100644 --- a/drivers/mailbox/mailbox-test.c +++ b/drivers/mailbox/mailbox-test.c @@ -235,7 +235,7 @@ kfree_err: return ret; } -static unsigned int +static __poll_t mbox_test_message_poll(struct file *filp, struct poll_table_struct *wait) { struct mbox_test_device *tdev = filp->private_data; diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index e52676fa9832..3f6791afd3e4 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1929,10 +1929,10 @@ static int dm_release(struct inode *inode, struct file *filp) return 0; } -static unsigned dm_poll(struct file *filp, poll_table *wait) +static __poll_t dm_poll(struct file *filp, poll_table *wait) { struct dm_file *priv = filp->private_data; - unsigned mask = 0; + __poll_t mask = 0; poll_wait(filp, &dm_global_eventq, wait); diff --git a/drivers/md/md.c b/drivers/md/md.c index 41c050b59ec4..e638d7199bd4 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7869,10 +7869,10 @@ static int md_seq_open(struct inode *inode, struct file *file) } static int md_unloading; -static unsigned int mdstat_poll(struct file *filp, poll_table *wait) +static __poll_t mdstat_poll(struct file *filp, poll_table *wait) { struct seq_file *seq = filp->private_data; - int mask; + __poll_t mask; if (md_unloading) return POLLIN|POLLRDNORM|POLLERR|POLLPRI; diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 7c11bad5cded..753b1a698fc4 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -427,7 +427,7 @@ int cxl_fd_mmap(struct file *file, struct vm_area_struct *vm) return afu_mmap(file, vm); } EXPORT_SYMBOL_GPL(cxl_fd_mmap); -unsigned int cxl_fd_poll(struct file *file, struct poll_table_struct *poll) +__poll_t cxl_fd_poll(struct file *file, struct poll_table_struct *poll) { return afu_poll(file, poll); } diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index e46a4062904a..a798c2ccd67d 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h @@ -1081,7 +1081,7 @@ int afu_open(struct inode *inode, struct file *file); int afu_release(struct inode *inode, struct file *file); long afu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); int afu_mmap(struct file *file, struct vm_area_struct *vm); -unsigned int afu_poll(struct file *file, struct poll_table_struct *poll); +__poll_t afu_poll(struct file *file, struct poll_table_struct *poll); ssize_t afu_read(struct file *file, char __user *buf, size_t count, loff_t *off); extern const struct file_operations afu_fops; diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c index 76c0b0ca9388..90341ccda9bd 100644 --- a/drivers/misc/cxl/file.c +++ b/drivers/misc/cxl/file.c @@ -354,10 +354,10 @@ static inline bool ctx_event_pending(struct cxl_context *ctx) return false; } -unsigned int afu_poll(struct file *file, struct poll_table_struct *poll) +__poll_t afu_poll(struct file *file, struct poll_table_struct *poll) { struct cxl_context *ctx = file->private_data; - int mask = 0; + __poll_t mask = 0; unsigned long flags; diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index 097e3092c158..95ce3e891b1b 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c @@ -514,7 +514,7 @@ static ssize_t ilo_write(struct file *fp, const char __user *buf, return err ? -EFAULT : len; } -static unsigned int ilo_poll(struct file *fp, poll_table *wait) +static __poll_t ilo_poll(struct file *fp, poll_table *wait) { struct ccb_data *data = fp->private_data; struct ccb *driver_ccb = &data->driver_ccb; diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index 8d53609861d8..e49888eab87d 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c @@ -651,7 +651,7 @@ out: return retval; } -static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) +static __poll_t lis3lv02d_misc_poll(struct file *file, poll_table *wait) { struct lis3lv02d *lis3 = container_of(file->private_data, struct lis3lv02d, miscdev); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 4f704641c574..505b710291e6 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -542,12 +542,12 @@ static long mei_compat_ioctl(struct file *file, * * Return: poll mask */ -static unsigned int mei_poll(struct file *file, poll_table *wait) +static __poll_t mei_poll(struct file *file, poll_table *wait) { __poll_t req_events = poll_requested_events(wait); struct mei_cl *cl = file->private_data; struct mei_device *dev; - unsigned int mask = 0; + __poll_t mask = 0; bool notify_en; if (WARN_ON(!cl || !cl->dev)) diff --git a/drivers/misc/mic/scif/scif_api.c b/drivers/misc/mic/scif/scif_api.c index ddc9e4b08b5c..8a3e48ec37dd 100644 --- a/drivers/misc/mic/scif/scif_api.c +++ b/drivers/misc/mic/scif/scif_api.c @@ -1311,10 +1311,10 @@ static inline void _scif_poll_wait(struct file *f, wait_queue_head_t *wq, spin_lock(&ep->lock); } -unsigned int +__poll_t __scif_pollfd(struct file *f, poll_table *wait, struct scif_endpt *ep) { - unsigned int mask = 0; + __poll_t mask = 0; dev_dbg(scif_info.mdev.this_device, "SCIFAPI pollfd: ep %p %s\n", ep, scif_ep_states[ep->state]); @@ -1389,7 +1389,8 @@ scif_poll(struct scif_pollepd *ufds, unsigned int nfds, long timeout_msecs) { struct poll_wqueues table; poll_table *pt; - int i, mask, count = 0, timed_out = timeout_msecs == 0; + int i, count = 0, timed_out = timeout_msecs == 0; + __poll_t mask; u64 timeout = timeout_msecs < 0 ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(timeout_msecs); diff --git a/drivers/misc/mic/scif/scif_epd.h b/drivers/misc/mic/scif/scif_epd.h index 1771d7a9b8d0..f39b663da287 100644 --- a/drivers/misc/mic/scif/scif_epd.h +++ b/drivers/misc/mic/scif/scif_epd.h @@ -203,7 +203,7 @@ void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg); int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block); int __scif_flush(scif_epd_t epd); int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd); -unsigned int __scif_pollfd(struct file *f, poll_table *wait, +__poll_t __scif_pollfd(struct file *f, poll_table *wait, struct scif_endpt *ep); int __scif_pin_pages(void *addr, size_t len, int *out_prot, int map_flags, scif_pinned_pages_t *pages); diff --git a/drivers/misc/mic/scif/scif_fd.c b/drivers/misc/mic/scif/scif_fd.c index f7e826142a72..5c2a57ae4f85 100644 --- a/drivers/misc/mic/scif/scif_fd.c +++ b/drivers/misc/mic/scif/scif_fd.c @@ -41,7 +41,7 @@ static int scif_fdmmap(struct file *f, struct vm_area_struct *vma) return scif_mmap(vma, priv); } -static unsigned int scif_fdpoll(struct file *f, poll_table *wait) +static __poll_t scif_fdpoll(struct file *f, poll_table *wait) { struct scif_endpt *priv = f->private_data; diff --git a/drivers/misc/mic/vop/vop_vringh.c b/drivers/misc/mic/vop/vop_vringh.c index fed992e2c258..4120ed8f0cae 100644 --- a/drivers/misc/mic/vop/vop_vringh.c +++ b/drivers/misc/mic/vop/vop_vringh.c @@ -1023,10 +1023,10 @@ __unlock_ret: * in the card->host (TX) path, when userspace is unblocked by poll it * must drain all available descriptors or it can stall. */ -static unsigned int vop_poll(struct file *f, poll_table *wait) +static __poll_t vop_poll(struct file *f, poll_table *wait) { struct vop_vdev *vdev = f->private_data; - int mask = 0; + __poll_t mask = 0; mutex_lock(&vdev->vdev_mutex); if (vop_vdev_inited(vdev)) { diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index 30754927fd80..8fa68cf308e0 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c @@ -256,10 +256,10 @@ static int phantom_release(struct inode *inode, struct file *file) return 0; } -static unsigned int phantom_poll(struct file *file, poll_table *wait) +static __poll_t phantom_poll(struct file *file, poll_table *wait) { struct phantom_device *dev = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; pr_debug("phantom_poll: %d\n", atomic_read(&dev->counter)); poll_wait(file, &dev->wait, wait); diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index 8a16a26e9658..6640e7651533 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -166,11 +166,11 @@ static int vmci_host_close(struct inode *inode, struct file *filp) * This is used to wake up the VMX when a VMCI call arrives, or * to wake up select() or poll() at the next clock tick. */ -static unsigned int vmci_host_poll(struct file *filp, poll_table *wait) +static __poll_t vmci_host_poll(struct file *filp, poll_table *wait) { struct vmci_host_dev *vmci_host_dev = filp->private_data; struct vmci_ctx *context = vmci_host_dev->context; - unsigned int mask = 0; + __poll_t mask = 0; if (vmci_host_dev->ct_type == VMCIOBJ_CONTEXT) { /* Check for VMCI calls to this VM context. */ diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 7900ed066d8a..e412dfdda7dd 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -2638,12 +2638,12 @@ static long ca8210_test_int_ioctl( * * Return: set of poll return flags */ -static unsigned int ca8210_test_int_poll( +static __poll_t ca8210_test_int_poll( struct file *filp, struct poll_table_struct *ptable ) { - unsigned int return_flags = 0; + __poll_t return_flags = 0; struct ca8210_priv *priv = filp->private_data; poll_wait(filp, &priv->test.readq, ptable); diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c index 1b28e6e702f5..bdc4d23627c5 100644 --- a/drivers/net/ppp/ppp_async.c +++ b/drivers/net/ppp/ppp_async.c @@ -334,7 +334,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, } /* No kernel lock - fine */ -static unsigned int +static __poll_t ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { return 0; diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index d8e5747ff4e3..422723230f8b 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -531,10 +531,10 @@ static ssize_t ppp_write(struct file *file, const char __user *buf, } /* No kernel lock - fine */ -static unsigned int ppp_poll(struct file *file, poll_table *wait) +static __poll_t ppp_poll(struct file *file, poll_table *wait) { struct ppp_file *pf = file->private_data; - unsigned int mask; + __poll_t mask; if (!pf) return 0; diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c index 7196f00f0991..047f6c68a441 100644 --- a/drivers/net/ppp/ppp_synctty.c +++ b/drivers/net/ppp/ppp_synctty.c @@ -327,7 +327,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, } /* No kernel lock - fine */ -static unsigned int +static __poll_t ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { return 0; diff --git a/drivers/net/tap.c b/drivers/net/tap.c index e9489b88407c..c4e91c73568e 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -572,10 +572,10 @@ static int tap_release(struct inode *inode, struct file *file) return 0; } -static unsigned int tap_poll(struct file *file, poll_table *wait) +static __poll_t tap_poll(struct file *file, poll_table *wait) { struct tap_queue *q = file->private_data; - unsigned int mask = POLLERR; + __poll_t mask = POLLERR; if (!q) goto out; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 95749006d687..130b049ac3da 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1248,12 +1248,12 @@ static void tun_net_init(struct net_device *dev) /* Character device part */ /* Poll */ -static unsigned int tun_chr_poll(struct file *file, poll_table *wait) +static __poll_t tun_chr_poll(struct file *file, poll_table *wait) { struct tun_file *tfile = file->private_data; struct tun_struct *tun = tun_get(tfile); struct sock *sk; - unsigned int mask = 0; + __poll_t mask = 0; if (!tun) return POLLERR; diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 6ea16260ec76..f6b000ddcd15 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -924,7 +924,7 @@ static int chrdev_tx_done(struct channel_data *chan, int size) return 1; } -static unsigned int cosa_poll(struct file *file, poll_table *poll) +static __poll_t cosa_poll(struct file *file, poll_table *poll) { pr_info("cosa_poll is here\n"); return 0; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c index f4fdad2ed319..72c55d1f8903 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c @@ -301,7 +301,7 @@ exit: return status; } -static unsigned int rt2x00debug_poll_queue_dump(struct file *file, +static __poll_t rt2x00debug_poll_queue_dump(struct file *file, poll_table *wait) { struct rt2x00debug_intf *intf = file->private_data; diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c index 730cc897b94d..fab143a17f9c 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -510,11 +510,11 @@ out: return -EBADMSG; } -static unsigned int switchtec_dev_poll(struct file *filp, poll_table *wait) +static __poll_t switchtec_dev_poll(struct file *filp, poll_table *wait) { struct switchtec_user *stuser = filp->private_data; struct switchtec_dev *stdev = stuser->stdev; - int ret = 0; + __poll_t ret = 0; poll_wait(filp, &stuser->comp.wait, wait); poll_wait(filp, &stdev->event_wq, wait); diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index 4cc66f405760..603fa8bd85d3 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c @@ -191,11 +191,11 @@ error: return ret; } -static unsigned int cros_ec_console_log_poll(struct file *file, +static __poll_t cros_ec_console_log_poll(struct file *file, poll_table *wait) { struct cros_ec_debugfs *debug_info = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &debug_info->log_wq, wait); diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 0578d34eec3f..999f1152655a 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -536,10 +536,10 @@ static ssize_t goldfish_pipe_write(struct file *filp, /* is_write */ 1); } -static unsigned int goldfish_pipe_poll(struct file *filp, poll_table *wait) +static __poll_t goldfish_pipe_poll(struct file *filp, poll_table *wait) { struct goldfish_pipe *pipe = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; int status; poll_wait(filp, &pipe->wake_queue, wait); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 935121814c97..a4fabf9d75f3 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -4124,7 +4124,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, return ret; } -static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) +static __poll_t sonypi_misc_poll(struct file *file, poll_table *wait) { poll_wait(file, &sonypi_compat.fifo_proc_list, wait); if (kfifo_len(&sonypi_compat.fifo)) diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c index 6eb0db37dd88..1d42385b1aa5 100644 --- a/drivers/pps/pps.c +++ b/drivers/pps/pps.c @@ -49,7 +49,7 @@ static DEFINE_IDR(pps_idr); * Char device methods */ -static unsigned int pps_cdev_poll(struct file *file, poll_table *wait) +static __poll_t pps_cdev_poll(struct file *file, poll_table *wait) { struct pps_device *pps = file->private_data; diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index 58a97d420572..a593b4cf47bf 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -280,7 +280,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) return err; } -unsigned int ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait) +__poll_t ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait) { struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h index b86f1bfecd6f..c7c62b782cb9 100644 --- a/drivers/ptp/ptp_private.h +++ b/drivers/ptp/ptp_private.h @@ -90,7 +90,7 @@ int ptp_open(struct posix_clock *pc, fmode_t fmode); ssize_t ptp_read(struct posix_clock *pc, uint flags, char __user *buf, size_t cnt); -uint ptp_poll(struct posix_clock *pc, +__poll_t ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait); /* diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index ec4bc1515f0d..6092b3a5978e 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -2319,7 +2319,7 @@ static int mport_cdev_mmap(struct file *filp, struct vm_area_struct *vma) return ret; } -static unsigned int mport_cdev_poll(struct file *filp, poll_table *wait) +static __poll_t mport_cdev_poll(struct file *filp, poll_table *wait) { struct mport_cdev_priv *priv = filp->private_data; diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c index b01774e9fac0..e540ca362d08 100644 --- a/drivers/rpmsg/qcom_smd.c +++ b/drivers/rpmsg/qcom_smd.c @@ -919,12 +919,12 @@ static int qcom_smd_trysend(struct rpmsg_endpoint *ept, void *data, int len) return __qcom_smd_send(qsept->qsch, data, len, false); } -static unsigned int qcom_smd_poll(struct rpmsg_endpoint *ept, +static __poll_t qcom_smd_poll(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait) { struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept); struct qcom_smd_channel *channel = qsept->qsch; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(filp, &channel->fblockread_event, wait); diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index e0996fce3963..e622fcda30fa 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -256,10 +256,10 @@ free_kbuf: return ret < 0 ? ret : len; } -static unsigned int rpmsg_eptdev_poll(struct file *filp, poll_table *wait) +static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait) { struct rpmsg_eptdev *eptdev = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; if (!eptdev->ept) return POLLERR; diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index dffa3aab7178..5a081762afcc 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -247,7 +247,7 @@ EXPORT_SYMBOL(rpmsg_trysendto); * * Returns mask representing the current state of the endpoint's send buffers */ -unsigned int rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, +__poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait) { if (WARN_ON(!ept)) diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h index 0cf9c7e2ee83..685aa70e9cbe 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h @@ -71,7 +71,7 @@ struct rpmsg_endpoint_ops { int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len); - unsigned int (*poll)(struct rpmsg_endpoint *ept, struct file *filp, + __poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait); }; diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 215eac68ae2d..5a7b30d0773b 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -194,7 +194,7 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) return ret; } -static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) +static __poll_t rtc_dev_poll(struct file *file, poll_table *wait) { struct rtc_device *rtc = file->private_data; unsigned long data; diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index a7917d473774..0c075d100252 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -661,9 +661,9 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf, return effective_count; } -static unsigned int dasd_eer_poll(struct file *filp, poll_table *ptable) +static __poll_t dasd_eer_poll(struct file *filp, poll_table *ptable) { - unsigned int mask; + __poll_t mask; unsigned long flags; struct eerbuffer *eerb; diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 027ac6ae5eea..de7b169004a2 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -428,7 +428,7 @@ out_copy: return count; } -static unsigned int mon_poll(struct file *filp, struct poll_table_struct *p) +static __poll_t mon_poll(struct file *filp, struct poll_table_struct *p) { struct mon_private *monpriv = filp->private_data; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index cc54bdb5c712..2c8cfa27909d 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7004,9 +7004,9 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) /** * megasas_mgmt_poll - char node "poll" entry point * */ -static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) +static __poll_t megasas_mgmt_poll(struct file *file, poll_table *wait) { - unsigned int mask; + __poll_t mask; unsigned long flags; poll_wait(file, &megasas_poll_wait, wait); diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index b4c374b08e5e..537de1b7e8e5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -534,7 +534,7 @@ _ctl_fasync(int fd, struct file *filep, int mode) * @wait - * */ -static unsigned int +static __poll_t _ctl_poll(struct file *filep, poll_table *wait) { struct MPT3SAS_ADAPTER *ioc; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index f098877eed4a..c746c6936ee4 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1140,10 +1140,10 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon } #endif -static unsigned int +static __poll_t sg_poll(struct file *filp, poll_table * wait) { - unsigned int res = 0; + __poll_t res = 0; Sg_device *sdp; Sg_fd *sfp; Sg_request *srp; diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index e19e395b0e44..491b54d986eb 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2276,9 +2276,9 @@ done: return retval; } -static unsigned int comedi_poll(struct file *file, poll_table *wait) +static __poll_t comedi_poll(struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; struct comedi_file *cfp = file->private_data; struct comedi_device *dev = cfp->dev; struct comedi_subdevice *s, *s_read; diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 1e5cbc893496..69f530972273 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -287,10 +287,10 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) return copied; } -static unsigned int aim_poll(struct file *filp, poll_table *wait) +static __poll_t aim_poll(struct file *filp, poll_table *wait) { struct aim_channel *c = filp->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(filp, &c->wq, wait); diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index e0748416aee5..7783bc2dd9f5 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -209,11 +209,11 @@ static ssize_t aim_vdev_read(struct file *filp, char __user *buf, return ret; } -static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait) +static __poll_t aim_vdev_poll(struct file *filp, poll_table *wait) { struct aim_fh *fh = filp->private_data; struct most_video_dev *mdev = fh->mdev; - unsigned int mask = 0; + __poll_t mask = 0; /* only wait if no data is available */ if (!data_ready(mdev)) diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c index d99daf69e501..585c6aa124cd 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -326,10 +326,10 @@ static ssize_t softsynth_write(struct file *fp, const char __user *buf, return count; } -static unsigned int softsynth_poll(struct file *fp, struct poll_table_struct *wait) +static __poll_t softsynth_poll(struct file *fp, struct poll_table_struct *wait) { unsigned long flags; - int ret = 0; + __poll_t ret = 0; poll_wait(fp, &speakup_event, wait); diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 5131bdc9e765..0edf4fcfea23 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2457,10 +2457,10 @@ static ssize_t gsmld_write(struct tty_struct *tty, struct file *file, * Called without the kernel lock held - fine */ -static unsigned int gsmld_poll(struct tty_struct *tty, struct file *file, +static __poll_t gsmld_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; struct gsm_mux *gsm = tty->disc_data; poll_wait(file, &tty->read_wait, wait); diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index eea7b6cb3cc4..929434ebee50 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -180,7 +180,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t nr); static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, +static __poll_t n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait); static int n_hdlc_tty_open(struct tty_struct *tty); static void n_hdlc_tty_close(struct tty_struct *tty); @@ -796,11 +796,11 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, * to caller. * Returns a bit mask containing info on which ops will not block. */ -static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, +static __poll_t n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait) { struct n_hdlc *n_hdlc = tty2n_hdlc (tty); - unsigned int mask = 0; + __poll_t mask = 0; if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_poll() called\n",__FILE__,__LINE__); diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 30bb0900cd2f..e81d3db8ad63 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -135,7 +135,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, static int r3964_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); -static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, +static __poll_t r3964_poll(struct tty_struct *tty, struct file *file, struct poll_table_struct *wait); static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count); @@ -1216,14 +1216,14 @@ static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old) } /* Called without the kernel lock held - fine */ -static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, +static __poll_t r3964_poll(struct tty_struct *tty, struct file *file, struct poll_table_struct *wait) { struct r3964_info *pInfo = tty->disc_data; struct r3964_client_info *pClient; struct r3964_message *pMsg = NULL; unsigned long flags; - int result = POLLOUT; + __poll_t result = POLLOUT; TRACE_L("POLL"); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 427e0d5d8f13..081bbbb7d49c 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2368,10 +2368,10 @@ break_out: * Called without the kernel lock held - fine */ -static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, +static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &tty->read_wait, wait); poll_wait(file, &tty->write_wait, wait); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 287f9a4eef6d..00d14d6a76bb 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -144,7 +144,7 @@ static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *); -static unsigned int tty_poll(struct file *, poll_table *); +static __poll_t tty_poll(struct file *, poll_table *); static int tty_open(struct inode *, struct file *); long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); #ifdef CONFIG_COMPAT @@ -443,7 +443,7 @@ static ssize_t hung_up_tty_write(struct file *file, const char __user *buf, } /* No kernel lock held - none needed ;) */ -static unsigned int hung_up_tty_poll(struct file *filp, poll_table *wait) +static __poll_t hung_up_tty_poll(struct file *filp, poll_table *wait) { return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM; } @@ -2055,7 +2055,7 @@ retry_open: * may be re-entered freely by other callers. */ -static unsigned int tty_poll(struct file *filp, poll_table *wait) +static __poll_t tty_poll(struct file *filp, poll_table *wait) { struct tty_struct *tty = file_tty(filp); struct tty_ldisc *ld; diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 85b6634f518a..3e64ccd0040f 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -559,11 +559,11 @@ unlock_out: return ret; } -static unsigned int +static __poll_t vcs_poll(struct file *file, poll_table *wait) { struct vcs_poll_data *poll = vcs_poll_data_get(file); - int ret = DEFAULT_POLLMASK|POLLERR|POLLPRI; + __poll_t ret = DEFAULT_POLLMASK|POLLERR|POLLPRI; if (poll) { poll_wait(file, &poll->waitq, wait); diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index ff04b7f8549f..85bc1aaea4a4 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -496,7 +496,7 @@ static int uio_release(struct inode *inode, struct file *filep) return ret; } -static unsigned int uio_poll(struct file *filep, poll_table *wait) +static __poll_t uio_poll(struct file *filep, poll_table *wait) { struct uio_listener *listener = filep->private_data; struct uio_device *idev = listener->dev; diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 6c181a625daf..9627ea6ec3ae 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -595,11 +595,11 @@ static int wdm_flush(struct file *file, fl_owner_t id) return usb_translate_errors(desc->werr); } -static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t wdm_poll(struct file *file, struct poll_table_struct *wait) { struct wdm_device *desc = file->private_data; unsigned long flags; - unsigned int mask = 0; + __poll_t mask = 0; spin_lock_irqsave(&desc->iuspin, flags); if (test_bit(WDM_DISCONNECTING, &desc->flags)) { diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index c454885ef4a0..f45e8877771a 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -469,9 +469,9 @@ static int usblp_release(struct inode *inode, struct file *file) } /* No kernel lock - fine */ -static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait) +static __poll_t usblp_poll(struct file *file, struct poll_table_struct *wait) { - int ret; + __poll_t ret; unsigned long flags; struct usblp *usblp = file->private_data; diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 0b8b0f3bdd2f..7ea67a55be10 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1257,10 +1257,10 @@ static int usbtmc_fasync(int fd, struct file *file, int on) return fasync_helper(fd, file, on, &data->fasync); } -static unsigned int usbtmc_poll(struct file *file, poll_table *wait) +static __poll_t usbtmc_poll(struct file *file, poll_table *wait) { struct usbtmc_device_data *data = file->private_data; - unsigned int mask; + __poll_t mask; mutex_lock(&data->io_mutex); diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index c2cf62b7043a..e2cec448779e 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -622,7 +622,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, } /* Kernel lock for "lastev" protection */ -static unsigned int usb_device_poll(struct file *file, +static __poll_t usb_device_poll(struct file *file, struct poll_table_struct *wait) { unsigned int event_count; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 705c573d0257..929a7380be66 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2568,11 +2568,11 @@ static long usbdev_compat_ioctl(struct file *file, unsigned int cmd, #endif /* No kernel lock - fine */ -static unsigned int usbdev_poll(struct file *file, +static __poll_t usbdev_poll(struct file *file, struct poll_table_struct *wait) { struct usb_dev_state *ps = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &ps->wait, wait); if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 97ea059a7aa4..17efadd6b395 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -638,10 +638,10 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) return ret; } -static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait) +static __poll_t ffs_ep0_poll(struct file *file, poll_table *wait) { struct ffs_data *ffs = file->private_data; - unsigned int mask = POLLWRNORM; + __poll_t mask = POLLWRNORM; int ret; poll_wait(file, &ffs->ev.waitq, wait); diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index daae35318a3a..a73efb1c47d0 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -413,10 +413,10 @@ release_write_pending_unlocked: return status; } -static unsigned int f_hidg_poll(struct file *file, poll_table *wait) +static __poll_t f_hidg_poll(struct file *file, poll_table *wait) { struct f_hidg *hidg = file->private_data; - unsigned int ret = 0; + __poll_t ret = 0; poll_wait(file, &hidg->read_queue, wait); poll_wait(file, &hidg->write_queue, wait); diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index dd607b99eb1d..453578c4af69 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -680,12 +680,12 @@ printer_fsync(struct file *fd, loff_t start, loff_t end, int datasync) return 0; } -static unsigned int +static __poll_t printer_poll(struct file *fd, poll_table *wait) { struct printer_dev *dev = fd->private_data; unsigned long flags; - int status = 0; + __poll_t status = 0; mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 9343ec436485..05691254d473 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1209,11 +1209,11 @@ dev_release (struct inode *inode, struct file *fd) return 0; } -static unsigned int +static __poll_t ep0_poll (struct file *fd, poll_table *wait) { struct dev_data *dev = fd->private_data; - int mask = 0; + __poll_t mask = 0; if (dev->state <= STATE_DEV_OPENED) return DEFAULT_POLLMASK; diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index ad3109490c0f..1fa00b35f4ad 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -677,10 +677,10 @@ static int iowarrior_release(struct inode *inode, struct file *file) return retval; } -static unsigned iowarrior_poll(struct file *file, poll_table * wait) +static __poll_t iowarrior_poll(struct file *file, poll_table * wait) { struct iowarrior *dev = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; if (!dev->present) return POLLERR | POLLHUP; diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 5c1a3b852453..074398c1e410 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -409,10 +409,10 @@ exit: /** * ld_usb_poll */ -static unsigned int ld_usb_poll(struct file *file, poll_table *wait) +static __poll_t ld_usb_poll(struct file *file, poll_table *wait) { struct ld_usb *dev; - unsigned int mask = 0; + __poll_t mask = 0; dev = file->private_data; diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index c5be6e9e24a5..941c45028828 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -224,7 +224,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t static inline void tower_delete (struct lego_usb_tower *dev); static int tower_open (struct inode *inode, struct file *file); static int tower_release (struct inode *inode, struct file *file); -static unsigned int tower_poll (struct file *file, poll_table *wait); +static __poll_t tower_poll (struct file *file, poll_table *wait); static loff_t tower_llseek (struct file *file, loff_t off, int whence); static void tower_abort_transfers (struct lego_usb_tower *dev); @@ -509,10 +509,10 @@ static void tower_check_for_read_packet (struct lego_usb_tower *dev) /** * tower_poll */ -static unsigned int tower_poll (struct file *file, poll_table *wait) +static __poll_t tower_poll (struct file *file, poll_table *wait) { struct lego_usb_tower *dev; - unsigned int mask = 0; + __poll_t mask = 0; dev = file->private_data; diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index f6ae753ab99b..bc6fa666f75a 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1189,11 +1189,11 @@ static long mon_bin_compat_ioctl(struct file *file, } #endif /* CONFIG_COMPAT */ -static unsigned int +static __poll_t mon_bin_poll(struct file *file, struct poll_table_struct *wait) { struct mon_reader_bin *rp = file->private_data; - unsigned int mask = 0; + __poll_t mask = 0; unsigned long flags; if (file->f_mode & FMODE_READ) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 8d626d7c2e7e..0ed445a17c54 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -1353,7 +1353,7 @@ static ssize_t vhost_net_chr_write_iter(struct kiocb *iocb, return vhost_chr_write_iter(dev, from); } -static unsigned int vhost_net_chr_poll(struct file *file, poll_table *wait) +static __poll_t vhost_net_chr_poll(struct file *file, poll_table *wait) { struct vhost_net *n = file->private_data; struct vhost_dev *dev = &n->dev; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 7a897d2f2188..3bbeabff505a 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1057,10 +1057,10 @@ done: } EXPORT_SYMBOL(vhost_chr_write_iter); -unsigned int vhost_chr_poll(struct file *file, struct vhost_dev *dev, +__poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; poll_wait(file, &dev->wait, wait); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index d94245b2fcc2..7876a3d7d1b3 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -217,7 +217,7 @@ void vhost_enqueue_msg(struct vhost_dev *dev, struct vhost_msg_node *node); struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev, struct list_head *head); -unsigned int vhost_chr_poll(struct file *file, struct vhost_dev *dev, +__poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev, poll_table *wait); ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to, int noblock); diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c index d70ad6d38879..b0597bef4555 100644 --- a/drivers/virt/fsl_hypervisor.c +++ b/drivers/virt/fsl_hypervisor.c @@ -565,11 +565,11 @@ static irqreturn_t fsl_hv_state_change_isr(int irq, void *data) /* * Returns a bitmask indicating whether a read will block */ -static unsigned int fsl_hv_poll(struct file *filp, struct poll_table_struct *p) +static __poll_t fsl_hv_poll(struct file *filp, struct poll_table_struct *p) { struct doorbell_queue *dbq = filp->private_data; unsigned long flags; - unsigned int mask; + __poll_t mask; spin_lock_irqsave(&dbq->lock, flags); diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c index 9729a64ea1a9..72c0416a01cc 100644 --- a/drivers/xen/evtchn.c +++ b/drivers/xen/evtchn.c @@ -621,9 +621,9 @@ static long evtchn_ioctl(struct file *file, return rc; } -static unsigned int evtchn_poll(struct file *file, poll_table *wait) +static __poll_t evtchn_poll(struct file *file, poll_table *wait) { - unsigned int mask = POLLOUT | POLLWRNORM; + __poll_t mask = POLLOUT | POLLWRNORM; struct per_user_data *u = file->private_data; poll_wait(file, &u->evtchn_wait, wait); diff --git a/drivers/xen/mcelog.c b/drivers/xen/mcelog.c index 6cc1c15bcd84..9ade533d9e40 100644 --- a/drivers/xen/mcelog.c +++ b/drivers/xen/mcelog.c @@ -139,7 +139,7 @@ out: return err ? err : buf - ubuf; } -static unsigned int xen_mce_chrdev_poll(struct file *file, poll_table *wait) +static __poll_t xen_mce_chrdev_poll(struct file *file, poll_table *wait) { poll_wait(file, &xen_mce_chrdev_wait, wait); diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c index 40caa92bff33..74c854955a6b 100644 --- a/drivers/xen/pvcalls-front.c +++ b/drivers/xen/pvcalls-front.c @@ -878,7 +878,7 @@ received: return ret; } -static unsigned int pvcalls_front_poll_passive(struct file *file, +static __poll_t pvcalls_front_poll_passive(struct file *file, struct pvcalls_bedata *bedata, struct sock_mapping *map, poll_table *wait) @@ -935,12 +935,12 @@ static unsigned int pvcalls_front_poll_passive(struct file *file, return 0; } -static unsigned int pvcalls_front_poll_active(struct file *file, +static __poll_t pvcalls_front_poll_active(struct file *file, struct pvcalls_bedata *bedata, struct sock_mapping *map, poll_table *wait) { - unsigned int mask = 0; + __poll_t mask = 0; int32_t in_error, out_error; struct pvcalls_data_intf *intf = map->active.ring; @@ -958,12 +958,12 @@ static unsigned int pvcalls_front_poll_active(struct file *file, return mask; } -unsigned int pvcalls_front_poll(struct file *file, struct socket *sock, +__poll_t pvcalls_front_poll(struct file *file, struct socket *sock, poll_table *wait) { struct pvcalls_bedata *bedata; struct sock_mapping *map; - int ret; + __poll_t ret; pvcalls_enter(); if (!pvcalls_front_dev) { diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index f3b089b7c0b6..e17ec3fce590 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -645,7 +645,7 @@ static int xenbus_file_release(struct inode *inode, struct file *filp) return 0; } -static unsigned int xenbus_file_poll(struct file *file, poll_table *wait) +static __poll_t xenbus_file_poll(struct file *file, poll_table *wait) { struct xenbus_file_priv *u = file->private_data; diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 0e0c868451a5..5176c3797680 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -364,7 +364,7 @@ int drm_open(struct inode *inode, struct file *filp); ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset); int drm_release(struct inode *inode, struct file *filp); -unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); +__poll_t drm_poll(struct file *filp, struct poll_table_struct *wait); int drm_event_reserve_init_locked(struct drm_device *dev, struct drm_file *file_priv, struct drm_pending_event *p, diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 10d6ae8bbb7d..ca07366c4c33 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -157,7 +157,7 @@ int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, void *data, int len); -unsigned int rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, +__poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait); #else @@ -258,7 +258,7 @@ static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, return -ENXIO; } -static inline unsigned int rpmsg_poll(struct rpmsg_endpoint *ept, +static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, poll_table *wait) { /* This shouldn't be possible */ diff --git a/include/misc/cxl.h b/include/misc/cxl.h index 480d50a0b8ba..b712be544f8c 100644 --- a/include/misc/cxl.h +++ b/include/misc/cxl.h @@ -267,7 +267,7 @@ int cxl_fd_open(struct inode *inode, struct file *file); int cxl_fd_release(struct inode *inode, struct file *file); long cxl_fd_ioctl(struct file *file, unsigned int cmd, unsigned long arg); int cxl_fd_mmap(struct file *file, struct vm_area_struct *vm); -unsigned int cxl_fd_poll(struct file *file, struct poll_table_struct *poll); +__poll_t cxl_fd_poll(struct file *file, struct poll_table_struct *poll); ssize_t cxl_fd_read(struct file *file, char __user *buf, size_t count, loff_t *off); -- cgit v1.2.3 From fcc5a652a51332d5e6582697bd847b082a6b4e40 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Jul 2017 23:54:30 -0400 Subject: debugging printk in sg_poll() uses %x to print POLL... bitmap Signed-off-by: Al Viro --- drivers/scsi/sg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index c746c6936ee4..0c434453aab3 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1174,7 +1174,7 @@ sg_poll(struct file *filp, poll_table * wait) } else if (count < SG_MAX_QUEUE) res |= POLLOUT | POLLWRNORM; SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, - "sg_poll: res=0x%x\n", (int) res)); + "sg_poll: res=0x%x\n", (__force u32) res)); return res; } -- cgit v1.2.3 From a5db27c00da37654ba518b814925d4e9cd05259c Mon Sep 17 00:00:00 2001 From: Sunny Luo Date: Tue, 28 Nov 2017 21:29:25 +0800 Subject: spi: meson-axg: add SPICC driver support Add new compatible string to support SPICC controller which found at Amlogic Meson-AXG SoC. This is aiming at adding a couple of enhanced feature patches. Signed-off-by: Sunny Luo Signed-off-by: Yixun Lan Signed-off-by: Mark Brown --- drivers/spi/spi-meson-spicc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 7f8429635502..5c82910e3480 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -599,6 +599,7 @@ static int meson_spicc_remove(struct platform_device *pdev) static const struct of_device_id meson_spicc_of_match[] = { { .compatible = "amlogic,meson-gx-spicc", }, + { .compatible = "amlogic,meson-axg-spicc", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, meson_spicc_of_match); -- cgit v1.2.3 From f15fc9b12286f64c2b9a8b90f2bcb94915b2c18b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 13 Nov 2017 18:27:39 +0100 Subject: ARM: pxa: move header file out of I2C realm include/linux/i2c is to be deprecated. Move this platform_data to the proper platform_data dir. Signed-off-by: Wolfram Sang Signed-off-by: Robert Jarzmik --- arch/arm/mach-mmp/mmp2.h | 2 +- arch/arm/mach-mmp/pxa168.h | 2 +- arch/arm/mach-mmp/pxa910.h | 2 +- arch/arm/mach-pxa/balloon3.c | 2 +- arch/arm/mach-pxa/cm-x300.c | 2 +- arch/arm/mach-pxa/colibri-evalboard.c | 2 +- arch/arm/mach-pxa/colibri-pxa270-income.c | 2 +- arch/arm/mach-pxa/corgi.c | 2 +- arch/arm/mach-pxa/csb726.c | 2 +- arch/arm/mach-pxa/devices.c | 2 +- arch/arm/mach-pxa/em-x270.c | 2 +- arch/arm/mach-pxa/ezx.c | 2 +- arch/arm/mach-pxa/hx4700.c | 2 +- arch/arm/mach-pxa/littleton.c | 2 +- arch/arm/mach-pxa/magician.c | 2 +- arch/arm/mach-pxa/mainstone.c | 2 +- arch/arm/mach-pxa/mioa701.c | 2 +- arch/arm/mach-pxa/mxm8x10.c | 2 +- arch/arm/mach-pxa/palm27x.c | 2 +- arch/arm/mach-pxa/pcm990-baseboard.c | 2 +- arch/arm/mach-pxa/poodle.c | 2 +- arch/arm/mach-pxa/pxa27x.c | 2 +- arch/arm/mach-pxa/pxa3xx.c | 2 +- arch/arm/mach-pxa/raumfeld.c | 2 +- arch/arm/mach-pxa/saar.c | 2 +- arch/arm/mach-pxa/spitz.c | 2 +- arch/arm/mach-pxa/stargate2.c | 2 +- arch/arm/mach-pxa/tosa.c | 2 +- arch/arm/mach-pxa/trizeps4.c | 2 +- arch/arm/mach-pxa/viper.c | 2 +- arch/arm/mach-pxa/vpac270.c | 2 +- arch/arm/mach-pxa/xcep.c | 2 +- arch/arm/mach-pxa/z2.c | 2 +- arch/arm/mach-pxa/zeus.c | 2 +- arch/arm/mach-pxa/zylonite_pxa300.c | 2 +- drivers/i2c/busses/i2c-pxa-pci.c | 2 +- drivers/i2c/busses/i2c-pxa.c | 2 +- include/linux/i2c/pxa-i2c.h | 74 ------------------------------- include/linux/platform_data/i2c-pxa.h | 74 +++++++++++++++++++++++++++++++ 39 files changed, 111 insertions(+), 111 deletions(-) delete mode 100644 include/linux/i2c/pxa-i2c.h create mode 100644 include/linux/platform_data/i2c-pxa.h (limited to 'drivers') diff --git a/arch/arm/mach-mmp/mmp2.h b/arch/arm/mach-mmp/mmp2.h index a4b82f719de1..adafc4fba8f4 100644 --- a/arch/arm/mach-mmp/mmp2.h +++ b/arch/arm/mach-mmp/mmp2.h @@ -10,7 +10,7 @@ extern void __init mmp2_init_irq(void); extern void mmp2_clear_pmic_int(void); #include -#include +#include #include #include "devices.h" diff --git a/arch/arm/mach-mmp/pxa168.h b/arch/arm/mach-mmp/pxa168.h index b39bff37ff11..0331c58b07a2 100644 --- a/arch/arm/mach-mmp/pxa168.h +++ b/arch/arm/mach-mmp/pxa168.h @@ -11,7 +11,7 @@ extern void pxa168_restart(enum reboot_mode, const char *); extern void pxa168_clear_keypad_wakeup(void); #include -#include +#include #include #include