summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-07-19 15:55:08 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2024-07-19 15:55:08 -0700
commitacc5965b9ff8a1889f5b51466562896d59c6e1b9 (patch)
tree8cd651e6594a9133f216d59a4fa1f18d8c63fb26 /drivers/misc
parent09ea8089abb5d851ce08a9b1a43706e42ef39db2 (diff)
parent5418e6dfc905b3ccc1e01bdad97d948697b20100 (diff)
Merge tag 'char-misc-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char / misc and other driver updates from Greg KH: "Here is the "big" set of char/misc and other driver subsystem changes for 6.11-rc1. Nothing major in here, just loads of new drivers and updates. Included in here are: - IIO api updates and new drivers added - wait_interruptable_timeout() api cleanups for some drivers - MODULE_DESCRIPTION() additions for loads of drivers - parport out-of-bounds fix - interconnect driver updates and additions - mhi driver updates and additions - w1 driver fixes - binder speedups and fixes - eeprom driver updates - coresight driver updates - counter driver update - new misc driver additions - other minor api updates All of these, EXCEPT for the final Kconfig build fix for 32bit systems, have been in linux-next for a while with no reported issues. The Kconfig fixup went in 29 hours ago, so might have missed the latest linux-next, but was acked by everyone involved" * tag 'char-misc-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (330 commits) misc: Kconfig: exclude mrvl-cn10k-dpi compilation for 32-bit systems misc: delete Makefile.rej binder: fix hang of unregistered readers misc: Kconfig: add a new dependency for MARVELL_CN10K_DPI virtio: add missing MODULE_DESCRIPTION() macro agp: uninorth: add missing MODULE_DESCRIPTION() macro spmi: add missing MODULE_DESCRIPTION() macros dev/parport: fix the array out-of-bounds risk samples: configfs: add missing MODULE_DESCRIPTION() macro misc: mrvl-cn10k-dpi: add Octeon CN10K DPI administrative driver misc: keba: Fix missing AUXILIARY_BUS dependency slimbus: Fix struct and documentation alignment in stream.c MAINTAINERS: CC dri-devel list on Qualcomm FastRPC patches misc: fastrpc: use coherent pool for untranslated Compute Banks misc: fastrpc: support complete DMA pool access to the DSP misc: fastrpc: add missing MODULE_DESCRIPTION() macro misc: fastrpc: Add missing dev_err newlines misc: fastrpc: Use memdup_user() nvmem: core: Implement force_ro sysfs attribute nvmem: Use sysfs_emit() for type attribute ...
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig16
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/apds9802als.c2
-rw-r--r--drivers/misc/apds990x.c12
-rw-r--r--drivers/misc/bh1770glc.c14
-rw-r--r--drivers/misc/ds1682.c2
-rw-r--r--drivers/misc/eeprom/Kconfig2
-rw-r--r--drivers/misc/eeprom/digsy_mtc_eeprom.c46
-rw-r--r--drivers/misc/eeprom/ee1004.c131
-rw-r--r--drivers/misc/eeprom/eeprom_93xx46.c178
-rw-r--r--drivers/misc/eeprom/idt_89hpesx.c104
-rw-r--r--drivers/misc/eeprom/max6875.c2
-rw-r--r--drivers/misc/fastrpc.c46
-rw-r--r--drivers/misc/hmc6352.c2
-rw-r--r--drivers/misc/ics932s401.c2
-rw-r--r--drivers/misc/isl29003.c2
-rw-r--r--drivers/misc/isl29020.c2
-rw-r--r--drivers/misc/keba/Kconfig13
-rw-r--r--drivers/misc/keba/Makefile3
-rw-r--r--drivers/misc/keba/cp500.c458
-rw-r--r--drivers/misc/mei/bus-fixup.c8
-rw-r--r--drivers/misc/mrvl_cn10k_dpi.c676
-rw-r--r--drivers/misc/open-dice.c1
-rw-r--r--drivers/misc/ti-st/st_kim.c8
-rw-r--r--drivers/misc/tifm_7xx1.c6
-rw-r--r--drivers/misc/tsl2550.c2
-rw-r--r--drivers/misc/vcpu_stall_detector.c31
27 files changed, 1502 insertions, 269 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index faf983680040..41c3d2821a78 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -585,6 +585,21 @@ config NSM
To compile this driver as a module, choose M here.
The module will be called nsm.
+config MARVELL_CN10K_DPI
+ tristate "Octeon CN10K DPI driver"
+ depends on PCI
+ depends on ARCH_THUNDER || (COMPILE_TEST && 64BIT)
+ help
+ Enables Octeon CN10K DMA packet interface (DPI) driver which
+ intializes DPI hardware's physical function (PF) device's
+ global configuration and its virtual function (VFs) resource
+ configuration to enable DMA transfers. DPI PF device does not
+ have any data movement functionality, it only serves VF's
+ resource configuration requests.
+
+ To compile this driver as a module, choose M here: the module
+ will be called mrvl_cn10k_dpi.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
@@ -602,4 +617,5 @@ source "drivers/misc/cardreader/Kconfig"
source "drivers/misc/uacce/Kconfig"
source "drivers/misc/pvpanic/Kconfig"
source "drivers/misc/mchp_pci1xxxx/Kconfig"
+source "drivers/misc/keba/Kconfig"
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 153a3f4837e8..c2f990862d2b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -69,3 +69,5 @@ obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o
obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o
obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o
obj-$(CONFIG_NSM) += nsm.o
+obj-$(CONFIG_MARVELL_CN10K_DPI) += mrvl_cn10k_dpi.o
+obj-y += keba/
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
index 693f0e539f37..6db4db975b9a 100644
--- a/drivers/misc/apds9802als.c
+++ b/drivers/misc/apds9802als.c
@@ -285,7 +285,7 @@ static UNIVERSAL_DEV_PM_OPS(apds9802als_pm_ops, apds9802als_suspend,
#endif /* CONFIG_PM */
static const struct i2c_device_id apds9802als_id[] = {
- { DRIVER_NAME, 0 },
+ { DRIVER_NAME },
{ }
};
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index 92b92be91d60..6d4edd69db12 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -625,15 +625,15 @@ static ssize_t apds990x_lux_show(struct device *dev,
struct apds990x_chip *chip = dev_get_drvdata(dev);
ssize_t ret;
u32 result;
- long timeout;
+ long time_left;
if (pm_runtime_suspended(dev))
return -EIO;
- timeout = wait_event_interruptible_timeout(chip->wait,
- !chip->lux_wait_fresh_res,
- msecs_to_jiffies(APDS_TIMEOUT));
- if (!timeout)
+ time_left = wait_event_interruptible_timeout(chip->wait,
+ !chip->lux_wait_fresh_res,
+ msecs_to_jiffies(APDS_TIMEOUT));
+ if (!time_left)
return -EIO;
mutex_lock(&chip->mutex);
@@ -1253,7 +1253,7 @@ static int apds990x_runtime_resume(struct device *dev)
#endif
static const struct i2c_device_id apds990x_id[] = {
- {"apds990x", 0 },
+ { "apds990x" },
{}
};
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
index 1629b62fd052..0c052b05ab6a 100644
--- a/drivers/misc/bh1770glc.c
+++ b/drivers/misc/bh1770glc.c
@@ -680,15 +680,15 @@ static ssize_t bh1770_lux_result_show(struct device *dev,
{
struct bh1770_chip *chip = dev_get_drvdata(dev);
ssize_t ret;
- long timeout;
+ long time_left;
if (pm_runtime_suspended(dev))
return -EIO; /* Chip is not enabled at all */
- timeout = wait_event_interruptible_timeout(chip->wait,
- !chip->lux_wait_result,
- msecs_to_jiffies(BH1770_TIMEOUT));
- if (!timeout)
+ time_left = wait_event_interruptible_timeout(chip->wait,
+ !chip->lux_wait_result,
+ msecs_to_jiffies(BH1770_TIMEOUT));
+ if (!time_left)
return -EIO;
mutex_lock(&chip->mutex);
@@ -1361,8 +1361,8 @@ static int bh1770_runtime_resume(struct device *dev)
#endif
static const struct i2c_device_id bh1770_id[] = {
- {"bh1770glc", 0 },
- {"sfh7770", 0 },
+ { "bh1770glc" },
+ { "sfh7770" },
{}
};
diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c
index 5f8dcd0e3848..4175df7ef011 100644
--- a/drivers/misc/ds1682.c
+++ b/drivers/misc/ds1682.c
@@ -271,7 +271,7 @@ static void ds1682_remove(struct i2c_client *client)
}
static const struct i2c_device_id ds1682_id[] = {
- { "ds1682", 0 },
+ { "ds1682" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1682_id);
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 4e61ac18cc96..9df12399bda3 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -109,6 +109,8 @@ config EEPROM_IDT_89HPESX
config EEPROM_EE1004
tristate "SPD EEPROMs on DDR4 memory modules"
depends on I2C && SYSFS
+ select NVMEM
+ select NVMEM_SYSFS
help
Enable this driver to get read support to SPD EEPROMs following
the JEDEC EE1004 standard. These are typically found on DDR4
diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c
index f1f766b70965..88888485e6f8 100644
--- a/drivers/misc/eeprom/digsy_mtc_eeprom.c
+++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c
@@ -14,13 +14,12 @@
* and delete this driver.
*/
-#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h>
-#include <linux/eeprom_93xx46.h>
#define GPIO_EEPROM_CLK 216
#define GPIO_EEPROM_CS 210
@@ -29,22 +28,13 @@
#define GPIO_EEPROM_OE 255
#define EE_SPI_BUS_NUM 1
-static void digsy_mtc_op_prepare(void *p)
-{
- /* enable */
- gpio_set_value(GPIO_EEPROM_OE, 0);
-}
-
-static void digsy_mtc_op_finish(void *p)
-{
- /* disable */
- gpio_set_value(GPIO_EEPROM_OE, 1);
-}
+static const struct property_entry digsy_mtc_spi_properties[] = {
+ PROPERTY_ENTRY_U32("data-size", 8),
+ { }
+};
-struct eeprom_93xx46_platform_data digsy_mtc_eeprom_data = {
- .flags = EE_ADDR8,
- .prepare = digsy_mtc_op_prepare,
- .finish = digsy_mtc_op_finish,
+static const struct software_node digsy_mtc_spi_node = {
+ .properties = digsy_mtc_spi_properties,
};
static struct spi_gpio_platform_data eeprom_spi_gpio_data = {
@@ -70,18 +60,19 @@ static struct gpiod_lookup_table eeprom_spi_gpiod_table = {
"miso", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_CS,
"cs", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_OE,
+ "select", GPIO_ACTIVE_LOW),
{ },
},
};
static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = {
{
- .modalias = "93xx46",
+ .modalias = "eeprom-93xx46",
.max_speed_hz = 1000000,
.bus_num = EE_SPI_BUS_NUM,
.chip_select = 0,
.mode = SPI_MODE_0,
- .platform_data = &digsy_mtc_eeprom_data,
},
};
@@ -89,15 +80,18 @@ static int __init digsy_mtc_eeprom_devices_init(void)
{
int ret;
- ret = gpio_request_one(GPIO_EEPROM_OE, GPIOF_OUT_INIT_HIGH,
- "93xx46 EEPROMs OE");
- if (ret) {
- pr_err("can't request gpio %d\n", GPIO_EEPROM_OE);
- return ret;
- }
gpiod_add_lookup_table(&eeprom_spi_gpiod_table);
spi_register_board_info(digsy_mtc_eeprom_info,
ARRAY_SIZE(digsy_mtc_eeprom_info));
- return platform_device_register(&digsy_mtc_eeprom);
+
+ ret = device_add_software_node(&digsy_mtc_eeprom.dev, &digsy_mtc_spi_node);
+ if (ret)
+ return ret;
+
+ ret = platform_device_register(&digsy_mtc_eeprom);
+ if (ret)
+ device_remove_software_node(&digsy_mtc_eeprom.dev);
+
+ return ret;
}
device_initcall(digsy_mtc_eeprom_devices_init);
diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c
index 21feebc3044c..d4aeeb2b2169 100644
--- a/drivers/misc/eeprom/ee1004.c
+++ b/drivers/misc/eeprom/ee1004.c
@@ -9,12 +9,14 @@
* Copyright (C) 2008 Wolfram Sang, Pengutronix
*/
+#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/nvmem-provider.h>
/*
* DDR4 memory modules use special EEPROMs following the Jedec EE1004
@@ -52,7 +54,7 @@ static struct ee1004_bus_data {
} ee1004_bus_data[EE1004_MAX_BUSSES];
static const struct i2c_device_id ee1004_ids[] = {
- { "ee1004", 0 },
+ { "ee1004" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ee1004_ids);
@@ -144,13 +146,17 @@ static ssize_t ee1004_eeprom_read(struct i2c_client *client, char *buf,
return i2c_smbus_read_i2c_block_data_or_emulated(client, offset, count, buf);
}
-static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
+static int ee1004_read(void *priv, unsigned int off, void *val, size_t count)
{
- struct i2c_client *client = kobj_to_i2c_client(kobj);
- size_t requested = count;
- int ret = 0;
+ struct i2c_client *client = priv;
+ char *buf = val;
+ int ret;
+
+ if (unlikely(!count))
+ return count;
+
+ if (off + count > EE1004_EEPROM_SIZE)
+ return -EINVAL;
/*
* Read data from chip, protecting against concurrent access to
@@ -160,42 +166,52 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
while (count) {
ret = ee1004_eeprom_read(client, buf, off, count);
- if (ret < 0)
- goto out;
+ if (ret < 0) {
+ mutex_unlock(&ee1004_bus_lock);
+ return ret;
+ }
buf += ret;
off += ret;
count -= ret;
}
-out:
+
mutex_unlock(&ee1004_bus_lock);
- return ret < 0 ? ret : requested;
+ return 0;
}
-static BIN_ATTR_RO(eeprom, EE1004_EEPROM_SIZE);
-
-static struct bin_attribute *ee1004_attrs[] = {
- &bin_attr_eeprom,
- NULL
-};
-
-BIN_ATTRIBUTE_GROUPS(ee1004);
-
static void ee1004_probe_temp_sensor(struct i2c_client *client)
{
struct i2c_board_info info = { .type = "jc42" };
- u8 byte14;
+ unsigned short addr = 0x18 | (client->addr & 7);
+ unsigned short addr_list[] = { addr, I2C_CLIENT_END };
+ u8 data[2];
int ret;
/* byte 14, bit 7 is set if temp sensor is present */
- ret = ee1004_eeprom_read(client, &byte14, 14, 1);
- if (ret != 1 || !(byte14 & BIT(7)))
+ ret = ee1004_eeprom_read(client, data, 14, 1);
+ if (ret != 1)
return;
- info.addr = 0x18 | (client->addr & 7);
-
- i2c_new_client_device(client->adapter, &info);
+ if (!(data[0] & BIT(7))) {
+ /*
+ * If the SPD data suggests that there is no temperature
+ * sensor, it may still be there for SPD revision 1.0.
+ * See SPD Annex L, Revision 1 and 2, for details.
+ * Check DIMM type and SPD revision; if it is a DDR4
+ * with SPD revision 1.0, check the thermal sensor address
+ * and instantiate the jc42 driver if a chip is found at
+ * that address.
+ * It is not necessary to check if there is a chip at the
+ * temperature sensor address since i2c_new_scanned_device()
+ * will do that and return silently if no chip is found.
+ */
+ ret = ee1004_eeprom_read(client, data, 1, 2);
+ if (ret != 2 || data[0] != 0x10 || data[1] != 0x0c)
+ return;
+ }
+ i2c_new_scanned_device(client->adapter, &info, addr_list, NULL);
}
static void ee1004_cleanup(int idx, struct ee1004_bus_data *bd)
@@ -207,9 +223,36 @@ static void ee1004_cleanup(int idx, struct ee1004_bus_data *bd)
}
}
+static void ee1004_cleanup_bus_data(void *data)
+{
+ struct ee1004_bus_data *bd = data;
+
+ /* Remove page select clients if this is the last device */
+ mutex_lock(&ee1004_bus_lock);
+ ee1004_cleanup(EE1004_NUM_PAGES, bd);
+ mutex_unlock(&ee1004_bus_lock);
+}
+
static int ee1004_probe(struct i2c_client *client)
{
+ struct nvmem_config config = {
+ .dev = &client->dev,
+ .name = dev_name(&client->dev),
+ .id = NVMEM_DEVID_NONE,
+ .owner = THIS_MODULE,
+ .type = NVMEM_TYPE_EEPROM,
+ .read_only = true,
+ .root_only = false,
+ .reg_read = ee1004_read,
+ .size = EE1004_EEPROM_SIZE,
+ .word_size = 1,
+ .stride = 1,
+ .priv = client,
+ .compat = true,
+ .base_dev = &client->dev,
+ };
struct ee1004_bus_data *bd;
+ struct nvmem_device *ndev;
int err, cnr = 0;
/* Make sure we can operate on this adapter */
@@ -228,6 +271,10 @@ static int ee1004_probe(struct i2c_client *client)
"Only %d busses supported", EE1004_MAX_BUSSES);
}
+ err = devm_add_action_or_reset(&client->dev, ee1004_cleanup_bus_data, bd);
+ if (err < 0)
+ return err;
+
i2c_set_clientdata(client, bd);
if (++bd->dev_count == 1) {
@@ -237,16 +284,18 @@ static int ee1004_probe(struct i2c_client *client)
cl = i2c_new_dummy_device(client->adapter, EE1004_ADDR_SET_PAGE + cnr);
if (IS_ERR(cl)) {
- err = PTR_ERR(cl);
- goto err_clients;
+ mutex_unlock(&ee1004_bus_lock);
+ return PTR_ERR(cl);
}
bd->set_page[cnr] = cl;
}
/* Remember current page to avoid unneeded page select */
err = ee1004_get_current_page(bd);
- if (err < 0)
- goto err_clients;
+ if (err < 0) {
+ mutex_unlock(&ee1004_bus_lock);
+ return err;
+ }
dev_dbg(&client->dev, "Currently selected page: %d\n", err);
bd->current_page = err;
}
@@ -255,27 +304,15 @@ static int ee1004_probe(struct i2c_client *client)
mutex_unlock(&ee1004_bus_lock);
+ ndev = devm_nvmem_register(&client->dev, &config);
+ if (IS_ERR(ndev))
+ return PTR_ERR(ndev);
+
dev_info(&client->dev,
"%u byte EE1004-compliant SPD EEPROM, read-only\n",
EE1004_EEPROM_SIZE);
return 0;
-
- err_clients:
- ee1004_cleanup(cnr, bd);
- mutex_unlock(&ee1004_bus_lock);
-
- return err;
-}
-
-static void ee1004_remove(struct i2c_client *client)
-{
- struct ee1004_bus_data *bd = i2c_get_clientdata(client);
-
- /* Remove page select clients if this is the last device */
- mutex_lock(&ee1004_bus_lock);
- ee1004_cleanup(EE1004_NUM_PAGES, bd);
- mutex_unlock(&ee1004_bus_lock);
}
/*-------------------------------------------------------------------------*/
@@ -283,10 +320,8 @@ static void ee1004_remove(struct i2c_client *client)
static struct i2c_driver ee1004_driver = {
.driver = {
.name = "ee1004",
- .dev_groups = ee1004_groups,
},
.probe = ee1004_probe,
- .remove = ee1004_remove,
.id_table = ee1004_ids,
};
module_i2c_driver(ee1004_driver);
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index 45c8ae0db8f9..e2221be88445 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -5,19 +5,42 @@
* (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
*/
+#include <linux/array_size.h>
+#include <linux/bits.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
-#include <linux/kernel.h>
+#include <linux/kstrtox.h>
#include <linux/log2.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
+#include <linux/string_choices.h>
+
#include <linux/nvmem-provider.h>
-#include <linux/eeprom_93xx46.h>
+
+struct eeprom_93xx46_platform_data {
+ unsigned char flags;
+#define EE_ADDR8 0x01 /* 8 bit addr. cfg */
+#define EE_ADDR16 0x02 /* 16 bit addr. cfg */
+#define EE_READONLY 0x08 /* forbid writing */
+#define EE_SIZE1K 0x10 /* 1 kb of data, that is a 93xx46 */
+#define EE_SIZE2K 0x20 /* 2 kb of data, that is a 93xx56 */
+#define EE_SIZE4K 0x40 /* 4 kb of data, that is a 93xx66 */
+
+ unsigned int quirks;
+/* Single word read transfers only; no sequential read. */
+#define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0)
+/* Instructions such as EWEN are (addrlen + 2) in length. */
+#define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1)
+/* Add extra cycle after address during a read */
+#define EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE BIT(2)
+
+ struct gpio_desc *select;
+};
#define OP_START 0x4
#define OP_WRITE (OP_START | 0x1)
@@ -96,15 +119,14 @@ static int eeprom_93xx46_read(void *priv, unsigned int off,
mutex_lock(&edev->lock);
- if (edev->pdata->prepare)
- edev->pdata->prepare(edev);
+ gpiod_set_value_cansleep(edev->pdata->select, 1);
/* The opcode in front of the address is three bits. */
bits = edev->addrlen + 3;
while (count) {
struct spi_message m;
- struct spi_transfer t[2] = { { 0 } };
+ struct spi_transfer t[2] = {};
u16 cmd_addr = OP_READ << edev->addrlen;
size_t nbytes = count;
@@ -126,25 +148,23 @@ static int eeprom_93xx46_read(void *priv, unsigned int off,
bits += 1;
}
- spi_message_init(&m);
-
t[0].tx_buf = (char *)&cmd_addr;
t[0].len = 2;
t[0].bits_per_word = bits;
- spi_message_add_tail(&t[0], &m);
t[1].rx_buf = buf;
t[1].len = count;
t[1].bits_per_word = 8;
- spi_message_add_tail(&t[1], &m);
+
+ spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t));
err = spi_sync(edev->spi, &m);
/* have to wait at least Tcsl ns */
ndelay(250);
if (err) {
- dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n",
- nbytes, (int)off, err);
+ dev_err(&edev->spi->dev, "read %zu bytes at %u: err. %d\n",
+ nbytes, off, err);
break;
}
@@ -153,8 +173,7 @@ static int eeprom_93xx46_read(void *priv, unsigned int off,
count -= nbytes;
}
- if (edev->pdata->finish)
- edev->pdata->finish(edev);
+ gpiod_set_value_cansleep(edev->pdata->select, 0);
mutex_unlock(&edev->lock);
@@ -164,7 +183,7 @@ static int eeprom_93xx46_read(void *priv, unsigned int off,
static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
{
struct spi_message m;
- struct spi_transfer t;
+ struct spi_transfer t = {};
int bits, ret;
u16 cmd_addr;
@@ -182,31 +201,27 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
bits += 2;
}
- dev_dbg(&edev->spi->dev, "ew%s cmd 0x%04x, %d bits\n",
- is_on ? "en" : "ds", cmd_addr, bits);
-
- spi_message_init(&m);
- memset(&t, 0, sizeof(t));
+ dev_dbg(&edev->spi->dev, "ew %s cmd 0x%04x, %d bits\n",
+ str_enable_disable(is_on), cmd_addr, bits);
t.tx_buf = &cmd_addr;
t.len = 2;
t.bits_per_word = bits;
- spi_message_add_tail(&t, &m);
+
+ spi_message_init_with_transfers(&m, &t, 1);
mutex_lock(&edev->lock);
- if (edev->pdata->prepare)
- edev->pdata->prepare(edev);
+ gpiod_set_value_cansleep(edev->pdata->select, 1);
ret = spi_sync(edev->spi, &m);
/* have to wait at least Tcsl ns */
ndelay(250);
if (ret)
- dev_err(&edev->spi->dev, "erase/write %sable error %d\n",
- is_on ? "en" : "dis", ret);
+ dev_err(&edev->spi->dev, "erase/write %s error %d\n",
+ str_enable_disable(is_on), ret);
- if (edev->pdata->finish)
- edev->pdata->finish(edev);
+ gpiod_set_value_cansleep(edev->pdata->select, 0);
mutex_unlock(&edev->lock);
return ret;
@@ -217,7 +232,7 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
const char *buf, unsigned off)
{
struct spi_message m;
- struct spi_transfer t[2];
+ struct spi_transfer t[2] = {};
int bits, data_len, ret;
u16 cmd_addr;
@@ -239,18 +254,15 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr);
- spi_message_init(&m);
- memset(t, 0, sizeof(t));
-
t[0].tx_buf = (char *)&cmd_addr;
t[0].len = 2;
t[0].bits_per_word = bits;
- spi_message_add_tail(&t[0], &m);
t[1].tx_buf = buf;
t[1].len = data_len;
t[1].bits_per_word = 8;
- spi_message_add_tail(&t[1], &m);
+
+ spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t));
ret = spi_sync(edev->spi, &m);
/* have to wait program cycle time Twc ms */
@@ -263,7 +275,8 @@ static int eeprom_93xx46_write(void *priv, unsigned int off,
{
struct eeprom_93xx46_dev *edev = priv;
char *buf = val;
- int i, ret, step = 1;
+ int ret, step = 1;
+ unsigned int i;
if (unlikely(off >= edev->size))
return -EFBIG;
@@ -285,20 +298,17 @@ static int eeprom_93xx46_write(void *priv, unsigned int off,
mutex_lock(&edev->lock);
- if (edev->pdata->prepare)
- edev->pdata->prepare(edev);
+ gpiod_set_value_cansleep(edev->pdata->select, 1);
for (i = 0; i < count; i += step) {
ret = eeprom_93xx46_write_word(edev, &buf[i], off + i);
if (ret) {
- dev_err(&edev->spi->dev, "write failed at %d: %d\n",
- (int)off + i, ret);
+ dev_err(&edev->spi->dev, "write failed at %u: %d\n", off + i, ret);
break;
}
}
- if (edev->pdata->finish)
- edev->pdata->finish(edev);
+ gpiod_set_value_cansleep(edev->pdata->select, 0);
mutex_unlock(&edev->lock);
@@ -309,9 +319,8 @@ static int eeprom_93xx46_write(void *priv, unsigned int off,
static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
{
- struct eeprom_93xx46_platform_data *pd = edev->pdata;
struct spi_message m;
- struct spi_transfer t;
+ struct spi_transfer t = {};
int bits, ret;
u16 cmd_addr;
@@ -331,18 +340,15 @@ static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
dev_dbg(&edev->spi->dev, "eral cmd 0x%04x, %d bits\n", cmd_addr, bits);
- spi_message_init(&m);
- memset(&t, 0, sizeof(t));
-
t.tx_buf = &cmd_addr;
t.len = 2;
t.bits_per_word = bits;
- spi_message_add_tail(&t, &m);
+
+ spi_message_init_with_transfers(&m, &t, 1);
mutex_lock(&edev->lock);
- if (edev->pdata->prepare)
- edev->pdata->prepare(edev);
+ gpiod_set_value_cansleep(edev->pdata->select, 1);
ret = spi_sync(edev->spi, &m);
if (ret)
@@ -350,21 +356,23 @@ static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
/* have to wait erase cycle time Tec ms */
mdelay(6);
- if (pd->finish)
- pd->finish(edev);
+ gpiod_set_value_cansleep(edev->pdata->select, 0);
mutex_unlock(&edev->lock);
return ret;
}
-static ssize_t eeprom_93xx46_store_erase(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t erase_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev);
- int erase = 0, ret;
+ bool erase;
+ int ret;
+
+ ret = kstrtobool(buf, &erase);
+ if (ret)
+ return ret;
- sscanf(buf, "%d", &erase);
if (erase) {
ret = eeprom_93xx46_ew(edev, 1);
if (ret)
@@ -378,21 +386,7 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev,
}
return count;
}
-static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
-
-static void select_assert(void *context)
-{
- struct eeprom_93xx46_dev *edev = context;
-
- gpiod_set_value_cansleep(edev->pdata->select, 1);
-}
-
-static void select_deassert(void *context)
-{
- struct eeprom_93xx46_dev *edev = context;
-
- gpiod_set_value_cansleep(edev->pdata->select, 0);
-}
+static DEVICE_ATTR_WO(erase);
static const struct of_device_id eeprom_93xx46_of_table[] = {
{ .compatible = "eeprom-93xx46", .data = &at93c46_data, },
@@ -422,22 +416,20 @@ static const struct spi_device_id eeprom_93xx46_spi_ids[] = {
};
MODULE_DEVICE_TABLE(spi, eeprom_93xx46_spi_ids);
-static int eeprom_93xx46_probe_dt(struct spi_device *spi)
+static int eeprom_93xx46_probe_fw(struct device *dev)
{
- const struct of_device_id *of_id =
- of_match_device(eeprom_93xx46_of_table, &spi->dev);
- struct device_node *np = spi->dev.of_node;
+ const struct eeprom_93xx46_devtype_data *data;
struct eeprom_93xx46_platform_data *pd;
u32 tmp;
int ret;
- pd = devm_kzalloc(&spi->dev, sizeof(*pd), GFP_KERNEL);
+ pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd)
return -ENOMEM;
- ret = of_property_read_u32(np, "data-size", &tmp);
+ ret = device_property_read_u32(dev, "data-size", &tmp);
if (ret < 0) {
- dev_err(&spi->dev, "data-size property not found\n");
+ dev_err(dev, "data-size property not found\n");
return ret;
}
@@ -446,30 +438,25 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi)
} else if (tmp == 16) {
pd->flags |= EE_ADDR16;
} else {
- dev_err(&spi->dev, "invalid data-size (%d)\n", tmp);
+ dev_err(dev, "invalid data-size (%d)\n", tmp);
return -EINVAL;
}
- if (of_property_read_bool(np, "read-only"))
+ if (device_property_read_bool(dev, "read-only"))
pd->flags |= EE_READONLY;
- pd->select = devm_gpiod_get_optional(&spi->dev, "select",
- GPIOD_OUT_LOW);
+ pd->select = devm_gpiod_get_optional(dev, "select", GPIOD_OUT_LOW);
if (IS_ERR(pd->select))
return PTR_ERR(pd->select);
+ gpiod_set_consumer_name(pd->select, "93xx46 EEPROMs OE");
- pd->prepare = select_assert;
- pd->finish = select_deassert;
- gpiod_direction_output(pd->select, 0);
-
- if (of_id->data) {
- const struct eeprom_93xx46_devtype_data *data = of_id->data;
-
+ data = spi_get_device_match_data(to_spi_device(dev));
+ if (data) {
pd->quirks = data->quirks;
pd->flags |= data->flags;
}
- spi->dev.platform_data = pd;
+ dev->platform_data = pd;
return 0;
}
@@ -478,13 +465,12 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
{
struct eeprom_93xx46_platform_data *pd;
struct eeprom_93xx46_dev *edev;
+ struct device *dev = &spi->dev;
int err;
- if (spi->dev.of_node) {
- err = eeprom_93xx46_probe_dt(spi);
- if (err < 0)
- return err;
- }
+ err = eeprom_93xx46_probe_fw(dev);
+ if (err < 0)
+ return err;
pd = spi->dev.platform_data;
if (!pd) {
@@ -565,7 +551,7 @@ static void eeprom_93xx46_remove(struct spi_device *spi)
static struct spi_driver eeprom_93xx46_driver = {
.driver = {
.name = "93xx46",
- .of_match_table = of_match_ptr(eeprom_93xx46_of_table),
+ .of_match_table = eeprom_93xx46_of_table,
},
.probe = eeprom_93xx46_probe,
.remove = eeprom_93xx46_remove,
diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c
index 327afb866b21..43421fe37d33 100644
--- a/drivers/misc/eeprom/idt_89hpesx.c
+++ b/drivers/misc/eeprom/idt_89hpesx.c
@@ -1426,58 +1426,58 @@ MODULE_DEVICE_TABLE(i2c, ee_ids);
* idt_ids - supported IDT 89HPESx devices
*/
static const struct i2c_device_id idt_ids[] = {
- { "89hpes8nt2", 0 },
- { "89hpes12nt3", 0 },
-
- { "89hpes24nt6ag2", 0 },
- { "89hpes32nt8ag2", 0 },
- { "89hpes32nt8bg2", 0 },
- { "89hpes12nt12g2", 0 },
- { "89hpes16nt16g2", 0 },
- { "89hpes24nt24g2", 0 },
- { "89hpes32nt24ag2", 0 },
- { "89hpes32nt24bg2", 0 },
-
- { "89hpes12n3", 0 },
- { "89hpes12n3a", 0 },
- { "89hpes24n3", 0 },
- { "89hpes24n3a", 0 },
-
- { "89hpes32h8", 0 },
- { "89hpes32h8g2", 0 },
- { "89hpes48h12", 0 },
- { "89hpes48h12g2", 0 },
- { "89hpes48h12ag2", 0 },
- { "89hpes16h16", 0 },
- { "89hpes22h16", 0 },
- { "89hpes22h16g2", 0 },
- { "89hpes34h16", 0 },
- { "89hpes34h16g2", 0 },
- { "89hpes64h16", 0 },
- { "89hpes64h16g2", 0 },
- { "89hpes64h16ag2", 0 },
-
- /* { "89hpes3t3", 0 }, // No SMBus-slave iface */
- { "89hpes12t3g2", 0 },
- { "89hpes24t3g2", 0 },
- /* { "89hpes4t4", 0 }, // No SMBus-slave iface */
- { "89hpes16t4", 0 },
- { "89hpes4t4g2", 0 },
- { "89hpes10t4g2", 0 },
- { "89hpes16t4g2", 0 },
- { "89hpes16t4ag2", 0 },
- { "89hpes5t5", 0 },
- { "89hpes6t5", 0 },
- { "89hpes8t5", 0 },
- { "89hpes8t5a", 0 },
- { "89hpes24t6", 0 },
- { "89hpes6t6g2", 0 },
- { "89hpes24t6g2", 0 },
- { "89hpes16t7", 0 },
- { "89hpes32t8", 0 },
- { "89hpes32t8g2", 0 },
- { "89hpes48t12", 0 },
- { "89hpes48t12g2", 0 },
+ { "89hpes8nt2" },
+ { "89hpes12nt3" },
+
+ { "89hpes24nt6ag2" },
+ { "89hpes32nt8ag2" },
+ { "89hpes32nt8bg2" },
+ { "89hpes12nt12g2" },
+ { "89hpes16nt16g2" },
+ { "89hpes24nt24g2" },
+ { "89hpes32nt24ag2" },
+ { "89hpes32nt24bg2" },
+
+ { "89hpes12n3" },
+ { "89hpes12n3a" },
+ { "89hpes24n3" },
+ { "89hpes24n3a" },
+
+ { "89hpes32h8" },
+ { "89hpes32h8g2" },
+ { "89hpes48h12" },
+ { "89hpes48h12g2" },
+ { "89hpes48h12ag2" },
+ { "89hpes16h16" },
+ { "89hpes22h16" },
+ { "89hpes22h16g2" },
+ { "89hpes34h16" },
+ { "89hpes34h16g2" },
+ { "89hpes64h16" },
+ { "89hpes64h16g2" },
+ { "89hpes64h16ag2" },
+
+ /* { "89hpes3t3" }, // No SMBus-slave iface */
+ { "89hpes12t3g2" },
+ { "89hpes24t3g2" },
+ /* { "89hpes4t4" }, // No SMBus-slave iface */
+ { "89hpes16t4" },
+ { "89hpes4t4g2" },
+ { "89hpes10t4g2" },
+ { "89hpes16t4g2" },
+ { "89hpes16t4ag2" },
+ { "89hpes5t5" },
+ { "89hpes6t5" },
+ { "89hpes8t5" },
+ { "89hpes8t5a" },
+ { "89hpes24t6" },
+ { "89hpes6t6g2" },
+ { "89hpes24t6g2" },
+ { "89hpes16t7" },
+ { "89hpes32t8" },
+ { "89hpes32t8g2" },
+ { "89hpes48t12" },
+ { "89hpes48t12g2" },
{ /* END OF LIST */ }
};
MODULE_DEVICE_TABLE(i2c, idt_ids);
diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c
index cb6b1efeafe0..6fab2ffa736b 100644
--- a/drivers/misc/eeprom/max6875.c
+++ b/drivers/misc/eeprom/max6875.c
@@ -183,7 +183,7 @@ static void max6875_remove(struct i2c_client *client)
}
static const struct i2c_device_id max6875_id[] = {
- { "max6875", 0 },
+ { "max6875" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max6875_id);
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index a7a2bcedb37e..5204fda51da3 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -325,7 +325,7 @@ static void fastrpc_free_map(struct kref *ref)
err = qcom_scm_assign_mem(map->phys, map->size,
&src_perms, &perm, 1);
if (err) {
- dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
+ dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n",
map->phys, map->size, err);
return;
}
@@ -816,7 +816,7 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
map->attr = attr;
err = qcom_scm_assign_mem(map->phys, (u64)map->size, &src_perms, dst_perms, 2);
if (err) {
- dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d",
+ dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n",
map->phys, map->size, err);
goto map_err;
}
@@ -953,7 +953,10 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx)
ctx->msg_sz = pkt_size;
- err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf);
+ if (ctx->fl->sctx->sid)
+ err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf);
+ else
+ err = fastrpc_remote_heap_alloc(ctx->fl, dev, pkt_size, &ctx->buf);
if (err)
return err;
@@ -1222,7 +1225,7 @@ static bool is_session_rejected(struct fastrpc_user *fl, bool unsigned_pd_reques
* that does not support unsigned PD offload
*/
if (!fl->cctx->unsigned_support || !unsigned_pd_request) {
- dev_err(&fl->cctx->rpdev->dev, "Error: Untrusted application trying to offload to signed PD");
+ dev_err(&fl->cctx->rpdev->dev, "Error: Untrusted application trying to offload to signed PD\n");
return true;
}
}
@@ -1260,17 +1263,12 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
goto err;
}
- name = kzalloc(init.namelen, GFP_KERNEL);
- if (!name) {
- err = -ENOMEM;
+ name = memdup_user(u64_to_user_ptr(init.name), init.namelen);
+ if (IS_ERR(name)) {
+ err = PTR_ERR(name);
goto err;
}
- if (copy_from_user(name, (void __user *)(uintptr_t)init.name, init.namelen)) {
- err = -EFAULT;
- goto err_name;
- }
-
if (!fl->cctx->remote_heap) {
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen,
&fl->cctx->remote_heap);
@@ -1286,7 +1284,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
&src_perms,
fl->cctx->vmperms, fl->cctx->vmcount);
if (err) {
- dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d",
+ dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n",
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
goto err_map;
}
@@ -1340,7 +1338,7 @@ err_invoke:
(u64)fl->cctx->remote_heap->size,
&src_perms, &dst_perms, 1);
if (err)
- dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
+ dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n",
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
}
err_map:
@@ -2278,6 +2276,8 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
int i, err, domain_id = -1, vmcount;
const char *domain;
bool secure_dsp;
+ struct device_node *rmem_node;
+ struct reserved_mem *rmem;
unsigned int vmids[FASTRPC_MAX_VMIDS];
err = of_property_read_string(rdev->of_node, "label", &domain);
@@ -2320,6 +2320,23 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
}
}
+ rmem_node = of_parse_phandle(rdev->of_node, "memory-region", 0);
+ if (domain_id == SDSP_DOMAIN_ID && rmem_node) {
+ u64 src_perms;
+
+ rmem = of_reserved_mem_lookup(rmem_node);
+ if (!rmem) {
+ err = -EINVAL;
+ goto fdev_error;
+ }
+
+ src_perms = BIT(QCOM_SCM_VMID_HLOS);
+
+ qcom_scm_assign_mem(rmem->base, rmem->size, &src_perms,
+ data->vmperms, data->vmcount);
+
+ }
+
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
data->secure = secure_dsp;
@@ -2501,5 +2518,6 @@ static void fastrpc_exit(void)
}
module_exit(fastrpc_exit);
+MODULE_DESCRIPTION("Qualcomm FastRPC");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(DMA_BUF);
diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c
index 759eaeb64307..ff92c6edff6b 100644
--- a/drivers/misc/hmc6352.c
+++ b/drivers/misc/hmc6352.c
@@ -121,7 +121,7 @@ static void hmc6352_remove(struct i2c_client *client)
}
static const struct i2c_device_id hmc6352_id[] = {
- { "hmc6352", 0 },
+ { "hmc6352" },
{ }
};
diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c
index ee6296b98078..4cdb1087838f 100644
--- a/drivers/misc/ics932s401.c
+++ b/drivers/misc/ics932s401.c
@@ -95,7 +95,7 @@ static int ics932s401_detect(struct i2c_client *client,
static void ics932s401_remove(struct i2c_client *client);
static const struct i2c_device_id ics932s401_id[] = {
- { "ics932s401", 0 },
+ { "ics932s401" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ics932s401_id);
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
index ebf0635aee64..9f26db467a81 100644
--- a/drivers/misc/isl29003.c
+++ b/drivers/misc/isl29003.c
@@ -449,7 +449,7 @@ static SIMPLE_DEV_PM_OPS(isl29003_pm_ops, isl29003_suspend, isl29003_resume);
#endif /* CONFIG_PM_SLEEP */
static const struct i2c_device_id isl29003_id[] = {
- { "isl29003", 0 },
+ { "isl29003" },
{}
};
MODULE_DEVICE_TABLE(i2c, isl29003_id);
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c
index c5976fa8c825..1643ba2ff964 100644
--- a/drivers/misc/isl29020.c
+++ b/drivers/misc/isl29020.c
@@ -177,7 +177,7 @@ static void isl29020_remove(struct i2c_client *client)
}
static const struct i2c_device_id isl29020_id[] = {
- { "isl29020", 0 },
+ { "isl29020" },
{ }
};
diff --git a/drivers/misc/keba/Kconfig b/drivers/misc/keba/Kconfig
new file mode 100644
index 000000000000..5fbcbc2252ac
--- /dev/null
+++ b/drivers/misc/keba/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+config KEBA_CP500
+ tristate "KEBA CP500 system FPGA support"
+ depends on PCI
+ select AUXILIARY_BUS
+ help
+ This driver supports the KEBA CP500 system FPGA, which is used in
+ KEBA CP500 devices. It registers all sub devices present on the CP500
+ system FPGA as separate devices. A driver is needed for each sub
+ device.
+
+ This driver can also be built as a module. If so, the module will be
+ called cp500.
diff --git a/drivers/misc/keba/Makefile b/drivers/misc/keba/Makefile
new file mode 100644
index 000000000000..0a8b846cda7d
--- /dev/null
+++ b/drivers/misc/keba/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_KEBA_CP500) += cp500.o
diff --git a/drivers/misc/keba/cp500.c b/drivers/misc/keba/cp500.c
new file mode 100644
index 000000000000..9ba46f0f9392
--- /dev/null
+++ b/drivers/misc/keba/cp500.c
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) KEBA Industrial Automation Gmbh 2024
+ *
+ * Driver for KEBA system FPGA
+ *
+ * The KEBA system FPGA implements various devices. This driver registers
+ * auxiliary devices for every device within the FPGA.
+ */
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/misc/keba.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#define CP500 "cp500"
+
+#define PCI_VENDOR_ID_KEBA 0xCEBA
+#define PCI_DEVICE_ID_KEBA_CP035 0x2706
+#define PCI_DEVICE_ID_KEBA_CP505 0x2703
+#define PCI_DEVICE_ID_KEBA_CP520 0x2696
+
+#define CP500_SYS_BAR 0
+#define CP500_ECM_BAR 1
+
+/* BAR 0 registers */
+#define CP500_VERSION_REG 0x00
+#define CP500_RECONFIG_REG 0x11 /* upper 8-bits of STARTUP register */
+#define CP500_AXI_REG 0x40
+
+/* Bits in BUILD_REG */
+#define CP500_BUILD_TEST 0x8000 /* FPGA test version */
+
+/* Bits in RECONFIG_REG */
+#define CP500_RECFG_REQ 0x01 /* reconfigure FPGA on next reset */
+
+/* MSIX */
+#define CP500_AXI_MSIX 3
+#define CP500_NUM_MSIX 8
+#define CP500_NUM_MSIX_NO_MMI 2
+#define CP500_NUM_MSIX_NO_AXI 3
+
+/* EEPROM */
+#define CP500_HW_CPU_EEPROM_NAME "cp500_cpu_eeprom"
+
+#define CP500_IS_CP035(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP035)
+#define CP500_IS_CP505(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP505)
+#define CP500_IS_CP520(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP520)
+
+struct cp500_dev_info {
+ off_t offset;
+ size_t size;
+};
+
+struct cp500_devs {
+ struct cp500_dev_info startup;
+ struct cp500_dev_info i2c;
+};
+
+/* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */
+static struct cp500_devs cp035_devices = {
+ .startup = { 0x0000, SZ_4K },
+ .i2c = { 0x4000, SZ_4K },
+};
+
+/* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */
+static struct cp500_devs cp505_devices = {
+ .startup = { 0x0000, SZ_4K },
+ .i2c = { 0x5000, SZ_4K },
+};
+
+/* list of devices within FPGA of CP520 family (CP520, CP530) */
+static struct cp500_devs cp520_devices = {
+ .startup = { 0x0000, SZ_4K },
+ .i2c = { 0x5000, SZ_4K },
+};
+
+struct cp500 {
+ struct pci_dev *pci_dev;
+ struct cp500_devs *devs;
+ int msix_num;
+ struct {
+ int major;
+ int minor;
+ int build;
+ } version;
+
+ /* system FPGA BAR */
+ resource_size_t sys_hwbase;
+ struct keba_i2c_auxdev *i2c;
+
+ /* ECM EtherCAT BAR */
+ resource_size_t ecm_hwbase;
+
+ void __iomem *system_startup_addr;
+};
+
+/* I2C devices */
+static struct i2c_board_info cp500_i2c_info[] = {
+ { /* temperature sensor */
+ I2C_BOARD_INFO("emc1403", 0x4c),
+ },
+ { /*
+ * CPU EEPROM
+ * CP035 family: CPU board
+ * CP505 family: bridge board
+ * CP520 family: carrier board
+ */
+ I2C_BOARD_INFO("24c32", 0x50),
+ .dev_name = CP500_HW_CPU_EEPROM_NAME,
+ },
+ { /* interface board EEPROM */
+ I2C_BOARD_INFO("24c32", 0x51),
+ },
+ { /*
+ * EEPROM (optional)
+ * CP505 family: CPU board
+ * CP520 family: MMI board
+ */
+ I2C_BOARD_INFO("24c32", 0x52),
+ },
+ { /* extension module 0 EEPROM (optional) */
+ I2C_BOARD_INFO("24c32", 0x53),
+ },
+ { /* extension module 1 EEPROM (optional) */
+ I2C_BOARD_INFO("24c32", 0x54),
+ },
+ { /* extension module 2 EEPROM (optional) */
+ I2C_BOARD_INFO("24c32", 0x55),
+ },
+ { /* extension module 3 EEPROM (optional) */
+ I2C_BOARD_INFO("24c32", 0x56),
+ }
+};
+
+static ssize_t cp500_get_fpga_version(struct cp500 *cp500, char *buf,
+ size_t max_len)
+{
+ int n;
+
+ if (CP500_IS_CP035(cp500))
+ n = scnprintf(buf, max_len, "CP035");
+ else if (CP500_IS_CP505(cp500))
+ n = scnprintf(buf, max_len, "CP505");
+ else
+ n = scnprintf(buf, max_len, "CP500");
+
+ n += scnprintf(buf + n, max_len - n, "_FPGA_%d.%02d",
+ cp500->version.major, cp500->version.minor);
+
+ /* test versions have test bit set */
+ if (cp500->version.build & CP500_BUILD_TEST)
+ n += scnprintf(buf + n, max_len - n, "Test%d",
+ cp500->version.build & ~CP500_BUILD_TEST);
+
+ n += scnprintf(buf + n, max_len - n, "\n");
+
+ return n;
+}
+
+static ssize_t version_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cp500 *cp500 = dev_get_drvdata(dev);
+
+ return cp500_get_fpga_version(cp500, buf, PAGE_SIZE);
+}
+static DEVICE_ATTR_RO(version);
+
+static ssize_t keep_cfg_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cp500 *cp500 = dev_get_drvdata(dev);
+ unsigned long keep_cfg = 1;
+
+ /*
+ * FPGA configuration stream is kept during reset when RECONFIG bit is
+ * zero
+ */
+ if (ioread8(cp500->system_startup_addr + CP500_RECONFIG_REG) &
+ CP500_RECFG_REQ)
+ keep_cfg = 0;
+
+ return sysfs_emit(buf, "%lu\n", keep_cfg);
+}
+
+static ssize_t keep_cfg_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cp500 *cp500 = dev_get_drvdata(dev);
+ unsigned long keep_cfg;
+
+ if (kstrtoul(buf, 10, &keep_cfg) < 0)
+ return -EINVAL;
+
+ /*
+ * In normal operation "keep_cfg" is "1". This means that the FPGA keeps
+ * its configuration stream during a reset.
+ * In case of a firmware update of the FPGA, the configuration stream
+ * needs to be reloaded. This can be done without a powercycle by
+ * writing a "0" into the "keep_cfg" attribute. After a reset/reboot th
+ * new configuration stream will be loaded.
+ */
+ if (keep_cfg)
+ iowrite8(0, cp500->system_startup_addr + CP500_RECONFIG_REG);
+ else
+ iowrite8(CP500_RECFG_REQ,
+ cp500->system_startup_addr + CP500_RECONFIG_REG);
+
+ return count;
+}
+static DEVICE_ATTR_RW(keep_cfg);
+
+static struct attribute *attrs[] = {
+ &dev_attr_version.attr,
+ &dev_attr_keep_cfg.attr,
+ NULL
+};
+static const struct attribute_group attrs_group = { .attrs = attrs };
+
+static void cp500_i2c_release(struct device *dev)
+{
+ struct keba_i2c_auxdev *i2c =
+ container_of(dev, struct keba_i2c_auxdev, auxdev.dev);
+
+ kfree(i2c);
+}
+
+static int cp500_register_i2c(struct cp500 *cp500)
+{
+ int retval;
+
+ cp500->i2c = kzalloc(sizeof(*cp500->i2c), GFP_KERNEL);
+ if (!cp500->i2c)
+ return -ENOMEM;
+
+ cp500->i2c->auxdev.name = "i2c";
+ cp500->i2c->auxdev.id = 0;
+ cp500->i2c->auxdev.dev.release = cp500_i2c_release;
+ cp500->i2c->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->i2c->io = (struct resource) {
+ /* I2C register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->i2c.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->i2c.offset +
+ cp500->devs->i2c.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+ cp500->i2c->info_size = ARRAY_SIZE(cp500_i2c_info);
+ cp500->i2c->info = cp500_i2c_info;
+
+ retval = auxiliary_device_init(&cp500->i2c->auxdev);
+ if (retval) {
+ kfree(cp500->i2c);
+ cp500->i2c = NULL;
+
+ return retval;
+ }
+ retval = __auxiliary_device_add(&cp500->i2c->auxdev, "keba");
+ if (retval) {
+ auxiliary_device_uninit(&cp500->i2c->auxdev);
+ cp500->i2c = NULL;
+
+ return retval;
+ }
+
+ return 0;
+}
+
+static void cp500_register_auxiliary_devs(struct cp500 *cp500)
+{
+ struct device *dev = &cp500->pci_dev->dev;
+
+ if (cp500_register_i2c(cp500))
+ dev_warn(dev, "Failed to register i2c!\n");
+}
+
+static void cp500_unregister_dev(struct auxiliary_device *auxdev)
+{
+ auxiliary_device_delete(auxdev);
+ auxiliary_device_uninit(auxdev);
+}
+
+static void cp500_unregister_auxiliary_devs(struct cp500 *cp500)
+{
+
+ if (cp500->i2c) {
+ cp500_unregister_dev(&cp500->i2c->auxdev);
+ cp500->i2c = NULL;
+ }
+}
+
+static irqreturn_t cp500_axi_handler(int irq, void *dev)
+{
+ struct cp500 *cp500 = dev;
+ u32 axi_address = ioread32(cp500->system_startup_addr + CP500_AXI_REG);
+
+ /*
+ * FPGA signals AXI response error, print AXI address to indicate which
+ * IP core was affected
+ */
+ dev_err(&cp500->pci_dev->dev, "AXI response error at 0x%08x\n",
+ axi_address);
+
+ return IRQ_HANDLED;
+}
+
+static int cp500_enable(struct cp500 *cp500)
+{
+ int axi_irq = -1;
+ int ret;
+
+ if (cp500->msix_num > CP500_NUM_MSIX_NO_AXI) {
+ axi_irq = pci_irq_vector(cp500->pci_dev, CP500_AXI_MSIX);
+ ret = request_irq(axi_irq, cp500_axi_handler, 0,
+ CP500, cp500);
+ if (ret != 0) {
+ dev_err(&cp500->pci_dev->dev,
+ "Failed to register AXI response error!\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void cp500_disable(struct cp500 *cp500)
+{
+ int axi_irq;
+
+ if (cp500->msix_num > CP500_NUM_MSIX_NO_AXI) {
+ axi_irq = pci_irq_vector(cp500->pci_dev, CP500_AXI_MSIX);
+ free_irq(axi_irq, cp500);
+ }
+}
+
+static int cp500_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+{
+ struct device *dev = &pci_dev->dev;
+ struct resource startup;
+ struct cp500 *cp500;
+ u32 cp500_vers;
+ char buf[64];
+ int ret;
+
+ cp500 = devm_kzalloc(dev, sizeof(*cp500), GFP_KERNEL);
+ if (!cp500)
+ return -ENOMEM;
+ cp500->pci_dev = pci_dev;
+ cp500->sys_hwbase = pci_resource_start(pci_dev, CP500_SYS_BAR);
+ cp500->ecm_hwbase = pci_resource_start(pci_dev, CP500_ECM_BAR);
+ if (!cp500->sys_hwbase || !cp500->ecm_hwbase)
+ return -ENODEV;
+
+ if (CP500_IS_CP035(cp500))
+ cp500->devs = &cp035_devices;
+ else if (CP500_IS_CP505(cp500))
+ cp500->devs = &cp505_devices;
+ else if (CP500_IS_CP520(cp500))
+ cp500->devs = &cp520_devices;
+ else
+ return -ENODEV;
+
+ ret = pci_enable_device(pci_dev);
+ if (ret)
+ return ret;
+ pci_set_master(pci_dev);
+
+ startup = *pci_resource_n(pci_dev, CP500_SYS_BAR);
+ startup.end = startup.start + cp500->devs->startup.size - 1;
+ cp500->system_startup_addr = devm_ioremap_resource(&pci_dev->dev,
+ &startup);
+ if (IS_ERR(cp500->system_startup_addr)) {
+ ret = PTR_ERR(cp500->system_startup_addr);
+ goto out_disable;
+ }
+
+ cp500->msix_num = pci_alloc_irq_vectors(pci_dev, CP500_NUM_MSIX_NO_MMI,
+ CP500_NUM_MSIX, PCI_IRQ_MSIX);
+ if (cp500->msix_num < CP500_NUM_MSIX_NO_MMI) {
+ dev_err(&pci_dev->dev,
+ "Hardware does not support enough MSI-X interrupts\n");
+ ret = -ENODEV;
+ goto out_disable;
+ }
+
+ cp500_vers = ioread32(cp500->system_startup_addr + CP500_VERSION_REG);
+ cp500->version.major = (cp500_vers & 0xff);
+ cp500->version.minor = (cp500_vers >> 8) & 0xff;
+ cp500->version.build = (cp500_vers >> 16) & 0xffff;
+ cp500_get_fpga_version(cp500, buf, sizeof(buf));
+
+ dev_info(&pci_dev->dev, "FPGA version %s", buf);
+
+ pci_set_drvdata(pci_dev, cp500);
+
+ ret = sysfs_create_group(&pci_dev->dev.kobj, &attrs_group);
+ if (ret != 0)
+ goto out_free_irq;
+
+ ret = cp500_enable(cp500);
+ if (ret != 0)
+ goto out_remove_group;
+
+ cp500_register_auxiliary_devs(cp500);
+
+ return 0;
+
+out_remove_group:
+ sysfs_remove_group(&pci_dev->dev.kobj, &attrs_group);
+out_free_irq:
+ pci_free_irq_vectors(pci_dev);
+out_disable:
+ pci_clear_master(pci_dev);
+ pci_disable_device(pci_dev);
+
+ return ret;
+}
+
+static void cp500_remove(struct pci_dev *pci_dev)
+{
+ struct cp500 *cp500 = pci_get_drvdata(pci_dev);
+
+ cp500_unregister_auxiliary_devs(cp500);
+
+ cp500_disable(cp500);
+
+ sysfs_remove_group(&pci_dev->dev.kobj, &attrs_group);
+
+ pci_set_drvdata(pci_dev, 0);
+
+ pci_free_irq_vectors(pci_dev);
+
+ pci_clear_master(pci_dev);
+ pci_disable_device(pci_dev);
+}
+
+static struct pci_device_id cp500_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP035) },
+ { PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP505) },
+ { PCI_DEVICE(PCI_VENDOR_ID_KEBA, PCI_DEVICE_ID_KEBA_CP520) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, cp500_ids);
+
+static struct pci_driver cp500_driver = {
+ .name = CP500,
+ .id_table = cp500_ids,
+ .probe = cp500_probe,
+ .remove = cp500_remove,
+};
+module_pci_driver(cp500_driver);
+
+MODULE_AUTHOR("Gerhard Engleder <eg@keba.com>");
+MODULE_DESCRIPTION("KEBA CP500 system FPGA driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 2733070acf39..9eebeffcd8fd 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -80,6 +80,8 @@ static void whitelist(struct mei_cl_device *cldev)
cldev->do_match = 1;
}
+#define MKHI_SEND_MAX_TIMEOUT_MSEC 4000
+
#define OSTYPE_LINUX 2
struct mei_os_ver {
__le16 build;
@@ -128,7 +130,7 @@ static int mei_osver(struct mei_cl_device *cldev)
os_ver = (struct mei_os_ver *)fwcaps->data;
os_ver->os_type = OSTYPE_LINUX;
- return __mei_cl_send(cldev->cl, buf, size, 0, mode);
+ return __mei_cl_send_timeout(cldev->cl, buf, size, 0, mode, MKHI_SEND_MAX_TIMEOUT_MSEC);
}
#define MKHI_FWVER_BUF_LEN (sizeof(struct mkhi_msg_hdr) + \
@@ -148,8 +150,8 @@ static int mei_fwver(struct mei_cl_device *cldev)
req.hdr.group_id = MKHI_GEN_GROUP_ID;
req.hdr.command = MKHI_GEN_GET_FW_VERSION_CMD;
- ret = __mei_cl_send(cldev->cl, (u8 *)&req, sizeof(req), 0,
- MEI_CL_IO_TX_BLOCKING);
+ ret = __mei_cl_send_timeout(cldev->cl, (u8 *)&req, sizeof(req), 0,
+ MEI_CL_IO_TX_BLOCKING, MKHI_SEND_MAX_TIMEOUT_MSEC);
if (ret < 0) {
dev_info(&cldev->dev, "Could not send ReqFWVersion cmd ret = %d\n", ret);
return ret;
diff --git a/drivers/misc/mrvl_cn10k_dpi.c b/drivers/misc/mrvl_cn10k_dpi.c
new file mode 100644
index 000000000000..7d5433121ff6
--- /dev/null
+++ b/drivers/misc/mrvl_cn10k_dpi.c
@@ -0,0 +1,676 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell Octeon CN10K DPI driver
+ *
+ * Copyright (C) 2024 Marvell.
+ *
+ */
+
+#include <linux/bitfield.h>
+#include <linux/compat.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <uapi/misc/mrvl_cn10k_dpi.h>
+
+/* PCI device IDs */
+#define PCI_DEVID_MRVL_CN10K_DPI_PF 0xA080
+#define PCI_SUBDEVID_MRVL_CN10K_DPI_PF 0xB900
+
+/* PCI BAR Number */
+#define PCI_DPI_CFG_BAR 0
+
+/* MSI-X interrupts */
+#define DPI_MAX_REQQ_INT 0x20
+#define DPI_MAX_CC_INT 0x40
+
+/* MBOX MSI-X interrupt vector index */
+#define DPI_MBOX_PF_VF_INT_IDX 0x75
+
+#define DPI_MAX_IRQS (DPI_MBOX_PF_VF_INT_IDX + 1)
+
+#define DPI_MAX_VFS 0x20
+
+#define DPI_MAX_ENG_FIFO_SZ 0x20
+#define DPI_MAX_ENG_MOLR 0x400
+
+#define DPI_DMA_IDS_DMA_NPA_PF_FUNC(x) FIELD_PREP(GENMASK_ULL(31, 16), x)
+#define DPI_DMA_IDS_INST_STRM(x) FIELD_PREP(GENMASK_ULL(47, 40), x)
+#define DPI_DMA_IDS_DMA_STRM(x) FIELD_PREP(GENMASK_ULL(39, 32), x)
+#define DPI_DMA_ENG_EN_MOLR(x) FIELD_PREP(GENMASK_ULL(41, 32), x)
+#define DPI_EBUS_PORTX_CFG_MPS(x) FIELD_PREP(GENMASK(6, 4), x)
+#define DPI_DMA_IDS_DMA_SSO_PF_FUNC(x) FIELD_PREP(GENMASK(15, 0), x)
+#define DPI_DMA_IDS2_INST_AURA(x) FIELD_PREP(GENMASK(19, 0), x)
+#define DPI_DMA_IBUFF_CSIZE_CSIZE(x) FIELD_PREP(GENMASK(13, 0), x)
+#define DPI_EBUS_PORTX_CFG_MRRS(x) FIELD_PREP(GENMASK(2, 0), x)
+#define DPI_ENG_BUF_BLKS(x) FIELD_PREP(GENMASK(5, 0), x)
+#define DPI_DMA_CONTROL_DMA_ENB GENMASK_ULL(53, 48)
+
+#define DPI_DMA_CONTROL_O_MODE BIT_ULL(14)
+#define DPI_DMA_CONTROL_LDWB BIT_ULL(32)
+#define DPI_DMA_CONTROL_WQECSMODE1 BIT_ULL(37)
+#define DPI_DMA_CONTROL_ZBWCSEN BIT_ULL(39)
+#define DPI_DMA_CONTROL_WQECSOFF(ofst) (((u64)ofst) << 40)
+#define DPI_DMA_CONTROL_WQECSDIS BIT_ULL(47)
+#define DPI_DMA_CONTROL_PKT_EN BIT_ULL(56)
+#define DPI_DMA_IBUFF_CSIZE_NPA_FREE BIT(16)
+
+#define DPI_CTL_EN BIT_ULL(0)
+#define DPI_DMA_CC_INT BIT_ULL(0)
+#define DPI_DMA_QRST BIT_ULL(0)
+
+#define DPI_REQQ_INT_INSTRFLT BIT_ULL(0)
+#define DPI_REQQ_INT_RDFLT BIT_ULL(1)
+#define DPI_REQQ_INT_WRFLT BIT_ULL(2)
+#define DPI_REQQ_INT_CSFLT BIT_ULL(3)
+#define DPI_REQQ_INT_INST_DBO BIT_ULL(4)
+#define DPI_REQQ_INT_INST_ADDR_NULL BIT_ULL(5)
+#define DPI_REQQ_INT_INST_FILL_INVAL BIT_ULL(6)
+#define DPI_REQQ_INT_INSTR_PSN BIT_ULL(7)
+
+#define DPI_REQQ_INT \
+ (DPI_REQQ_INT_INSTRFLT | \
+ DPI_REQQ_INT_RDFLT | \
+ DPI_REQQ_INT_WRFLT | \
+ DPI_REQQ_INT_CSFLT | \
+ DPI_REQQ_INT_INST_DBO | \
+ DPI_REQQ_INT_INST_ADDR_NULL | \
+ DPI_REQQ_INT_INST_FILL_INVAL | \
+ DPI_REQQ_INT_INSTR_PSN)
+
+#define DPI_PF_RAS_EBI_DAT_PSN BIT_ULL(0)
+#define DPI_PF_RAS_NCB_DAT_PSN BIT_ULL(1)
+#define DPI_PF_RAS_NCB_CMD_PSN BIT_ULL(2)
+
+#define DPI_PF_RAS_INT \
+ (DPI_PF_RAS_EBI_DAT_PSN | \
+ DPI_PF_RAS_NCB_DAT_PSN | \
+ DPI_PF_RAS_NCB_CMD_PSN)
+
+/* Message fields in word_l of DPI mailbox structure */
+#define DPI_MBOX_VFID(msg) FIELD_GET(GENMASK_ULL(7, 0), msg)
+#define DPI_MBOX_CMD(msg) FIELD_GET(GENMASK_ULL(11, 8), msg)
+#define DPI_MBOX_CBUF_SIZE(msg) FIELD_GET(GENMASK_ULL(27, 12), msg)
+#define DPI_MBOX_CBUF_AURA(msg) FIELD_GET(GENMASK_ULL(47, 28), msg)
+#define DPI_MBOX_SSO_PFFUNC(msg) FIELD_GET(GENMASK_ULL(63, 48), msg)
+
+/* Message fields in word_h of DPI mailbox structure */
+#define DPI_MBOX_NPA_PFFUNC(msg) FIELD_GET(GENMASK_ULL(15, 0), msg)
+#define DPI_MBOX_WQES_COMPL(msg) FIELD_GET(GENMASK_ULL(16, 16), msg)
+#define DPI_MBOX_WQES_OFFSET(msg) FIELD_GET(GENMASK_ULL(23, 17), msg)
+
+#define DPI_DMAX_IBUFF_CSIZE(x) (0x0ULL | ((x) << 11))
+#define DPI_DMAX_IDS(x) (0x18ULL | ((x) << 11))
+#define DPI_DMAX_IDS2(x) (0x20ULL | ((x) << 11))
+#define DPI_DMAX_QRST(x) (0x30ULL | ((x) << 11))
+
+#define DPI_CTL 0x10010ULL
+#define DPI_DMA_CONTROL 0x10018ULL
+#define DPI_PF_RAS 0x10308ULL
+#define DPI_PF_RAS_ENA_W1C 0x10318ULL
+#define DPI_MBOX_VF_PF_INT 0x16300ULL
+#define DPI_MBOX_VF_PF_INT_W1S 0x16308ULL
+#define DPI_MBOX_VF_PF_INT_ENA_W1C 0x16310ULL
+#define DPI_MBOX_VF_PF_INT_ENA_W1S 0x16318ULL
+
+#define DPI_DMA_ENGX_EN(x) (0x10040ULL | ((x) << 3))
+#define DPI_ENGX_BUF(x) (0x100C0ULL | ((x) << 3))
+#define DPI_EBUS_PORTX_CFG(x) (0x10100ULL | ((x) << 3))
+#define DPI_DMA_CCX_INT(x) (0x11000ULL | ((x) << 3))
+#define DPI_DMA_CCX_INT_ENA_W1C(x) (0x11800ULL | ((x) << 3))
+#define DPI_REQQX_INT(x) (0x12C00ULL | ((x) << 5))
+#define DPI_REQQX_INT_ENA_W1C(x) (0x13800ULL | ((x) << 5))
+#define DPI_MBOX_PF_VF_DATA0(x) (0x16000ULL | ((x) << 4))
+#define DPI_MBOX_PF_VF_DATA1(x) (0x16008ULL | ((x) << 4))
+
+#define DPI_WCTL_FIF_THR 0x17008ULL
+
+#define DPI_EBUS_MAX_PORTS 2
+
+#define DPI_EBUS_MRRS_MIN 128
+#define DPI_EBUS_MRRS_MAX 1024
+#define DPI_EBUS_MPS_MIN 128
+#define DPI_EBUS_MPS_MAX 1024
+#define DPI_WCTL_FIFO_THRESHOLD 0x30
+
+#define DPI_QUEUE_OPEN 0x1
+#define DPI_QUEUE_CLOSE 0x2
+#define DPI_REG_DUMP 0x3
+#define DPI_GET_REG_CFG 0x4
+#define DPI_QUEUE_OPEN_V2 0x5
+
+enum dpi_mbox_rsp_type {
+ DPI_MBOX_TYPE_CMD,
+ DPI_MBOX_TYPE_RSP_ACK,
+ DPI_MBOX_TYPE_RSP_NACK,
+};
+
+struct dpivf_config {
+ u32 aura;
+ u16 csize;
+ u16 sso_pf_func;
+ u16 npa_pf_func;
+};
+
+struct dpipf_vf {
+ struct dpivf_config vf_config;
+ bool setup_done;
+ u8 this_vfid;
+};
+
+/* DPI device mailbox */
+struct dpi_mbox {
+ struct work_struct work;
+ /* lock to serialize mbox requests */
+ struct mutex lock;
+ struct dpipf *pf;
+ u8 __iomem *pf_vf_data_reg;
+ u8 __iomem *vf_pf_data_reg;
+};
+
+struct dpipf {
+ struct miscdevice miscdev;
+ void __iomem *reg_base;
+ struct pci_dev *pdev;
+ struct dpipf_vf vf[DPI_MAX_VFS];
+ /* Mailbox to talk to VFs */
+ struct dpi_mbox *mbox[DPI_MAX_VFS];
+};
+
+struct dpi_mbox_message {
+ uint64_t word_l;
+ uint64_t word_h;
+};
+
+static inline void dpi_reg_write(struct dpipf *dpi, u64 offset, u64 val)
+{
+ writeq(val, dpi->reg_base + offset);
+}
+
+static inline u64 dpi_reg_read(struct dpipf *dpi, u64 offset)
+{
+ return readq(dpi->reg_base + offset);
+}
+
+static void dpi_wqe_cs_offset(struct dpipf *dpi, u8 offset)
+{
+ u64 reg;
+
+ reg = dpi_reg_read(dpi, DPI_DMA_CONTROL);
+ reg &= ~DPI_DMA_CONTROL_WQECSDIS;
+ reg |= DPI_DMA_CONTROL_ZBWCSEN | DPI_DMA_CONTROL_WQECSMODE1;
+ reg |= DPI_DMA_CONTROL_WQECSOFF(offset);
+ dpi_reg_write(dpi, DPI_DMA_CONTROL, reg);
+}
+
+static int dpi_queue_init(struct dpipf *dpi, struct dpipf_vf *dpivf, u8 vf)
+{
+ u16 sso_pf_func = dpivf->vf_config.sso_pf_func;
+ u16 npa_pf_func = dpivf->vf_config.npa_pf_func;
+ u16 csize = dpivf->vf_config.csize;
+ u32 aura = dpivf->vf_config.aura;
+ unsigned long timeout;
+ u64 reg;
+
+ dpi_reg_write(dpi, DPI_DMAX_QRST(vf), DPI_DMA_QRST);
+
+ /* Wait for a maximum of 3 sec */
+ timeout = jiffies + msecs_to_jiffies(3000);
+ while (!time_after(jiffies, timeout)) {
+ reg = dpi_reg_read(dpi, DPI_DMAX_QRST(vf));
+ if (!(reg & DPI_DMA_QRST))
+ break;
+
+ /* Reset would take time for the request cache to drain */
+ usleep_range(500, 1000);
+ }
+
+ if (reg & DPI_DMA_QRST) {
+ dev_err(&dpi->pdev->dev, "Queue reset failed\n");
+ return -EBUSY;
+ }
+
+ dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), 0);
+ dpi_reg_write(dpi, DPI_DMAX_IDS(vf), 0);
+
+ reg = DPI_DMA_IBUFF_CSIZE_CSIZE(csize) | DPI_DMA_IBUFF_CSIZE_NPA_FREE;
+ dpi_reg_write(dpi, DPI_DMAX_IBUFF_CSIZE(vf), reg);
+
+ reg = dpi_reg_read(dpi, DPI_DMAX_IDS2(vf));
+ reg |= DPI_DMA_IDS2_INST_AURA(aura);
+ dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), reg);
+
+ reg = dpi_reg_read(dpi, DPI_DMAX_IDS(vf));
+ reg |= DPI_DMA_IDS_DMA_NPA_PF_FUNC(npa_pf_func);
+ reg |= DPI_DMA_IDS_DMA_SSO_PF_FUNC(sso_pf_func);
+ reg |= DPI_DMA_IDS_DMA_STRM(vf + 1);
+ reg |= DPI_DMA_IDS_INST_STRM(vf + 1);
+ dpi_reg_write(dpi, DPI_DMAX_IDS(vf), reg);
+
+ return 0;
+}
+
+static void dpi_queue_fini(struct dpipf *dpi, u8 vf)
+{
+ dpi_reg_write(dpi, DPI_DMAX_QRST(vf), DPI_DMA_QRST);
+
+ /* Reset IDS and IDS2 registers */
+ dpi_reg_write(dpi, DPI_DMAX_IDS2(vf), 0);
+ dpi_reg_write(dpi, DPI_DMAX_IDS(vf), 0);
+}
+
+static irqreturn_t dpi_mbox_intr_handler(int irq, void *data)
+{
+ struct dpipf *dpi = data;
+ u64 reg;
+ u32 vf;
+
+ reg = dpi_reg_read(dpi, DPI_MBOX_VF_PF_INT);
+ if (reg) {
+ for (vf = 0; vf < pci_num_vf(dpi->pdev); vf++) {
+ if (reg & BIT_ULL(vf))
+ schedule_work(&dpi->mbox[vf]->work);
+ }
+ dpi_reg_write(dpi, DPI_MBOX_VF_PF_INT, reg);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int queue_config(struct dpipf *dpi, struct dpipf_vf *dpivf, struct dpi_mbox_message *msg)
+{
+ int ret = 0;
+
+ switch (DPI_MBOX_CMD(msg->word_l)) {
+ case DPI_QUEUE_OPEN:
+ case DPI_QUEUE_OPEN_V2:
+ dpivf->vf_config.aura = DPI_MBOX_CBUF_AURA(msg->word_l);
+ dpivf->vf_config.csize = DPI_MBOX_CMD(msg->word_l) == DPI_QUEUE_OPEN ?
+ DPI_MBOX_CBUF_SIZE(msg->word_l) >> 3 :
+ DPI_MBOX_CBUF_SIZE(msg->word_l);
+ dpivf->vf_config.sso_pf_func = DPI_MBOX_SSO_PFFUNC(msg->word_l);
+ dpivf->vf_config.npa_pf_func = DPI_MBOX_NPA_PFFUNC(msg->word_h);
+ ret = dpi_queue_init(dpi, dpivf, DPI_MBOX_VFID(msg->word_l));
+ if (!ret) {
+ if (DPI_MBOX_WQES_COMPL(msg->word_h))
+ dpi_wqe_cs_offset(dpi, DPI_MBOX_WQES_OFFSET(msg->word_h));
+ dpivf->setup_done = true;
+ }
+ break;
+ case DPI_QUEUE_CLOSE:
+ memset(&dpivf->vf_config, 0, sizeof(struct dpivf_config));
+ dpi_queue_fini(dpi, DPI_MBOX_VFID(msg->word_l));
+ dpivf->setup_done = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static void dpi_pfvf_mbox_work(struct work_struct *work)
+{
+ struct dpi_mbox *mbox = container_of(work, struct dpi_mbox, work);
+ struct dpi_mbox_message msg;
+ struct dpipf_vf *dpivf;
+ struct dpipf *dpi;
+ int vfid, ret;
+
+ dpi = mbox->pf;
+ memset(&msg, 0, sizeof(msg));
+
+ mutex_lock(&mbox->lock);
+ msg.word_l = readq(mbox->vf_pf_data_reg);
+ if (msg.word_l == (u64)-1)
+ goto exit;
+
+ vfid = DPI_MBOX_VFID(msg.word_l);
+ if (vfid >= pci_num_vf(dpi->pdev))
+ goto exit;
+
+ dpivf = &dpi->vf[vfid];
+ msg.word_h = readq(mbox->pf_vf_data_reg);
+
+ ret = queue_config(dpi, dpivf, &msg);
+ if (ret < 0)
+ writeq(DPI_MBOX_TYPE_RSP_NACK, mbox->pf_vf_data_reg);
+ else
+ writeq(DPI_MBOX_TYPE_RSP_ACK, mbox->pf_vf_data_reg);
+exit:
+ mutex_unlock(&mbox->lock);
+}
+
+/* Setup registers for a PF mailbox */
+static void dpi_setup_mbox_regs(struct dpipf *dpi, int vf)
+{
+ struct dpi_mbox *mbox = dpi->mbox[vf];
+
+ mbox->pf_vf_data_reg = dpi->reg_base + DPI_MBOX_PF_VF_DATA0(vf);
+ mbox->vf_pf_data_reg = dpi->reg_base + DPI_MBOX_PF_VF_DATA1(vf);
+}
+
+static int dpi_pfvf_mbox_setup(struct dpipf *dpi)
+{
+ int vf;
+
+ for (vf = 0; vf < DPI_MAX_VFS; vf++) {
+ dpi->mbox[vf] = devm_kzalloc(&dpi->pdev->dev, sizeof(*dpi->mbox[vf]), GFP_KERNEL);
+
+ if (!dpi->mbox[vf])
+ return -ENOMEM;
+
+ mutex_init(&dpi->mbox[vf]->lock);
+ INIT_WORK(&dpi->mbox[vf]->work, dpi_pfvf_mbox_work);
+ dpi->mbox[vf]->pf = dpi;
+ dpi_setup_mbox_regs(dpi, vf);
+ }
+
+ return 0;
+}
+
+static void dpi_pfvf_mbox_destroy(struct dpipf *dpi)
+{
+ unsigned int vf;
+
+ for (vf = 0; vf < DPI_MAX_VFS; vf++) {
+ if (work_pending(&dpi->mbox[vf]->work))
+ cancel_work_sync(&dpi->mbox[vf]->work);
+
+ dpi->mbox[vf] = NULL;
+ }
+}
+
+static void dpi_init(struct dpipf *dpi)
+{
+ unsigned int engine, port;
+ u8 mrrs_val, mps_val;
+ u64 reg;
+
+ for (engine = 0; engine < DPI_MAX_ENGINES; engine++) {
+ if (engine == 4 || engine == 5)
+ reg = DPI_ENG_BUF_BLKS(16);
+ else
+ reg = DPI_ENG_BUF_BLKS(8);
+
+ dpi_reg_write(dpi, DPI_ENGX_BUF(engine), reg);
+ }
+
+ reg = DPI_DMA_CONTROL_ZBWCSEN | DPI_DMA_CONTROL_PKT_EN | DPI_DMA_CONTROL_LDWB |
+ DPI_DMA_CONTROL_O_MODE | DPI_DMA_CONTROL_DMA_ENB;
+
+ dpi_reg_write(dpi, DPI_DMA_CONTROL, reg);
+ dpi_reg_write(dpi, DPI_CTL, DPI_CTL_EN);
+
+ mrrs_val = 2; /* 512B */
+ mps_val = 1; /* 256B */
+
+ for (port = 0; port < DPI_EBUS_MAX_PORTS; port++) {
+ reg = dpi_reg_read(dpi, DPI_EBUS_PORTX_CFG(port));
+ reg &= ~(DPI_EBUS_PORTX_CFG_MRRS(7) | DPI_EBUS_PORTX_CFG_MPS(7));
+ reg |= DPI_EBUS_PORTX_CFG_MPS(mps_val) | DPI_EBUS_PORTX_CFG_MRRS(mrrs_val);
+ dpi_reg_write(dpi, DPI_EBUS_PORTX_CFG(port), reg);
+ }
+
+ dpi_reg_write(dpi, DPI_WCTL_FIF_THR, DPI_WCTL_FIFO_THRESHOLD);
+}
+
+static void dpi_fini(struct dpipf *dpi)
+{
+ unsigned int engine;
+
+ for (engine = 0; engine < DPI_MAX_ENGINES; engine++)
+ dpi_reg_write(dpi, DPI_ENGX_BUF(engine), 0);
+
+ dpi_reg_write(dpi, DPI_DMA_CONTROL, 0);
+ dpi_reg_write(dpi, DPI_CTL, 0);
+}
+
+static void dpi_free_irq_vectors(void *pdev)
+{
+ pci_free_irq_vectors((struct pci_dev *)pdev);
+}
+
+static int dpi_irq_init(struct dpipf *dpi)
+{
+ struct pci_dev *pdev = dpi->pdev;
+ struct device *dev = &pdev->dev;
+ int i, ret;
+
+ /* Clear all RAS interrupts */
+ dpi_reg_write(dpi, DPI_PF_RAS, DPI_PF_RAS_INT);
+
+ /* Clear all RAS interrupt enable bits */
+ dpi_reg_write(dpi, DPI_PF_RAS_ENA_W1C, DPI_PF_RAS_INT);
+
+ for (i = 0; i < DPI_MAX_REQQ_INT; i++) {
+ dpi_reg_write(dpi, DPI_REQQX_INT(i), DPI_REQQ_INT);
+ dpi_reg_write(dpi, DPI_REQQX_INT_ENA_W1C(i), DPI_REQQ_INT);
+ }
+
+ for (i = 0; i < DPI_MAX_CC_INT; i++) {
+ dpi_reg_write(dpi, DPI_DMA_CCX_INT(i), DPI_DMA_CC_INT);
+ dpi_reg_write(dpi, DPI_DMA_CCX_INT_ENA_W1C(i), DPI_DMA_CC_INT);
+ }
+
+ ret = pci_alloc_irq_vectors(pdev, DPI_MAX_IRQS, DPI_MAX_IRQS, PCI_IRQ_MSIX);
+ if (ret != DPI_MAX_IRQS) {
+ dev_err(dev, "DPI: Failed to alloc %d msix irqs\n", DPI_MAX_IRQS);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(dev, dpi_free_irq_vectors, pdev);
+ if (ret) {
+ dev_err(dev, "DPI: Failed to add irq free action\n");
+ return ret;
+ }
+
+ ret = devm_request_irq(dev, pci_irq_vector(pdev, DPI_MBOX_PF_VF_INT_IDX),
+ dpi_mbox_intr_handler, 0, "dpi-mbox", dpi);
+ if (ret) {
+ dev_err(dev, "DPI: request_irq failed for mbox; err=%d\n", ret);
+ return ret;
+ }
+
+ dpi_reg_write(dpi, DPI_MBOX_VF_PF_INT_ENA_W1S, GENMASK_ULL(31, 0));
+
+ return 0;
+}
+
+static int dpi_mps_mrrs_config(struct dpipf *dpi, void __user *arg)
+{
+ struct dpi_mps_mrrs_cfg cfg;
+ u8 mrrs_val, mps_val;
+ u64 reg;
+
+ if (copy_from_user(&cfg, arg, sizeof(struct dpi_mps_mrrs_cfg)))
+ return -EFAULT;
+
+ if (cfg.max_read_req_sz < DPI_EBUS_MRRS_MIN || cfg.max_read_req_sz > DPI_EBUS_MRRS_MAX ||
+ !is_power_of_2(cfg.max_read_req_sz))
+ return -EINVAL;
+
+ if (cfg.max_payload_sz < DPI_EBUS_MPS_MIN || cfg.max_payload_sz > DPI_EBUS_MPS_MAX ||
+ !is_power_of_2(cfg.max_payload_sz))
+ return -EINVAL;
+
+ if (cfg.port >= DPI_EBUS_MAX_PORTS)
+ return -EINVAL;
+
+ /* Make sure reserved fields are set to 0 */
+ if (cfg.reserved)
+ return -EINVAL;
+
+ mrrs_val = fls(cfg.max_read_req_sz >> 8);
+ mps_val = fls(cfg.max_payload_sz >> 8);
+
+ reg = dpi_reg_read(dpi, DPI_EBUS_PORTX_CFG(cfg.port));
+ reg &= ~(DPI_EBUS_PORTX_CFG_MRRS(0x7) | DPI_EBUS_PORTX_CFG_MPS(0x7));
+ reg |= DPI_EBUS_PORTX_CFG_MPS(mps_val) | DPI_EBUS_PORTX_CFG_MRRS(mrrs_val);
+ dpi_reg_write(dpi, DPI_EBUS_PORTX_CFG(cfg.port), reg);
+
+ return 0;
+}
+
+static int dpi_engine_config(struct dpipf *dpi, void __user *arg)
+{
+ struct dpi_engine_cfg cfg;
+ unsigned int engine;
+ u8 *eng_buf;
+ u64 reg;
+
+ if (copy_from_user(&cfg, arg, sizeof(struct dpi_engine_cfg)))
+ return -EFAULT;
+
+ /* Make sure reserved fields are set to 0 */
+ if (cfg.reserved)
+ return -EINVAL;
+
+ eng_buf = (u8 *)&cfg.fifo_mask;
+
+ for (engine = 0; engine < DPI_MAX_ENGINES; engine++) {
+ if (eng_buf[engine] > DPI_MAX_ENG_FIFO_SZ)
+ return -EINVAL;
+ dpi_reg_write(dpi, DPI_ENGX_BUF(engine), eng_buf[engine]);
+
+ if (cfg.update_molr) {
+ if (cfg.molr[engine] > DPI_MAX_ENG_MOLR)
+ return -EINVAL;
+ reg = DPI_DMA_ENG_EN_MOLR(cfg.molr[engine]);
+ dpi_reg_write(dpi, DPI_DMA_ENGX_EN(engine), reg);
+ } else {
+ /* Make sure unused fields are set to 0 */
+ if (cfg.molr[engine])
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static long dpi_dev_ioctl(struct file *fptr, unsigned int cmd, unsigned long data)
+{
+ void __user *arg = (void __user *)data;
+ struct dpipf *dpi;
+ int ret;
+
+ dpi = container_of(fptr->private_data, struct dpipf, miscdev);
+
+ switch (cmd) {
+ case DPI_MPS_MRRS_CFG:
+ ret = dpi_mps_mrrs_config(dpi, arg);
+ break;
+ case DPI_ENGINE_CFG:
+ ret = dpi_engine_config(dpi, arg);
+ break;
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct file_operations dpi_device_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = dpi_dev_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+};
+
+static int dpi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct device *dev = &pdev->dev;
+ struct dpipf *dpi;
+ int ret;
+
+ dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
+ if (!dpi)
+ return -ENOMEM;
+
+ dpi->pdev = pdev;
+
+ ret = pcim_enable_device(pdev);
+ if (ret) {
+ dev_err(dev, "DPI: Failed to enable PCI device\n");
+ return ret;
+ }
+
+ ret = pcim_iomap_regions(pdev, BIT(0) | BIT(4), KBUILD_MODNAME);
+ if (ret) {
+ dev_err(dev, "DPI: Failed to request MMIO region\n");
+ return ret;
+ }
+
+ dpi->reg_base = pcim_iomap_table(pdev)[PCI_DPI_CFG_BAR];
+
+ /* Initialize global PF registers */
+ dpi_init(dpi);
+
+ /* Setup PF-VF mailbox */
+ ret = dpi_pfvf_mbox_setup(dpi);
+ if (ret) {
+ dev_err(dev, "DPI: Failed to setup pf-vf mbox\n");
+ goto err_dpi_fini;
+ }
+
+ /* Register interrupts */
+ ret = dpi_irq_init(dpi);
+ if (ret) {
+ dev_err(dev, "DPI: Failed to initialize irq vectors\n");
+ goto err_dpi_mbox_free;
+ }
+
+ pci_set_drvdata(pdev, dpi);
+ dpi->miscdev.minor = MISC_DYNAMIC_MINOR;
+ dpi->miscdev.name = KBUILD_MODNAME;
+ dpi->miscdev.fops = &dpi_device_fops;
+ dpi->miscdev.parent = dev;
+
+ ret = misc_register(&dpi->miscdev);
+ if (ret) {
+ dev_err(dev, "DPI: Failed to register misc device\n");
+ goto err_dpi_mbox_free;
+ }
+
+ return 0;
+
+err_dpi_mbox_free:
+ dpi_pfvf_mbox_destroy(dpi);
+err_dpi_fini:
+ dpi_fini(dpi);
+ return ret;
+}
+
+static void dpi_remove(struct pci_dev *pdev)
+{
+ struct dpipf *dpi = pci_get_drvdata(pdev);
+
+ misc_deregister(&dpi->miscdev);
+ pci_sriov_configure_simple(pdev, 0);
+ dpi_pfvf_mbox_destroy(dpi);
+ dpi_fini(dpi);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static const struct pci_device_id dpi_id_table[] = {
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_MRVL_CN10K_DPI_PF,
+ PCI_VENDOR_ID_CAVIUM, PCI_SUBDEVID_MRVL_CN10K_DPI_PF) },
+ { 0, } /* end of table */
+};
+
+static struct pci_driver dpi_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = dpi_id_table,
+ .probe = dpi_probe,
+ .remove = dpi_remove,
+ .sriov_configure = pci_sriov_configure_simple,
+};
+
+module_pci_driver(dpi_driver);
+MODULE_DEVICE_TABLE(pci, dpi_id_table);
+MODULE_AUTHOR("Marvell.");
+MODULE_DESCRIPTION("Marvell Octeon CN10K DPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/open-dice.c b/drivers/misc/open-dice.c
index 1e3eb2aa44d9..e6a61e6d9427 100644
--- a/drivers/misc/open-dice.c
+++ b/drivers/misc/open-dice.c
@@ -201,5 +201,6 @@ static void __exit open_dice_exit(void)
module_init(open_dice_init);
module_exit(open_dice_exit);
+MODULE_DESCRIPTION("Driver for Open Profile for DICE.");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("David Brazdil <dbrazdil@google.com>");
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index c4f963cf96f2..ff172cf4614d 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -198,7 +198,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
{
unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0;
static const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 };
- long timeout;
+ long time_left;
pr_debug("%s", __func__);
@@ -208,11 +208,11 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
return -EIO;
}
- timeout = wait_for_completion_interruptible_timeout(
+ time_left = wait_for_completion_interruptible_timeout(
&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME));
- if (timeout <= 0) {
+ if (time_left <= 0) {
pr_err(" waiting for ver info- timed out or received signal");
- return timeout ? -ERESTARTSYS : -ETIMEDOUT;
+ return time_left ? -ERESTARTSYS : -ETIMEDOUT;
}
reinit_completion(&kim_gdata->kim_rcvd);
/*
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 7dd86a9858ab..1d54680d6ed2 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -229,7 +229,7 @@ static int __maybe_unused tifm_7xx1_resume(struct device *dev_d)
struct pci_dev *dev = to_pci_dev(dev_d);
struct tifm_adapter *fm = pci_get_drvdata(dev);
int rc;
- unsigned long timeout;
+ unsigned long time_left;
unsigned int good_sockets = 0, bad_sockets = 0;
unsigned long flags;
/* Maximum number of entries is 4 */
@@ -265,8 +265,8 @@ static int __maybe_unused tifm_7xx1_resume(struct device *dev_d)
if (good_sockets) {
fm->finish_me = &finish_resume;
spin_unlock_irqrestore(&fm->lock, flags);
- timeout = wait_for_completion_timeout(&finish_resume, HZ);
- dev_dbg(&dev->dev, "wait returned %lu\n", timeout);
+ time_left = wait_for_completion_timeout(&finish_resume, HZ);
+ dev_dbg(&dev->dev, "wait returned %lu\n", time_left);
writel(TIFM_IRQ_FIFOMASK(good_sockets)
| TIFM_IRQ_CARDMASK(good_sockets),
fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
index a3bc2823143e..2ad4387c9837 100644
--- a/drivers/misc/tsl2550.c
+++ b/drivers/misc/tsl2550.c
@@ -420,7 +420,7 @@ static SIMPLE_DEV_PM_OPS(tsl2550_pm_ops, tsl2550_suspend, tsl2550_resume);
#endif /* CONFIG_PM_SLEEP */
static const struct i2c_device_id tsl2550_id[] = {
- { "tsl2550", 0 },
+ { "tsl2550" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tsl2550_id);
diff --git a/drivers/misc/vcpu_stall_detector.c b/drivers/misc/vcpu_stall_detector.c
index e2015c87f03f..41b8c2119e20 100644
--- a/drivers/misc/vcpu_stall_detector.c
+++ b/drivers/misc/vcpu_stall_detector.c
@@ -32,6 +32,7 @@
struct vcpu_stall_detect_config {
u32 clock_freq_hz;
u32 stall_timeout_sec;
+ int ppi_irq;
void __iomem *membase;
struct platform_device *dev;
@@ -77,6 +78,12 @@ vcpu_stall_detect_timer_fn(struct hrtimer *hrtimer)
return HRTIMER_RESTART;
}
+static irqreturn_t vcpu_stall_detector_irq(int irq, void *dev)
+{
+ panic("vCPU stall detector");
+ return IRQ_HANDLED;
+}
+
static int start_stall_detector_cpu(unsigned int cpu)
{
u32 ticks, ping_timeout_ms;
@@ -132,7 +139,7 @@ static int stop_stall_detector_cpu(unsigned int cpu)
static int vcpu_stall_detect_probe(struct platform_device *pdev)
{
- int ret;
+ int ret, irq;
struct resource *r;
void __iomem *membase;
u32 clock_freq_hz = VCPU_STALL_DEFAULT_CLOCK_HZ;
@@ -169,9 +176,22 @@ static int vcpu_stall_detect_probe(struct platform_device *pdev)
vcpu_stall_config = (struct vcpu_stall_detect_config) {
.membase = membase,
.clock_freq_hz = clock_freq_hz,
- .stall_timeout_sec = stall_timeout_sec
+ .stall_timeout_sec = stall_timeout_sec,
+ .ppi_irq = -1,
};
+ irq = platform_get_irq_optional(pdev, 0);
+ if (irq > 0) {
+ ret = request_percpu_irq(irq,
+ vcpu_stall_detector_irq,
+ "vcpu_stall_detector",
+ vcpu_stall_detectors);
+ if (ret)
+ goto err;
+
+ vcpu_stall_config.ppi_irq = irq;
+ }
+
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"virt/vcpu_stall_detector:online",
start_stall_detector_cpu,
@@ -184,6 +204,9 @@ static int vcpu_stall_detect_probe(struct platform_device *pdev)
vcpu_stall_config.hp_online = ret;
return 0;
err:
+ if (vcpu_stall_config.ppi_irq > 0)
+ free_percpu_irq(vcpu_stall_config.ppi_irq,
+ vcpu_stall_detectors);
return ret;
}
@@ -193,6 +216,10 @@ static void vcpu_stall_detect_remove(struct platform_device *pdev)
cpuhp_remove_state(vcpu_stall_config.hp_online);
+ if (vcpu_stall_config.ppi_irq > 0)
+ free_percpu_irq(vcpu_stall_config.ppi_irq,
+ vcpu_stall_detectors);
+
for_each_possible_cpu(cpu)
stop_stall_detector_cpu(cpu);
}