Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH 3/8] Add Advantech EIO Hardware Monitor driver
From: Ramiro Oliveira @ 2025-12-12 16:40 UTC (permalink / raw)
  To: Lee Jones, Linus Walleij, Bartosz Golaszewski, Guenter Roeck,
	Andi Shyti, Daniel Thompson, Jingoo Han, Helge Deller,
	Wim Van Sebroeck, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
	Lukasz Luba
  Cc: linux-kernel, linux-gpio, linux-hwmon, linux-i2c, dri-devel,
	linux-fbdev, linux-watchdog, linux-pm, Wenkai Chung,
	Francisco Aragon-Trivino, Hongzhi Wang, Mikhail Tsukerman,
	Thomas Kastner, Ramiro Oliveira
In-Reply-To: <20251212-upstream-v1-v1-0-d50d40ec8d8a@advantech.com>

This driver controls the Hardware Monitor block of the Advantech EIO chip.

Signed-off-by: Ramiro Oliveira <ramiro.oliveira@advantech.com>
---
 MAINTAINERS               |   1 +
 drivers/hwmon/Kconfig     |  10 ++
 drivers/hwmon/Makefile    |   1 +
 drivers/hwmon/eio-hwmon.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 356 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 359d4a13f212..fdd39b152f41 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -620,6 +620,7 @@ ADVANTECH EIO DRIVER
 M:	Ramiro Oliveira <ramiro.oliveira@advantech.com>
 S:	Maintained
 F:	drivers/gpio/gpio-eio.c
+F:	drivers/hwmon/eio-hwmon.c
 F:	drivers/mfd/eio_core.c
 F:	include/linux/mfd/eio.h
 
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 157678b821fc..08993b993596 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -2043,6 +2043,16 @@ config SENSORS_DME1737
 	  This driver can also be built as a module. If so, the module
 	  will be called dme1737.
 
+config SENSORS_EIO
+	tristate "Advantech EIO HWMON"
+	depends on MFD_EIO
+	help
+	  If you say yes here you get support for the Advantech EIO
+	  temperature, voltage and fan speed monitoring block.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called eio-hwmon
+
 config SENSORS_EMC1403
 	tristate "SMSC EMC1403/23 thermal sensor"
 	depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index eade8e3b1bde..e69f03b41fae 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
 obj-$(CONFIG_SENSORS_DRIVETEMP)	+= drivetemp.o
 obj-$(CONFIG_SENSORS_DS620)	+= ds620.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
+obj-$(CONFIG_SENSORS_EIO)	+= eio-hwmon.o
 obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
 obj-$(CONFIG_SENSORS_EMC2103)	+= emc2103.o
 obj-$(CONFIG_SENSORS_EMC2305)	+= emc2305.o
diff --git a/drivers/hwmon/eio-hwmon.c b/drivers/hwmon/eio-hwmon.c
new file mode 100644
index 000000000000..164591aa31a7
--- /dev/null
+++ b/drivers/hwmon/eio-hwmon.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * GPIO driver for Advantech EIO embedded controller.
+ *
+ * Copyright (C) 2025 Advantech Corporation. All rights reserved.
+ */
+
+#include <linux/errno.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/eio.h>
+#include <linux/module.h>
+
+#define MAX_DEV 128
+#define MAX_NAME 32
+
+static uint timeout;
+module_param(timeout, uint, 0444);
+MODULE_PARM_DESC(timeout,
+		 "Default pmc command timeout in micro-seconds.\n");
+
+struct eio_hwmon_dev {
+	struct device *mfd;
+};
+
+enum _sen_type {
+	NONE,
+	VOLTAGE,
+	CURRENT,
+	TEMP,
+	PWM,
+	TACHO,
+	FAN,
+	CASEOPEN,
+};
+
+struct eio_key {
+	enum _sen_type type;
+	u8 chan;
+	u8 item;
+	u8 label_idx;
+};
+
+struct eio_attr {
+	struct sensor_device_attribute sda;
+	struct eio_key key;
+};
+
+static struct {
+	u8   cmd;
+	u8   max;
+	signed int shift;
+	char name[32];
+	u8   ctrl[16];
+	u16  multi[16];
+	char item[16][32];
+	char labels[32][32];
+
+} sen_info[] = {
+	{ 0x00, 0, 0, "none" },
+	{ 0x12, 8, 0, "in",
+		{ 0xFF, 0x10, 0x11, 0x12 },
+		{ 1,    10,   10,   10 },
+		{ "label", "input", "max", "min" },
+		{ "5V", "5Vs5", "12V", "12Vs5",
+		  "3V3", "3V3", "5Vsb", "3Vsb",
+		  "Vcmos", "Vbat", "Vdc", "Vstb",
+		  "Vcore_a", "Vcore_b", "", "",
+		  "Voem0", "Voem1", "Voem2", "Voem3"
+		},
+	},
+	{ 0x1a, 2, 0, "curr",
+		{ 0xFF, 0x10, 0x11, 0x12 },
+		{ 1,    10,   10,   10 },
+		{ "label", "input", "max", "min" },
+		{ "dc", "oem0" },
+	},
+	{ 0x10, 4, -2731, "temp",
+		{ 0xFF, 0x10, 0x11, 0x12, 0x21, 0x41 },
+		{ 1,    100,  100,  100,  100,  100 },
+		{ "label", "input", "max", "min", "crit", "emergency" },
+		{ "cpu0", "cpu1", "cpu2", "cpu3",
+		  "sys0", "sys1", "sys2", "sys3",
+		  "aux0", "aux1", "aux2", "aux3",
+		  "dimm0", "dimm1", "dimm2", "dimm3",
+		  "pch", "gpu", "", "",
+		  "", "", "", "",
+		  "", "", "", "",
+		  "oem0", "oem1", "oem", "oem3" },
+	},
+	{ 0x14, 0, 0, "pwm",
+		{ 0xFF, 0x11, 0x12 },
+		{ 1, 1, 1 },
+		{ "label", "polarity", "freq" },
+		{ "pwm0", "pwm0", "pwm0", "pwm0" },
+	},
+	{ 0x16, 2, 0, "tacho",
+		{ 0xFF, 0x10 },
+		{ 1, 1 },
+		{ "label", "input"},
+		{ "cpu0", "cpu1", "cpu2", "cpu3",
+		  "sys0", "sys1", "sys2", "sys3",
+		  "", "", "", "", "", "", "", "",
+		  "", "", "", "", "", "", "", "",
+		  "", "", "", "",
+		  "oem0", "oem1", "oem2", "oem3"
+		},
+	},
+	{ 0x24, 4, 0, "fan",
+		{ 0xFF, 0x1A },
+		{ 1, 1 },
+		{ "label", "input"},
+		{ "cpu0", "cpu1", "cpu2", "cpu3",
+		  "sys0", "sys1", "sys2", "sys3",
+		  "", "", "", "", "", "", "", "",
+		  "", "", "", "", "", "", "", "",
+		  "", "", "", "",
+		  "oem0", "oem1", "oem2", "oem3",
+		},
+	},
+	{ 0x28, 1, 0, "intrusion",
+		{ 0xFF, 0x02 },
+		{ 1, 1 },
+		{ "label", "input" },
+		{ "case_open" }
+	}
+};
+
+static struct {
+	enum _sen_type type;
+	u8   ctrl;
+	int  size;
+	bool write;
+
+} ctrl_para[] = {
+	{ NONE,     0x00, 0, false },
+
+	{ VOLTAGE,  0x00, 1, false }, { VOLTAGE,  0x01, 1, false },
+	{ VOLTAGE,  0x10, 2, false }, { VOLTAGE,  0x11, 2, false },
+	{ VOLTAGE,  0x12, 2, false },
+
+	{ CURRENT,  0x00, 1, false }, { CURRENT,  0x01, 1, false },
+	{ CURRENT,  0x10, 2, false }, { CURRENT,  0x11, 2, false },
+	{ CURRENT,  0x12, 2, false },
+
+	{ TEMP,	    0x00, 2, false }, { TEMP,	  0x01, 1, false },
+	{ TEMP,     0x04, 1, false }, { TEMP,	  0x10, 2, false },
+	{ TEMP,     0x11, 2, false }, { TEMP,	  0x12, 2, false },
+	{ TEMP,     0x21, 2, false }, { TEMP,	  0x41, 2, false },
+
+	{ PWM,      0x00, 1, false }, { PWM,	  0x10, 1, true  },
+	{ PWM,      0x11, 1, true  }, { PWM,	  0x12, 4, true  },
+
+	{ TACHO,    0x00, 1, false }, { TACHO,	  0x01, 1, false },
+	{ TACHO,    0x10, 4, true  },
+
+	{ FAN,      0x00, 1, false }, { FAN,	  0x01, 1, false },
+	{ FAN,      0x03, 1, true  }, { FAN,	  0x1A, 2, false },
+
+	{ CASEOPEN, 0x00, 1, false }, { CASEOPEN, 0x02, 1, true  },
+};
+
+static int para_idx(enum _sen_type type, u8 ctrl)
+{
+	int i;
+
+	for (i = 1 ; i < ARRAY_SIZE(ctrl_para) ; i++)
+		if (type == ctrl_para[i].type &&
+		    ctrl == ctrl_para[i].ctrl)
+			return i;
+
+	return 0;
+}
+
+static int pmc_read(struct device *mfd, enum _sen_type type, u8 dev_id, u8 ctrl, void *data)
+{
+	int idx = para_idx(type, ctrl);
+	int ret = 0;
+
+	if (idx == 0)
+		return -EINVAL;
+
+	if (WARN_ON(!data))
+		return -EINVAL;
+
+	struct pmc_op op = {
+		 .cmd       = sen_info[type].cmd | EIO_FLAG_PMC_READ,
+		 .control   = ctrl,
+		 .device_id = dev_id,
+		 .size	    = ctrl_para[idx].size,
+		 .payload   = (u8 *)data,
+		 .timeout   = timeout,
+	};
+
+	ret = eio_core_pmc_operation(mfd, &op);
+	return ret;
+}
+
+static ssize_t eio_show(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct eio_hwmon_dev *eio_hwmon = dev_get_drvdata(dev);
+	struct eio_attr *eio_attr =
+		container_of(attr, struct eio_attr, sda.dev_attr);
+	const struct eio_key *eio_key = &eio_attr->key;
+	int ret;
+	u8 data[2];
+	u32 temp_val;
+	signed int final_val;
+
+	switch (eio_key->item) {
+	case 0:
+		return sysfs_emit(buf, "%s\n",
+				  sen_info[eio_key->type].labels[eio_key->label_idx]);
+
+	default:
+		ret = pmc_read(eio_hwmon->mfd, eio_key->type, eio_key->chan,
+			       sen_info[eio_key->type].ctrl[eio_key->item],
+			       &data);
+		if (ret)
+			return ret;
+
+		temp_val = data[0] | data[1] << 8;
+
+		final_val = (signed int)temp_val + (signed int)(sen_info[eio_key->type].shift);
+		final_val = final_val * (signed int)sen_info[eio_key->type].multi[eio_key->item];
+
+		return sysfs_emit(buf, "%d\n", final_val);
+	}
+
+	return -EINVAL;
+}
+
+static char devname[MAX_DEV][MAX_NAME];
+static struct eio_attr devattrs[MAX_DEV];
+static struct attribute *attrs[MAX_DEV];
+
+static struct attribute_group group = {
+	.attrs = attrs,
+};
+
+static const struct attribute_group *groups[] = {
+	&group,
+	NULL
+};
+
+static int hwmon_init(struct device *mfd, struct eio_hwmon_dev *eio_hwmon)
+{
+	enum _sen_type type;
+	u8 i, j, data[16];
+	int sum = 0;
+	int ret;
+
+	for (type = VOLTAGE ; type <= CASEOPEN ; type++) {
+		int cnt = 1;
+
+		for (i = 0 ; i < sen_info[type].max ; i++) {
+			if (pmc_read(mfd, type, i, 0x00, data) ||
+			    (data[0] & 0x01) == 0)
+				continue;
+
+			memset(data, 0, sizeof(data));
+			ret = pmc_read(mfd, type, i, 0x01, data);
+			if (ret != 0 && ret != -EINVAL) {
+				dev_info(mfd, "read type id error\n");
+				continue;
+			}
+
+			for (j = 0 ; j < ARRAY_SIZE(sen_info->item) ; j++) {
+				struct eio_attr *eio_attr;
+
+				if (sen_info[type].item[j][0] == 0)
+					continue;
+
+				eio_attr = &devattrs[sum];
+
+				eio_attr->key.type      = type;
+				eio_attr->key.chan      = i;
+				eio_attr->key.item      = j;
+				eio_attr->key.label_idx = data[0];
+
+				snprintf(devname[sum], sizeof(devname[sum]),
+					 "%s%d_%s", sen_info[type].name, cnt,
+					 sen_info[type].item[j]);
+
+				eio_attr->sda.dev_attr.attr.name = devname[sum];
+				eio_attr->sda.dev_attr.attr.mode = 0444;
+				eio_attr->sda.dev_attr.show      = eio_show;
+
+				attrs[sum] = &eio_attr->sda.dev_attr.attr;
+
+				if (++sum >= MAX_DEV)
+					break;
+			}
+			cnt++;
+		}
+	}
+
+	return sum;
+}
+
+static int hwmon_probe(struct platform_device *pdev)
+{
+	struct device *dev =  &pdev->dev;
+	struct eio_hwmon_dev *eio_hwmon;
+	struct eio_dev *eio_dev = dev_get_drvdata(dev->parent);
+	struct device *hwmon;
+
+	if (!eio_dev) {
+		dev_err(dev, "Error contact eio_core\n");
+		return -ENODEV;
+	}
+
+	eio_hwmon = devm_kzalloc(dev, sizeof(*eio_hwmon), GFP_KERNEL);
+	if (!eio_hwmon)
+		return -ENOMEM;
+
+	eio_hwmon->mfd = dev->parent;
+	platform_set_drvdata(pdev, eio_hwmon);
+
+	if (hwmon_init(dev->parent, eio_hwmon) <= 0)
+		return -ENODEV;
+
+	hwmon =	devm_hwmon_device_register_with_groups(dev, KBUILD_MODNAME,
+						       eio_hwmon,
+						       groups);
+	return PTR_ERR_OR_ZERO(hwmon);
+}
+
+static struct platform_driver eio_hwmon_driver = {
+	.probe  = hwmon_probe,
+	.driver = {
+		.name = "eio_hwmon",
+	},
+};
+
+module_platform_driver(eio_hwmon_driver);
+
+MODULE_AUTHOR("Wenkai Chung <wenkai.chung@advantech.com.tw>");
+MODULE_AUTHOR("Ramiro Oliveira <ramiro.oliveira@advantech.com>");
+MODULE_DESCRIPTION("Hardware monitor driver for Advantech EIO embedded controller");
+MODULE_LICENSE("GPL");
+

-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/8] Add Advantech EIO GPIO driver
From: Ramiro Oliveira @ 2025-12-12 16:40 UTC (permalink / raw)
  To: Lee Jones, Linus Walleij, Bartosz Golaszewski, Guenter Roeck,
	Andi Shyti, Daniel Thompson, Jingoo Han, Helge Deller,
	Wim Van Sebroeck, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
	Lukasz Luba
  Cc: linux-kernel, linux-gpio, linux-hwmon, linux-i2c, dri-devel,
	linux-fbdev, linux-watchdog, linux-pm, Wenkai Chung,
	Francisco Aragon-Trivino, Hongzhi Wang, Mikhail Tsukerman,
	Thomas Kastner, Ramiro Oliveira
In-Reply-To: <20251212-upstream-v1-v1-0-d50d40ec8d8a@advantech.com>

This driver controls the GPIO component of the Advantech EIO chip.

Signed-off-by: Ramiro Oliveira <ramiro.oliveira@advantech.com>
---
 MAINTAINERS             |   1 +
 drivers/gpio/Kconfig    |   6 ++
 drivers/gpio/Makefile   |   1 +
 drivers/gpio/gpio-eio.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 281 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index bd9279796c2f..359d4a13f212 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -619,6 +619,7 @@ F:	drivers/platform/x86/adv_swbutton.c
 ADVANTECH EIO DRIVER
 M:	Ramiro Oliveira <ramiro.oliveira@advantech.com>
 S:	Maintained
+F:	drivers/gpio/gpio-eio.c
 F:	drivers/mfd/eio_core.c
 F:	include/linux/mfd/eio.h
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index bd185482a7fd..628a914842bd 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -277,6 +277,12 @@ config GPIO_DWAPB
 	  Say Y or M here to build support for the Synopsys DesignWare APB
 	  GPIO block.
 
+config GPIO_EIO
+	tristate "Advantech EIO GPIO"
+	depends on MFD_EIO
+	help
+	  Say Y or M to build support for Advantech EIO GPIO block.
+
 config GPIO_EIC_SPRD
 	tristate "Spreadtrum EIC support"
 	depends on ARCH_SPRD || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 2421a8fd3733..ba3883d5e4a0 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_GPIO_DLN2)			+= gpio-dln2.o
 obj-$(CONFIG_GPIO_DS4520)		+= gpio-ds4520.o
 obj-$(CONFIG_GPIO_DWAPB)		+= gpio-dwapb.o
 obj-$(CONFIG_GPIO_EIC_SPRD)		+= gpio-eic-sprd.o
+obj-$(CONFIG_GPIO_EIO)			+= gpio-eio.o
 obj-$(CONFIG_GPIO_ELKHARTLAKE)		+= gpio-elkhartlake.o
 obj-$(CONFIG_GPIO_EM)			+= gpio-em.o
 obj-$(CONFIG_GPIO_EN7523)		+= gpio-en7523.o
diff --git a/drivers/gpio/gpio-eio.c b/drivers/gpio/gpio-eio.c
new file mode 100644
index 000000000000..50f66a325e8f
--- /dev/null
+++ b/drivers/gpio/gpio-eio.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * GPIO driver for Advantech EIO Embedded controller.
+ *
+ * Copyright (C) 2025 Advantech Corporation. All rights reserved.
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/eio.h>
+#include <linux/module.h>
+
+#define GPIO_MAX_PINS	48
+#define GPIO_WRITE	0x18
+#define GPIO_READ	0x19
+
+struct eio_gpio_dev {
+	u64 avail;
+	int max;
+	struct gpio_chip chip;
+	struct device *dev;
+};
+
+struct {
+	int size;
+	bool write;
+} ctrl_para[] = {
+	{ 0x01, false }, { 0x00, false }, { 0x00, false }, { 0x02, false },
+	{ 0x01, false }, { 0x00, false }, { 0x00, false }, { 0x00, false },
+	{ 0x00, false }, { 0x00, false }, { 0x00, false }, { 0x00, false },
+	{ 0x00, false }, { 0x00, false }, { 0x00, false }, { 0x00, false },
+	{ 0x01, true  }, { 0x01, true  }, { 0x02, true  }, { 0x02, true  },
+	{ 0x02, false }, { 0x10, false }
+};
+
+enum {
+	GPIO_STATUS	 = 0,
+	GPIO_GROUP_AVAIL = 3,
+	GPIO_ERROR	 = 0x04,
+	GPIO_PIN_DIR	 = 0x10,
+	GPIO_PIN_LEVEL	 = 0x11,
+	GPIO_GROUP_DIR	 = 0x12,
+	GPIO_GROUP_LEVEL = 0x13,
+	GPIO_MAPPING	 = 0x14,
+	GPIO_NAME	 = 0x15
+} gpio_ctrl;
+
+struct {
+	int group;
+	int port;
+} group_map[] = {
+	{ 0, 0 }, { 0, 1 },
+	{ 1, 0 }, { 1, 1 },
+	{ 2, 0 }, { 2, 1 },
+	{ 3, 0 }, { 3, 1 },
+	{ 3, 2 }, { 3, 3 },
+	{ 3, 4 }, { 3, 5 },
+	{ 3, 6 }, { 3, 7 }
+};
+
+static int timeout;
+module_param(timeout, int, 0444);
+MODULE_PARM_DESC(timeout, "Set PMC command timeout value.\n");
+
+static int pmc_write(struct device *mfd_dev, u8 ctrl, u8 dev_id, void *data)
+{
+	struct pmc_op op = {
+		 .cmd       = GPIO_WRITE,
+		 .control   = ctrl,
+		 .device_id = dev_id,
+		 .payload   = (u8 *)data,
+		 .timeout   = timeout,
+	};
+
+	if (ctrl > ARRAY_SIZE(ctrl_para))
+		return -ENOMEM;
+
+	if (!ctrl_para[ctrl].write)
+		return -EINVAL;
+
+	op.size = ctrl_para[ctrl].size;
+
+	return eio_core_pmc_operation(mfd_dev, &op);
+}
+
+static int pmc_read(struct device *mfd_dev, u8 ctrl, u8 dev_id, void *data)
+{
+	struct pmc_op op = {
+		 .cmd       = GPIO_READ,
+		 .control   = ctrl,
+		 .device_id = dev_id,
+		 .payload   = (u8 *)data,
+		 .timeout   = timeout,
+	};
+
+	if (ctrl > ARRAY_SIZE(ctrl_para))
+		return -ENOMEM;
+
+	op.size = ctrl_para[ctrl].size;
+
+	return eio_core_pmc_operation(mfd_dev, &op);
+}
+
+static int get_dir(struct gpio_chip *chip, unsigned int offset)
+{
+	u8 dir;
+	int ret;
+
+	ret = pmc_read(chip->parent, GPIO_PIN_DIR, offset, &dir);
+	if (ret)
+		return ret;
+
+	return dir ? 0 : 1;
+}
+
+static int dir_input(struct gpio_chip *chip, unsigned int offset)
+{
+	u8 dir = 0;
+
+	return pmc_write(chip->parent, GPIO_PIN_DIR, offset, &dir);
+}
+
+static int dir_output(struct gpio_chip *chip, unsigned int offset, int value)
+{
+	u8 dir = 1;
+	u8 val = value;
+
+	pmc_write(chip->parent, GPIO_PIN_DIR, offset, &dir);
+
+	return pmc_write(chip->parent, GPIO_PIN_LEVEL, offset, &val);
+}
+
+static int gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	u8 level;
+	int ret;
+
+	ret = pmc_read(chip->parent, GPIO_PIN_LEVEL, offset, &level);
+	if (ret)
+		return ret;
+
+	return level;
+}
+
+static int gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+	u8 val = value;
+
+	pmc_write(chip->parent, GPIO_PIN_LEVEL, offset, &val);
+
+	return 0;
+}
+
+static int check_support(struct device *dev)
+{
+	u8  data;
+	int ret;
+
+	ret = pmc_read(dev, GPIO_STATUS, 0, &data);
+	if (!ret)
+		return ret;
+
+	if ((data & 0x01) == 0)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+static int check_pin(struct device *dev, int pin)
+{
+	int ret;
+	int group, bit;
+	u16 data;
+
+	/* Get pin mapping */
+	ret = pmc_read(dev, GPIO_MAPPING, pin, &data);
+	if (ret)
+		return ret;
+
+	if ((data & 0xFF) > ARRAY_SIZE(group_map))
+		return -EINVAL;
+
+	group = group_map[data & 0xFF].group;
+	bit   = data >> 8;
+
+	/* Check mapped pin */
+	ret = pmc_read(dev, GPIO_GROUP_AVAIL, group, &data);
+	if (ret)
+		return ret;
+
+	return data & BIT(bit) ? 0 : -EOPNOTSUPP;
+}
+
+static int gpio_init(struct device *mfd, struct eio_gpio_dev *eio_gpio)
+{
+	int ret;
+	int i;
+	char str[GPIO_MAX_PINS + 1];
+
+	memset(str, 0x30, sizeof(str));
+
+	ret = check_support(mfd);
+	if (ret) {
+		dev_err(eio_gpio->dev, "GPIO not supported (%d)\n", ret);
+		return ret;
+	}
+
+	eio_gpio->avail = 0;
+
+	for (i = 0 ; i <  GPIO_MAX_PINS ; i++) {
+		ret = check_pin(mfd, i);
+		if (ret)
+			continue;
+
+		eio_gpio->avail |= BIT(i);
+		eio_gpio->max = i + 1;
+		str[GPIO_MAX_PINS - i] = '1';
+	}
+
+	dev_info(eio_gpio->dev, "GPIO pins=%s\n", str);
+
+	return eio_gpio->max ? 0 : -EOPNOTSUPP;
+}
+
+static const struct gpio_chip eio_gpio_chip = {
+	.label		  = KBUILD_MODNAME,
+	.owner		  = THIS_MODULE,
+	.direction_input  = dir_input,
+	.get		  = gpio_get,
+	.direction_output = dir_output,
+	.set		  = gpio_set,
+	.get_direction	  = get_dir,
+	.base		  = -1,
+	.can_sleep	  = true,
+};
+
+static int gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev =  &pdev->dev;
+	struct eio_gpio_dev *eio_gpio;
+	struct eio_dev *eio_dev = dev_get_drvdata(dev->parent);
+
+	if (!eio_dev) {
+		dev_err(dev, "Error contact eio_core\n");
+		return -ENODEV;
+	}
+
+	eio_gpio = devm_kzalloc(dev, sizeof(*eio_gpio), GFP_KERNEL);
+	eio_gpio->dev = dev;
+
+	if (gpio_init(dev->parent, eio_gpio))
+		return -EIO;
+
+	eio_gpio->chip	   = eio_gpio_chip;
+	eio_gpio->chip.parent = dev->parent;
+	eio_gpio->chip.ngpio  = eio_gpio->max;
+
+	return devm_gpiochip_add_data(dev, &eio_gpio->chip, eio_gpio);
+}
+
+static struct platform_driver gpio_driver = {
+	.probe  = gpio_probe,
+	.driver = { .name = KBUILD_MODNAME, },
+};
+
+module_platform_driver(gpio_driver);
+
+MODULE_AUTHOR("Wenkai Chung <wenkai.chung@advantech.com.tw>");
+MODULE_AUTHOR("Ramiro Oliveira <ramiro.oliveira@advantech.com>");
+MODULE_DESCRIPTION("GPIO driver for Advantech EIO embedded controller");
+MODULE_LICENSE("GPL");

-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/8] Add Advantech EIO MFD driver
From: Ramiro Oliveira @ 2025-12-12 16:40 UTC (permalink / raw)
  To: Lee Jones, Linus Walleij, Bartosz Golaszewski, Guenter Roeck,
	Andi Shyti, Daniel Thompson, Jingoo Han, Helge Deller,
	Wim Van Sebroeck, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
	Lukasz Luba
  Cc: linux-kernel, linux-gpio, linux-hwmon, linux-i2c, dri-devel,
	linux-fbdev, linux-watchdog, linux-pm, Wenkai Chung,
	Francisco Aragon-Trivino, Hongzhi Wang, Mikhail Tsukerman,
	Thomas Kastner, Ramiro Oliveira
In-Reply-To: <20251212-upstream-v1-v1-0-d50d40ec8d8a@advantech.com>

Creating the MFD core driver for Advantech EIO, all other drivers (GPIO,
I2C, etc) depend on this core driver.

Signed-off-by: Ramiro Oliveira <ramiro.oliveira@advantech.com>
---
 MAINTAINERS             |   6 +
 drivers/mfd/Kconfig     |  10 +
 drivers/mfd/Makefile    |   1 +
 drivers/mfd/eio_core.c  | 621 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/eio.h | 127 ++++++++++
 5 files changed, 765 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 663e86eb9ff1..bd9279796c2f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -616,6 +616,12 @@ L:	platform-driver-x86@vger.kernel.org
 S:	Maintained
 F:	drivers/platform/x86/adv_swbutton.c
 
+ADVANTECH EIO DRIVER
+M:	Ramiro Oliveira <ramiro.oliveira@advantech.com>
+S:	Maintained
+F:	drivers/mfd/eio_core.c
+F:	include/linux/mfd/eio.h
+
 ADXL313 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
 M:	Lucas Stankus <lucas.p.stankus@gmail.com>
 S:	Supported
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index aace5766b38a..02a0b324eb6a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -506,6 +506,16 @@ config MFD_DLN2
 	  etc. must be enabled in order to use the functionality of
 	  the device.
 
+config MFD_EIO
+	tristate "Advantech EIO MFD core"
+	select MFD_CORE
+	help
+	  This enables support for the Advantech EIO multi-function device.
+	  This core driver provides register access and coordination for the
+	  EIO's subdevices (GPIO, watchdog, hwmon, thermal, backlight, I2C).
+	  This driver supports EIO-IS200, EIO-201, EIO-210 and EIO-211.
+
+
 config MFD_ENE_KB3930
 	tristate "ENE KB3930 Embedded Controller support"
 	depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e75e8045c28a..f8c53b55b679 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_MFD_CROS_EC_DEV)	+= cros_ec_dev.o
 obj-$(CONFIG_MFD_CS42L43)	+= cs42l43.o
 obj-$(CONFIG_MFD_CS42L43_I2C)	+= cs42l43-i2c.o
 obj-$(CONFIG_MFD_CS42L43_SDW)	+= cs42l43-sdw.o
+obj-$(CONFIG_MFD_EIO)		+= eio_core.o
 obj-$(CONFIG_MFD_ENE_KB3930)	+= ene-kb3930.o
 obj-$(CONFIG_MFD_EXYNOS_LPASS)	+= exynos-lpass.o
 obj-$(CONFIG_MFD_GATEWORKS_GSC)	+= gateworks-gsc.o
diff --git a/drivers/mfd/eio_core.c b/drivers/mfd/eio_core.c
new file mode 100644
index 000000000000..7a58c62595a5
--- /dev/null
+++ b/drivers/mfd/eio_core.c
@@ -0,0 +1,621 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Advantech Embedded Controller base Driver
+ *
+ * This driver provides an interface to access the EIO Series EC
+ * firmware via its own Power Management Channel (PMC) for subdrivers:
+ *
+ * A system may have one or two independent EIO devices.
+ *
+ * Copyright (C) 2025 Advantech Co., Ltd.
+ */
+
+#include <linux/delay.h>
+#include <linux/isa.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/sysfs.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+#include <linux/mfd/eio.h>
+
+#define TIMEOUT_MAX (10 * USEC_PER_SEC)
+#define TIMEOUT_MIN 200
+#define SLEEP_MAX 200
+#define DEFAULT_TIMEOUT 5000
+
+/**
+ * Timeout: Default timeout in microseconds when a PMC command's
+ * timeout is unspecified. PMC command responses typically range
+ * from 200us to 2ms. 5ms is quite a safe value for timeout. In
+ * In some cases, responses are longer. In such situations, please
+ * adding the timeout parameter loading related sub-drivers or
+ * this core driver (not recommended).
+ */
+static uint timeout = DEFAULT_TIMEOUT;
+module_param(timeout, uint, 0444);
+MODULE_PARM_DESC(timeout, "Default PMC command timeout in usec.\n");
+
+struct eio_dev_port {
+	u16 idx_port;
+	u16 data_port;
+};
+
+static struct eio_dev_port pnp_port[] = {
+	{ .idx_port = EIO_PNP_INDEX, .data_port = EIO_PNP_DATA },
+	{ .idx_port = EIO_SUB_PNP_INDEX,
+	  .data_port = EIO_SUB_PNP_DATA },
+};
+
+static struct mfd_cell mfd_devs[] = {
+	{ .name = "eio_wdt" },
+	{ .name = "gpio_eio" },
+	{ .name = "eio_hwmon" },
+	{ .name = "i2c_eio" },
+	{ .name = "eio_thermal" },
+	{ .name = "eio_fan" },
+	{ .name = "eio_bl" },
+};
+
+static const struct regmap_range eio_range[] = {
+	regmap_reg_range(EIO_PNP_INDEX, EIO_PNP_DATA),
+	regmap_reg_range(EIO_SUB_PNP_INDEX, EIO_SUB_PNP_DATA),
+	regmap_reg_range(0x200, 0x3FF),
+};
+
+static const struct regmap_access_table volatile_regs = {
+	.yes_ranges = eio_range,
+	.n_yes_ranges = ARRAY_SIZE(eio_range),
+};
+
+static const struct regmap_config pnp_regmap_config = {
+	.name = "eio_core",
+	.reg_bits = 16,
+	.val_bits = 8,
+	.volatile_table = &volatile_regs,
+	.io_port = true,
+	.cache_type = REGCACHE_NONE,
+};
+
+static struct {
+	char name[32];
+	int cmd;
+	int ctrl;
+	int dev;
+	int size;
+	enum {
+		HEX,
+		NUMBER,
+		PNP_ID,
+	} type;
+
+} attrs[] = {
+	{ "board_name", 0x53, 0x10, 0, 16 },
+	{ "board_serial", 0x53, 0x1F, 0, 16 },
+	{ "board_manufacturer", 0x53, 0x11, 0, 16 },
+	{ "board_id", 0x53, 0x1E, 0, 4 },
+	{ "firmware_version", 0x53, 0x21, 0, 4 },
+	{ "firmware_name", 0x53, 0x22, 0, 16 },
+	{ "firmware_build", 0x53, 0x23, 0, 26 },
+	{ "firmware_date", 0x53, 0x24, 0, 16 },
+	{ "chip_id", 0x53, 0x12, 0, 12 },
+	{ "chip_detect", 0x53, 0x15, 0, 12 },
+	{ "platform_type", 0x53, 0x13, 0, 16 },
+	{ "platform_revision", 0x53, 0x04, 0x44, 4 },
+	{ "eapi_version", 0x53, 0x04, 0x64, 4 },
+	{ "eapi_id", 0x53, 0x31, 0, 4 },
+	{ "boot_count", 0x55, 0x10, 0, 4, NUMBER },
+	{ "powerup_hour", 0x55, 0x11, 0, 4, NUMBER },
+	{ "pnp_id", 0x53, 0x04, 0x68, 4, PNP_ID },
+};
+
+static ssize_t info_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	uint i;
+
+	for (i = 0; i < ARRAY_SIZE(attrs); i++) {
+		int ret;
+		char str[32] = "";
+		int val;
+
+		struct pmc_op op = {
+			.cmd = attrs[i].cmd,
+			.control = attrs[i].ctrl,
+			.device_id = attrs[i].dev,
+			.payload = (u8 *)str,
+			.size = attrs[i].size,
+		};
+
+		if (strcmp(attr->attr.name, attrs[i].name))
+			continue;
+
+		ret = eio_core_pmc_operation(dev, &op);
+		if (ret)
+			return ret;
+
+		if (attrs[i].size != 4)
+			return sprintf(buf, "%s\n", str);
+
+		val = *(u32 *)str;
+
+		if (attrs[i].type == HEX)
+			return sprintf(buf, "0x%08X\n", val);
+
+		if (attrs[i].type == NUMBER)
+			return sprintf(buf, "%d\n", val);
+
+		/* Should be pnp_id */
+		return sprintf(buf, "%c%c%c, %X\n", (val >> 14 & 0x3F) + 0x40,
+			       ((val >> 9 & 0x18) | (val >> 25 & 0x07)) + 0x40,
+			       (val >> 20 & 0x1F) + 0x40, val & 0xFFF);
+	}
+
+	return -EINVAL;
+}
+
+#define PMC_DEVICE_ATTR_RO(_name)                                             \
+	static ssize_t _name##_show(struct device *dev,                       \
+				    struct device_attribute *attr, char *buf) \
+	{                                                                     \
+		return info_show(dev, attr, buf);                             \
+	}                                                                     \
+	static DEVICE_ATTR_RO(_name)
+
+PMC_DEVICE_ATTR_RO(board_name);
+PMC_DEVICE_ATTR_RO(board_serial);
+PMC_DEVICE_ATTR_RO(board_manufacturer);
+PMC_DEVICE_ATTR_RO(firmware_name);
+PMC_DEVICE_ATTR_RO(firmware_version);
+PMC_DEVICE_ATTR_RO(firmware_build);
+PMC_DEVICE_ATTR_RO(firmware_date);
+PMC_DEVICE_ATTR_RO(chip_id);
+PMC_DEVICE_ATTR_RO(chip_detect);
+PMC_DEVICE_ATTR_RO(platform_type);
+PMC_DEVICE_ATTR_RO(platform_revision);
+PMC_DEVICE_ATTR_RO(board_id);
+PMC_DEVICE_ATTR_RO(eapi_version);
+PMC_DEVICE_ATTR_RO(eapi_id);
+PMC_DEVICE_ATTR_RO(boot_count);
+PMC_DEVICE_ATTR_RO(powerup_hour);
+PMC_DEVICE_ATTR_RO(pnp_id);
+
+static struct attribute *pmc_attrs[] = { &dev_attr_board_name.attr,
+					 &dev_attr_board_serial.attr,
+					 &dev_attr_board_manufacturer.attr,
+					 &dev_attr_firmware_name.attr,
+					 &dev_attr_firmware_version.attr,
+					 &dev_attr_firmware_build.attr,
+					 &dev_attr_firmware_date.attr,
+					 &dev_attr_chip_id.attr,
+					 &dev_attr_chip_detect.attr,
+					 &dev_attr_platform_type.attr,
+					 &dev_attr_platform_revision.attr,
+					 &dev_attr_board_id.attr,
+					 &dev_attr_eapi_version.attr,
+					 &dev_attr_eapi_id.attr,
+					 &dev_attr_boot_count.attr,
+					 &dev_attr_powerup_hour.attr,
+					 &dev_attr_pnp_id.attr,
+					 NULL };
+
+ATTRIBUTE_GROUPS(pmc);
+
+static unsigned int eio_pnp_read(struct device *dev,
+				 struct eio_dev_port *port, u8 idx)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	unsigned int val;
+
+	if (regmap_write(eio->map, port->idx_port, idx))
+		dev_err(dev, "Error port write 0x%X\n", port->idx_port);
+
+	if (regmap_read(eio->map, port->data_port, &val))
+		dev_err(dev, "Error port read 0x%X\n", port->data_port);
+
+	return val;
+}
+
+static void eio_pnp_write(struct device *dev, struct eio_dev_port *port,
+			  u8 idx, u8 data)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+
+	if (regmap_write(eio->map, port->idx_port, idx) ||
+	    regmap_write(eio->map, port->data_port, data))
+		dev_err(dev, "Error port write 0x%X %X\n", port->idx_port,
+			port->data_port);
+}
+
+static void eio_pnp_enter(struct device *dev, struct eio_dev_port *port)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	/* Write 0x87 to index port twice to unlock IO port */
+	if (regmap_write(eio->map, port->idx_port,
+			 EIO_EXT_MODE_ENTER) ||
+	    regmap_write(eio->map, port->idx_port, EIO_EXT_MODE_ENTER))
+		dev_err(dev, "Error port write 0x%X\n", port->idx_port);
+}
+
+static void eio_pnp_leave(struct device *dev, struct eio_dev_port *port)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	/* Write 0xAA to index port once to lock IO port */
+	if (regmap_write(eio->map, port->idx_port, EIO_EXT_MODE_EXIT))
+		dev_err(dev, "Error port write 0x%X\n", port->idx_port);
+}
+
+static int pmc_write_data(struct device *dev, int id, u8 value, u16 timeout)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	int ret;
+
+	if (WAIT_IBF(dev, id, timeout))
+		return -ETIME;
+
+	ret = regmap_write(eio->map, eio->pmc[id].data, value);
+	if (ret)
+		dev_err(dev, "Error PMC write %X:%X\n",
+			eio->pmc[id].data, value);
+
+	return ret;
+}
+
+static int pmc_write_cmd(struct device *dev, int id, u8 value, u16 timeout)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	int ret;
+
+	if (WAIT_IBF(dev, id, timeout))
+		return -ETIME;
+
+	ret = regmap_write(eio->map, eio->pmc[id].cmd, value);
+	if (ret)
+		dev_err(dev, "Error PMC write %X:%X\n",
+			eio->pmc[id].cmd, value);
+
+	return ret;
+}
+
+static int pmc_read_data(struct device *dev, int id, u8 *value, u16 timeout)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	unsigned int val;
+	int ret;
+
+	if (WAIT_OBF(dev, id, timeout))
+		return -ETIME;
+
+	ret = regmap_read(eio->map, eio->pmc[id].data, &val);
+	if (ret)
+		dev_err(dev, "Error PMC read %X\n", eio->pmc[id].data);
+	else
+		*value = (u8)(val & 0xFF);
+
+	return ret;
+}
+
+static int pmc_read_status(struct device *dev, int id)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	unsigned int val;
+
+	if (regmap_read(eio->map, eio->pmc[id].status, &val)) {
+		dev_err(dev, "Error PMC read %X\n",
+			eio->pmc[id].status);
+		return 0;
+	}
+
+	return val;
+}
+
+static void pmc_clear(struct device *dev, int id)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	unsigned int val;
+
+	/* Check if input buffer blocked */
+	if ((pmc_read_status(dev, id) & EIO_PMC_STATUS_IBF) == 0)
+		return;
+
+	/* Read out previous garbage */
+	if (regmap_read(eio->map, eio->pmc[id].data, &val))
+		dev_err(dev, "Error pmc clear\n");
+
+	usleep_range(10, 100);
+}
+
+int eio_core_pmc_wait(struct device *dev, int id,
+		      enum eio_pmc_wait wait, uint max_duration)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	uint val;
+	int new_timeout = max_duration ? max_duration : timeout;
+
+	if (new_timeout < TIMEOUT_MIN || new_timeout > TIMEOUT_MAX) {
+		dev_err(dev,
+			"Error timeout value: %dus. Timeout value should between %d and %ld\n",
+			new_timeout, TIMEOUT_MIN, TIMEOUT_MAX);
+		return -ETIME;
+	}
+
+	if (wait == PMC_WAIT_INPUT)
+		return regmap_read_poll_timeout(eio->map, eio->pmc[id].status,
+						val, (val & EIO_PMC_STATUS_IBF) == 0,
+						SLEEP_MAX, new_timeout);
+	return regmap_read_poll_timeout(eio->map,
+					eio->pmc[id].status, val,
+					(val & EIO_PMC_STATUS_OBF) != 0,
+					SLEEP_MAX, new_timeout);
+}
+EXPORT_SYMBOL_GPL(eio_core_pmc_wait);
+
+int eio_core_pmc_operation(struct device *dev, struct pmc_op *op)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	u8 i;
+	int ret;
+	bool read_cmd = op->cmd & EIO_FLAG_PMC_READ;
+	ktime_t t = ktime_get();
+
+	mutex_lock(&eio->mutex);
+
+	pmc_clear(dev, op->chip);
+
+	ret = pmc_write_cmd(dev, op->chip, op->cmd, op->timeout);
+	if (ret)
+		goto err;
+
+	ret = pmc_write_data(dev, op->chip, op->control, op->timeout);
+	if (ret)
+		goto err;
+
+	ret = pmc_write_data(dev, op->chip, op->device_id, op->timeout);
+	if (ret)
+		goto err;
+
+	ret = pmc_write_data(dev, op->chip, op->size, op->timeout);
+	if (ret)
+		goto err;
+
+	for (i = 0; i < op->size; i++) {
+		if (read_cmd)
+			ret = pmc_read_data(dev, op->chip, &op->payload[i],
+					    op->timeout);
+		else
+			ret = pmc_write_data(dev, op->chip, op->payload[i],
+					     op->timeout);
+
+		if (ret)
+			goto err;
+	}
+
+	mutex_unlock(&eio->mutex);
+
+	return 0;
+
+err:
+	mutex_unlock(&eio->mutex);
+
+	dev_err(dev, "PMC error duration:%lldus",
+		ktime_to_us(ktime_sub(ktime_get(), t)));
+	dev_err(dev,
+		".cmd=0x%02X, .ctrl=0x%02X .id=0x%02X, .size=0x%02X .data=0x%02X%02X",
+		op->cmd, op->control, op->device_id, op->size, op->payload[0],
+		op->payload[1]);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(eio_core_pmc_operation);
+
+static int get_pmc_port(struct device *dev, int id,
+			struct eio_dev_port *port)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	struct _pmc_port *pmc = &eio->pmc[id];
+
+	eio_pnp_enter(dev, port);
+
+	/* Switch to PMC device page */
+	eio_pnp_write(dev, port, EIO_LDN, EIO_LDN_PMC1);
+
+	/* Active this device */
+	eio_pnp_write(dev, port, EIO_LDAR, EIO_LDAR_LDACT);
+
+	/* Get PMC cmd and data port */
+	pmc->data = eio_pnp_read(dev, port, EIO_IOBA0H) << 8;
+	pmc->data |= eio_pnp_read(dev, port, EIO_IOBA0L);
+	pmc->cmd = eio_pnp_read(dev, port, EIO_IOBA1H) << 8;
+	pmc->cmd |= eio_pnp_read(dev, port, EIO_IOBA1L);
+
+	/* Disable IRQ */
+	eio_pnp_write(dev, port, EIO_IRQCTRL, 0);
+
+	eio_pnp_leave(dev, port);
+
+	/* Make sure IO ports are not occupied */
+	if (!devm_request_region(dev, pmc->data, 2, KBUILD_MODNAME)) {
+		dev_err(dev, "Request region %X error\n", pmc->data);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int eio_init(struct device *dev)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	u16 chip_id = 0;
+	u8 tmp = 0;
+	int chip = 0;
+	int ret = -ENOMEM;
+
+	for (chip = 0; chip < ARRAY_SIZE(pnp_port); chip++) {
+		struct eio_dev_port *port = pnp_port + chip;
+
+		if (!devm_request_region(dev, pnp_port[chip].idx_port,
+					 pnp_port[chip].data_port -
+						 pnp_port[chip].idx_port,
+					 KBUILD_MODNAME))
+			continue;
+
+		eio_pnp_enter(dev, port);
+
+		chip_id = eio_pnp_read(dev, port, EIO_CHIPID1) << 8;
+		chip_id |= eio_pnp_read(dev, port, EIO_CHIPID2);
+
+		if (chip_id != EIO200_CHIPID && chip_id != EIO201_211_CHIPID)
+			continue;
+
+		/* Turn on the enable flag */
+		tmp = eio_pnp_read(dev, port, EIO_SIOCTRL);
+		tmp |= EIO_SIOCTRL_SIOEN;
+
+		eio_pnp_write(dev, port, EIO_SIOCTRL, tmp);
+
+		eio_pnp_leave(dev, port);
+
+		ret = get_pmc_port(dev, chip, port);
+		if (ret)
+			return ret;
+
+		if (chip == 0)
+			eio->flag |= EIO_F_CHIP_EXIST;
+		else
+			eio->flag |= EIO_F_SUB_CHIP_EXIST;
+	}
+
+	return ret;
+}
+
+static uint8_t acpiram_access(struct device *dev, uint8_t offset)
+{
+	u8 val;
+	int ret;
+	int timeout = 0;
+	struct eio_dev *eio = dev_get_drvdata(dev);
+
+	/* We only store information on primary EC */
+	int chip = 0;
+
+	mutex_lock(&eio->mutex);
+
+	pmc_clear(dev, chip);
+
+	ret = pmc_write_cmd(dev, chip, EIO_PMC_CMD_ACPIRAM_READ, timeout);
+	if (ret)
+		goto err;
+
+	ret = pmc_write_data(dev, chip, offset, timeout);
+	if (ret)
+		goto err;
+
+	ret = pmc_write_data(dev, chip, sizeof(val), timeout);
+	if (ret)
+		goto err;
+
+	ret = pmc_read_data(dev, chip, &val, timeout);
+	if (ret)
+		goto err;
+
+err:
+	mutex_unlock(&eio->mutex);
+	return ret ? 0 : val;
+}
+
+static int firmware_code_base(struct device *dev)
+{
+	struct eio_dev *eio = dev_get_drvdata(dev);
+	u8 ic_vendor, ic_code, code_base;
+
+	ic_vendor = acpiram_access(dev, EIO_ACPIRAM_ICVENDOR);
+	ic_code = acpiram_access(dev, EIO_ACPIRAM_ICCODE);
+	code_base = acpiram_access(dev, EIO_ACPIRAM_CODEBASE);
+
+	if (ic_vendor != 'R')
+		return -ENODEV;
+
+	if (ic_code != EIO200_ICCODE && ic_code != EIO201_ICCODE &&
+	    ic_code != EIO211_ICCODE)
+		goto err;
+
+	if (code_base == EIO_ACPIRAM_CODEBASE_NEW) {
+		eio->flag |= EIO_F_NEW_CODE_BASE;
+		return 0;
+	}
+
+	if (code_base == 0 &&
+	    (ic_code != EIO201_ICCODE && ic_code != EIO211_ICCODE)) {
+		dev_info(dev, "Old code base not supported, yet.");
+		return -ENODEV;
+	}
+
+err:
+	/* Codebase error. This should only happen on firmware error. */
+	dev_err(dev,
+		"Codebase check fail: vendor: 0x%X, code: 0x%X, base: 0x%X\n",
+		ic_vendor, ic_code, code_base);
+	return -ENODEV;
+}
+
+static int eio_probe(struct device *dev, unsigned int id)
+{
+	int ret = 0;
+	struct eio_dev *eio;
+
+	eio = devm_kzalloc(dev, sizeof(*eio), GFP_KERNEL);
+	if (!eio)
+		return -ENOMEM;
+
+	eio->dev = dev;
+	mutex_init(&eio->mutex);
+
+	eio->iomem = devm_ioport_map(dev, 0, EIO_SUB_PNP_DATA + 1);
+	if (IS_ERR(eio->iomem))
+		return PTR_ERR(eio->iomem);
+
+	eio->map = devm_regmap_init_mmio(dev, eio->iomem, &pnp_regmap_config);
+	if (IS_ERR(eio->map))
+		return PTR_ERR(eio->map);
+
+	/* publish instance for subdrivers (dev_get_drvdata(dev->parent)) */
+	dev_set_drvdata(dev, eio);
+
+	if (eio_init(dev)) {
+		dev_dbg(dev, "No device found\n");
+		return -ENODEV;
+	}
+
+	ret = firmware_code_base(dev);
+	if (ret) {
+		dev_err(dev, "Chip code base check fail\n");
+		return ret; /* keep helper's return (e.g., -EIO) */
+	}
+
+	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+				   mfd_devs, ARRAY_SIZE(mfd_devs),
+				   NULL, 0, NULL);
+	if (ret)
+		dev_err(dev, "Cannot register child devices (error = %d)\n", ret);
+
+	dev_dbg(dev, "Module insert completed\n");
+	return 0;
+}
+
+static struct isa_driver eio_driver = {
+	.probe    = eio_probe,
+
+	.driver = {
+		.name = "eio_core",
+		.dev_groups = pmc_groups,
+	},
+};
+module_isa_driver(eio_driver, 1);
+
+MODULE_AUTHOR("Wenkai Chung <wenkai.chung@advantech.com.tw>");
+MODULE_AUTHOR("Ramiro Oliveira <ramiro.oliveira@advantech.com>");
+MODULE_DESCRIPTION("Advantech EIO series EC core driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/eio.h b/include/linux/mfd/eio.h
new file mode 100644
index 000000000000..b87614274201
--- /dev/null
+++ b/include/linux/mfd/eio.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Header for the Advantech EIO core driver and its sub-drivers
+ *
+ * Copyright (C) 2025 Advantech Co., Ltd.
+ */
+
+#ifndef _MFD_EIO_H_
+#define _MFD_EIO_H_
+#include <linux/io.h>
+#include <linux/regmap.h>
+
+/* Definition */
+#define EIO_CHIPID1		0x20
+#define EIO_CHIPID2		0x21
+#define EIO_CHIPVER		0x22
+#define EIO_SIOCTRL		0x23
+#define EIO_SIOCTRL_SIOEN	BIT(0)
+#define EIO_SIOCTRL_SWRST	BIT(1)
+#define EIO_IRQCTRL		0x70
+#define EIO200_CHIPID		0x9610
+#define EIO201_211_CHIPID	0x9620
+#define EIO200_ICCODE		0x10
+#define EIO201_ICCODE		0x20
+#define EIO211_ICCODE		0x21
+
+/* LPC PNP */
+#define EIO_PNP_INDEX		0x299
+#define EIO_PNP_DATA		0x29A
+#define EIO_SUB_PNP_INDEX	0x499
+#define EIO_SUB_PNP_DATA	0x49A
+#define EIO_EXT_MODE_ENTER	0x87
+#define EIO_EXT_MODE_EXIT	0xAA
+
+/* LPC LDN */
+#define EIO_LDN			0x07
+#define EIO_LDN_PMC0		0x0C
+#define EIO_LDN_PMC1		0x0D
+
+/* PMC registers */
+#define EIO_PMC_STATUS_IBF	BIT(1)
+#define EIO_PMC_STATUS_OBF	BIT(0)
+#define EIO_LDAR		0x30
+#define EIO_LDAR_LDACT		BIT(0)
+#define EIO_IOBA0H		0x60
+#define EIO_IOBA0L		0x61
+#define EIO_IOBA1H		0x62
+#define EIO_IOBA1L		0x63
+#define EIO_FLAG_PMC_READ	BIT(0)
+
+/* PMC command list */
+#define EIO_PMC_CMD_ACPIRAM_READ	0x31
+#define EIO_PMC_CMD_CFG_SAVE		0x56
+
+/* OLD PMC */
+#define EIO_PMC_NO_INDEX	0xFF
+
+/* ACPI RAM Address Table */
+#define EIO_ACPIRAM_VERSIONSECTION	(0xFA)
+#define EIO_ACPIRAM_ICVENDOR		(EIO_ACPIRAM_VERSIONSECTION + 0x00)
+#define EIO_ACPIRAM_ICCODE		(EIO_ACPIRAM_VERSIONSECTION + 0x01)
+#define EIO_ACPIRAM_CODEBASE		(EIO_ACPIRAM_VERSIONSECTION + 0x02)
+
+#define EIO_ACPIRAM_CODEBASE_NEW	BIT(7)
+
+/* Firmware */
+#define EIO_F_SUB_NEW_CODE_BASE	BIT(6)
+#define EIO_F_SUB_CHANGED	BIT(7)
+#define EIO_F_NEW_CODE_BASE	BIT(8)
+#define EIO_F_CHANGED		BIT(9)
+#define EIO_F_SUB_CHIP_EXIST	BIT(30)
+#define EIO_F_CHIP_EXIST	BIT(31)
+
+/* Others */
+#define EIO_EC_NUM	2
+
+struct _pmc_port {
+	union {
+		u16 cmd;
+		u16 status;
+	};
+	u16 data;
+};
+
+struct pmc_op {
+	u8  cmd;
+	u8  control;
+	u8  device_id;
+	u8  size;
+	u8  *payload;
+	u8  chip;
+	u16 timeout;
+};
+
+enum eio_rw_operation {
+	OPERATION_READ,
+	OPERATION_WRITE,
+};
+
+struct eio_dev {
+	struct device *dev;
+	struct regmap *map;
+	void __iomem  *iomem;
+	struct mutex mutex; /* Protects PMC command access */
+	struct _pmc_port pmc[EIO_EC_NUM];
+	u32 flag;
+};
+
+int eio_core_pmc_operation(struct device *dev, struct pmc_op *operation);
+
+enum eio_pmc_wait {
+	PMC_WAIT_INPUT,
+	PMC_WAIT_OUTPUT,
+};
+
+int eio_core_pmc_wait(struct device *dev, int id, enum eio_pmc_wait wait,
+		      uint timeout);
+
+#define WAIT_IBF(dev, id, timeout)	eio_core_pmc_wait(dev, id, PMC_WAIT_INPUT, timeout)
+#define WAIT_OBF(dev, id, timeout)	eio_core_pmc_wait(dev, id, PMC_WAIT_OUTPUT, timeout)
+
+#ifdef pr_fmt
+#undef pr_fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#endif
+
+#endif

-- 
2.43.0


^ permalink raw reply related

* [PATCH 0/8] Add support for Advantech EIO MFD series devices
From: Ramiro Oliveira @ 2025-12-12 16:40 UTC (permalink / raw)
  To: Lee Jones, Linus Walleij, Bartosz Golaszewski, Guenter Roeck,
	Andi Shyti, Daniel Thompson, Jingoo Han, Helge Deller,
	Wim Van Sebroeck, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
	Lukasz Luba
  Cc: linux-kernel, linux-gpio, linux-hwmon, linux-i2c, dri-devel,
	linux-fbdev, linux-watchdog, linux-pm, Wenkai Chung,
	Francisco Aragon-Trivino, Hongzhi Wang, Mikhail Tsukerman,
	Thomas Kastner, Ramiro Oliveira

This series implements a set of drivers allowing to support the
Advantech EIO-2xx series of devices.

This includes GPIO, hwmon, I2C bus, backlight controller, watchdog,
thermal and a fan driver.

This series of patches targets several different subsystems, but the MFD
subsystem is the main target.

Signed-off-by: Ramiro Oliveira <ramiro.oliveira@advantech.com>
---
Ramiro Oliveira (8):
      Add Advantech EIO MFD driver
      Add Advantech EIO GPIO driver
      Add Advantech EIO Hardware Monitor driver
      Add Advantech EIO I2C driver
      Add Advantech EIO Backlight driver
      Add Advantech EIO Watchdog driver
      Add Advantech EIO Thermal driver
      Add Advantech EIO Fan driver

 MAINTAINERS                      |   13 +
 drivers/gpio/Kconfig             |    6 +
 drivers/gpio/Makefile            |    1 +
 drivers/gpio/gpio-eio.c          |  273 +++++++++
 drivers/hwmon/Kconfig            |   10 +
 drivers/hwmon/Makefile           |    1 +
 drivers/hwmon/eio-hwmon.c        |  344 ++++++++++++
 drivers/i2c/busses/Kconfig       |    6 +
 drivers/i2c/busses/Makefile      |    1 +
 drivers/i2c/busses/i2c-eio.c     | 1142 ++++++++++++++++++++++++++++++++++++++
 drivers/mfd/Kconfig              |   10 +
 drivers/mfd/Makefile             |    1 +
 drivers/mfd/eio_core.c           |  621 +++++++++++++++++++++
 drivers/thermal/Kconfig          |   17 +
 drivers/thermal/Makefile         |    2 +
 drivers/thermal/eio_fan.c        |  490 ++++++++++++++++
 drivers/thermal/eio_thermal.c    |  352 ++++++++++++
 drivers/video/backlight/Kconfig  |    6 +
 drivers/video/backlight/Makefile |    1 +
 drivers/video/backlight/eio_bl.c |  268 +++++++++
 drivers/watchdog/Kconfig         |    7 +
 drivers/watchdog/Makefile        |    1 +
 drivers/watchdog/eio_wdt.c       |  672 ++++++++++++++++++++++
 include/linux/mfd/eio.h          |  127 +++++
 24 files changed, 4372 insertions(+)
---
base-commit: d9771d0dbe18dd643760431870a6abf9b0866bb0
change-id: 20251212-upstream-v1-81338c603f94

Best regards,
-- 
Ramiro Oliveira <ramiro.oliveira@advantech.com>


^ permalink raw reply

* Re: [PATCH 14/19] video/vga: Add VGA_IS0_R
From: kernel test robot @ 2025-12-10 14:24 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx
  Cc: oe-kbuild-all, intel-xe, Helge Deller, linux-fbdev, dri-devel
In-Reply-To: <20251208182637.334-15-ville.syrjala@linux.intel.com>

Hi Ville,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-tip/drm-tip]
[cannot apply to drm-i915/for-linux-next drm-i915/for-linux-next-fixes drm-xe/drm-xe-next linus/master v6.18 next-20251210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ville-Syrjala/drm-i915-vga-Register-vgaarb-client-later/20251209-195929
base:   https://gitlab.freedesktop.org/drm/tip.git drm-tip
patch link:    https://lore.kernel.org/r/20251208182637.334-15-ville.syrjala%40linux.intel.com
patch subject: [PATCH 14/19] video/vga: Add VGA_IS0_R
config: s390-randconfig-002-20251210 (https://download.01.org/0day-ci/archive/20251210/202512102200.KIAC3RLu-lkp@intel.com/config)
compiler: s390-linux-gcc (GCC) 9.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251210/202512102200.KIAC3RLu-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512102200.KIAC3RLu-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from drivers/video/vgastate.c:20:
   include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
     489 | ?
         | ^
   drivers/video/vgastate.c: In function 'save_vga_text':
>> drivers/video/vgastate.c:89:9: error: dereferencing pointer to incomplete type 'struct regstate'
      89 |    saved->vga_font0[i] = vga_r(fbbase, i);
         |         ^~
   drivers/video/vgastate.c: In function 'restore_vga_text':
   drivers/video/vgastate.c:175:26: error: dereferencing pointer to incomplete type 'struct regstate'
     175 |    vga_w(fbbase, i, saved->vga_font0[i]);
         |                          ^~
   drivers/video/vgastate.c: In function 'save_vga_mode':
   drivers/video/vgastate.c:232:7: error: dereferencing pointer to incomplete type 'struct regstate'
     232 |  saved->misc = vga_r(state->vgabase, VGA_MIS_R);
         |       ^~
   drivers/video/vgastate.c: In function 'restore_vga_mode':
   drivers/video/vgastate.c:263:40: error: dereferencing pointer to incomplete type 'struct regstate'
     263 |  vga_w(state->vgabase, VGA_MIS_W, saved->misc);
         |                                        ^~
   drivers/video/vgastate.c: In function 'save_vga_cmap':
   drivers/video/vgastate.c:319:8: error: dereferencing pointer to incomplete type 'struct regstate'
     319 |   saved->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D);
         |        ^~
   drivers/video/vgastate.c: In function 'restore_vga_cmap':
   drivers/video/vgastate.c:332:41: error: dereferencing pointer to incomplete type 'struct regstate'
     332 |   vga_w(state->vgabase, VGA_PEL_D, saved->vga_cmap[i]);
         |                                         ^~
   drivers/video/vgastate.c: In function 'vga_cleanup':
   drivers/video/vgastate.c:340:14: error: dereferencing pointer to incomplete type 'struct regstate'
     340 |   vfree(saved->vga_font0);
         |              ^~
   In file included from include/linux/workqueue.h:9,
                    from include/linux/mm_types.h:19,
                    from include/linux/mmzone.h:22,
                    from include/linux/gfp.h:7,
                    from include/linux/umh.h:4,
                    from include/linux/kmod.h:9,
                    from include/linux/module.h:18,
                    from drivers/video/vgastate.c:16:
   drivers/video/vgastate.c: In function 'save_vga':
   drivers/video/vgastate.c:354:25: error: invalid application of 'sizeof' to incomplete type 'struct regstate'
     354 |  saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
         |                         ^~~~~~
   include/linux/alloc_tag.h:251:9: note: in definition of macro 'alloc_hooks_tag'
     251 |  typeof(_do_alloc) _res;      \
         |         ^~~~~~~~~
   include/linux/slab.h:1096:25: note: in expansion of macro 'alloc_hooks'
    1096 | #define kzalloc(...)    alloc_hooks(kzalloc_noprof(__VA_ARGS__))
         |                         ^~~~~~~~~~~
   drivers/video/vgastate.c:354:10: note: in expansion of macro 'kzalloc'
     354 |  saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
         |          ^~~~~~~
   drivers/video/vgastate.c:354:25: error: invalid application of 'sizeof' to incomplete type 'struct regstate'
     354 |  saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
         |                         ^~~~~~
   include/linux/alloc_tag.h:255:10: note: in definition of macro 'alloc_hooks_tag'
     255 |   _res = _do_alloc;     \
         |          ^~~~~~~~~
   include/linux/slab.h:1096:25: note: in expansion of macro 'alloc_hooks'
    1096 | #define kzalloc(...)    alloc_hooks(kzalloc_noprof(__VA_ARGS__))
         |                         ^~~~~~~~~~~
   drivers/video/vgastate.c:354:10: note: in expansion of macro 'kzalloc'
     354 |  saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
         |          ^~~~~~~
   drivers/video/vgastate.c:354:25: error: invalid application of 'sizeof' to incomplete type 'struct regstate'
     354 |  saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
         |                         ^~~~~~
   include/linux/alloc_tag.h:258:10: note: in definition of macro 'alloc_hooks_tag'
     258 |   _res = _do_alloc;     \
         |          ^~~~~~~~~
   include/linux/slab.h:1096:25: note: in expansion of macro 'alloc_hooks'
    1096 | #define kzalloc(...)    alloc_hooks(kzalloc_noprof(__VA_ARGS__))
         |                         ^~~~~~~~~~~
   drivers/video/vgastate.c:354:10: note: in expansion of macro 'kzalloc'
     354 |  saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
         |          ^~~~~~~
   drivers/video/vgastate.c:354:8: warning: assignment to 'struct regstate *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     354 |  saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
         |        ^
   drivers/video/vgastate.c:362:8: error: dereferencing pointer to incomplete type 'struct regstate'
     362 |   saved->vga_cmap = vmalloc(768);
         |        ^~


vim +89 drivers/video/vgastate.c

^1da177e4c3f41 Linus Torvalds 2005-04-16   47  
^1da177e4c3f41 Linus Torvalds 2005-04-16   48  static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
^1da177e4c3f41 Linus Torvalds 2005-04-16   49  {
^1da177e4c3f41 Linus Torvalds 2005-04-16   50  	struct regstate *saved = (struct regstate *) state->vidstate;
^1da177e4c3f41 Linus Torvalds 2005-04-16   51  	int i;
^1da177e4c3f41 Linus Torvalds 2005-04-16   52  	u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4;
0449359f053829 Ondrej Zajicek 2007-05-08   53  	unsigned short iobase;
^1da177e4c3f41 Linus Torvalds 2005-04-16   54  
^1da177e4c3f41 Linus Torvalds 2005-04-16   55  	/* if in graphics mode, no need to save */
0449359f053829 Ondrej Zajicek 2007-05-08   56  	misc = vga_r(state->vgabase, VGA_MIS_R);
0449359f053829 Ondrej Zajicek 2007-05-08   57  	iobase = (misc & 1) ? 0x3d0 : 0x3b0;
0449359f053829 Ondrej Zajicek 2007-05-08   58  
0449359f053829 Ondrej Zajicek 2007-05-08   59  	vga_r(state->vgabase, iobase + 0xa);
0449359f053829 Ondrej Zajicek 2007-05-08   60  	vga_w(state->vgabase, VGA_ATT_W, 0x00);
^1da177e4c3f41 Linus Torvalds 2005-04-16   61  	attr10 = vga_rattr(state->vgabase, 0x10);
0449359f053829 Ondrej Zajicek 2007-05-08   62  	vga_r(state->vgabase, iobase + 0xa);
0449359f053829 Ondrej Zajicek 2007-05-08   63  	vga_w(state->vgabase, VGA_ATT_W, 0x20);
0449359f053829 Ondrej Zajicek 2007-05-08   64  
^1da177e4c3f41 Linus Torvalds 2005-04-16   65  	if (attr10 & 1)
^1da177e4c3f41 Linus Torvalds 2005-04-16   66  		return;
^1da177e4c3f41 Linus Torvalds 2005-04-16   67  
^1da177e4c3f41 Linus Torvalds 2005-04-16   68  	/* save regs */
^1da177e4c3f41 Linus Torvalds 2005-04-16   69  	gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
^1da177e4c3f41 Linus Torvalds 2005-04-16   70  	gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
^1da177e4c3f41 Linus Torvalds 2005-04-16   71  	gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
^1da177e4c3f41 Linus Torvalds 2005-04-16   72  	seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
^1da177e4c3f41 Linus Torvalds 2005-04-16   73  	seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
^1da177e4c3f41 Linus Torvalds 2005-04-16   74  
^1da177e4c3f41 Linus Torvalds 2005-04-16   75  	/* blank screen */
^1da177e4c3f41 Linus Torvalds 2005-04-16   76  	seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
^1da177e4c3f41 Linus Torvalds 2005-04-16   77  	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
^1da177e4c3f41 Linus Torvalds 2005-04-16   78  	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
^1da177e4c3f41 Linus Torvalds 2005-04-16   79  	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
^1da177e4c3f41 Linus Torvalds 2005-04-16   80  
^1da177e4c3f41 Linus Torvalds 2005-04-16   81  	/* save font at plane 2 */
^1da177e4c3f41 Linus Torvalds 2005-04-16   82  	if (state->flags & VGA_SAVE_FONT0) {
^1da177e4c3f41 Linus Torvalds 2005-04-16   83  		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
^1da177e4c3f41 Linus Torvalds 2005-04-16   84  		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
^1da177e4c3f41 Linus Torvalds 2005-04-16   85  		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
^1da177e4c3f41 Linus Torvalds 2005-04-16   86  		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
^1da177e4c3f41 Linus Torvalds 2005-04-16   87  		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
^1da177e4c3f41 Linus Torvalds 2005-04-16   88  		for (i = 0; i < 4 * 8192; i++)
^1da177e4c3f41 Linus Torvalds 2005-04-16  @89  			saved->vga_font0[i] = vga_r(fbbase, i);
^1da177e4c3f41 Linus Torvalds 2005-04-16   90  	}
^1da177e4c3f41 Linus Torvalds 2005-04-16   91  
^1da177e4c3f41 Linus Torvalds 2005-04-16   92  	/* save font at plane 3 */
^1da177e4c3f41 Linus Torvalds 2005-04-16   93  	if (state->flags & VGA_SAVE_FONT1) {
^1da177e4c3f41 Linus Torvalds 2005-04-16   94  		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
^1da177e4c3f41 Linus Torvalds 2005-04-16   95  		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
^1da177e4c3f41 Linus Torvalds 2005-04-16   96  		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
^1da177e4c3f41 Linus Torvalds 2005-04-16   97  		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
^1da177e4c3f41 Linus Torvalds 2005-04-16   98  		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
^1da177e4c3f41 Linus Torvalds 2005-04-16   99  		for (i = 0; i < state->memsize; i++)
^1da177e4c3f41 Linus Torvalds 2005-04-16  100  			saved->vga_font1[i] = vga_r(fbbase, i);
^1da177e4c3f41 Linus Torvalds 2005-04-16  101  	}
^1da177e4c3f41 Linus Torvalds 2005-04-16  102  
^1da177e4c3f41 Linus Torvalds 2005-04-16  103  	/* save font at plane 0/1 */
^1da177e4c3f41 Linus Torvalds 2005-04-16  104  	if (state->flags & VGA_SAVE_TEXT) {
^1da177e4c3f41 Linus Torvalds 2005-04-16  105  		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
^1da177e4c3f41 Linus Torvalds 2005-04-16  106  		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
^1da177e4c3f41 Linus Torvalds 2005-04-16  107  		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
^1da177e4c3f41 Linus Torvalds 2005-04-16  108  		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
^1da177e4c3f41 Linus Torvalds 2005-04-16  109  		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
^1da177e4c3f41 Linus Torvalds 2005-04-16  110  		for (i = 0; i < 8192; i++)
^1da177e4c3f41 Linus Torvalds 2005-04-16  111  			saved->vga_text[i] = vga_r(fbbase, i);
^1da177e4c3f41 Linus Torvalds 2005-04-16  112  
^1da177e4c3f41 Linus Torvalds 2005-04-16  113  		vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
^1da177e4c3f41 Linus Torvalds 2005-04-16  114  		vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
^1da177e4c3f41 Linus Torvalds 2005-04-16  115  		vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
^1da177e4c3f41 Linus Torvalds 2005-04-16  116  		vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
^1da177e4c3f41 Linus Torvalds 2005-04-16  117  		vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
^1da177e4c3f41 Linus Torvalds 2005-04-16  118  		for (i = 0; i < 8192; i++)
^1da177e4c3f41 Linus Torvalds 2005-04-16  119  			saved->vga_text[8192+i] = vga_r(fbbase + 2 * 8192, i);
^1da177e4c3f41 Linus Torvalds 2005-04-16  120  	}
^1da177e4c3f41 Linus Torvalds 2005-04-16  121  
^1da177e4c3f41 Linus Torvalds 2005-04-16  122  	/* restore regs */
^1da177e4c3f41 Linus Torvalds 2005-04-16  123  	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
^1da177e4c3f41 Linus Torvalds 2005-04-16  124  	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
^1da177e4c3f41 Linus Torvalds 2005-04-16  125  
^1da177e4c3f41 Linus Torvalds 2005-04-16  126  	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
^1da177e4c3f41 Linus Torvalds 2005-04-16  127  	vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
^1da177e4c3f41 Linus Torvalds 2005-04-16  128  	vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
^1da177e4c3f41 Linus Torvalds 2005-04-16  129  
^1da177e4c3f41 Linus Torvalds 2005-04-16  130  	/* unblank screen */
^1da177e4c3f41 Linus Torvalds 2005-04-16  131  	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
^1da177e4c3f41 Linus Torvalds 2005-04-16  132  	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
^1da177e4c3f41 Linus Torvalds 2005-04-16  133  	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
^1da177e4c3f41 Linus Torvalds 2005-04-16  134  
^1da177e4c3f41 Linus Torvalds 2005-04-16  135  	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
^1da177e4c3f41 Linus Torvalds 2005-04-16  136  }
^1da177e4c3f41 Linus Torvalds 2005-04-16  137  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH 14/19] video/vga: Add VGA_IS0_R
From: kernel test robot @ 2025-12-10 14:13 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx
  Cc: oe-kbuild-all, intel-xe, Helge Deller, linux-fbdev, dri-devel
In-Reply-To: <20251208182637.334-15-ville.syrjala@linux.intel.com>

Hi Ville,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-tip/drm-tip]
[cannot apply to drm-i915/for-linux-next drm-i915/for-linux-next-fixes drm-xe/drm-xe-next linus/master v6.18 next-20251210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ville-Syrjala/drm-i915-vga-Register-vgaarb-client-later/20251209-195929
base:   https://gitlab.freedesktop.org/drm/tip.git drm-tip
patch link:    https://lore.kernel.org/r/20251208182637.334-15-ville.syrjala%40linux.intel.com
patch subject: [PATCH 14/19] video/vga: Add VGA_IS0_R
config: parisc-randconfig-002-20251210 (https://download.01.org/0day-ci/archive/20251210/202512102159.xsvvXCXy-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251210/202512102159.xsvvXCXy-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512102159.xsvvXCXy-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/svga.h:6,
                    from drivers/video/fbdev/arkfb.c:24:
   include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   In file included from drivers/video/fbdev/arkfb.c:28:
   include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   drivers/video/fbdev/arkfb.c:68:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_h_total_regs[]        = {{0x00, 0, 7}, {0x41, 7, 7}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:69:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_h_display_regs[]      = {{0x01, 0, 7}, {0x41, 6, 6}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:70:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x41, 5, 5}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:71:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7 }, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:72:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x41, 4, 4}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:73:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:75:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x40, 7, 7}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:76:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x40, 6, 6}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:77:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x40, 5, 5}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:79:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:80:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x40, 4, 4}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:81:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:83:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:84:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:85:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset ark_offset_regs[]         = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c: In function 'arkfb_tilecursor':
>> drivers/video/fbdev/arkfb.c:152:21: error: dereferencing pointer to incomplete type 'struct arkfb_info'
     svga_tilecursor(par->state.vgabase, info, cursor);
                        ^~
   drivers/video/fbdev/arkfb.c: At top level:
   drivers/video/fbdev/arkfb.c:303:29: warning: 'struct dac_info' declared inside parameter list will not be visible outside of this definition or declaration
     int (*dac_get_mode)(struct dac_info *info);
                                ^~~~~~~~
   drivers/video/fbdev/arkfb.c:304:29: warning: 'struct dac_info' declared inside parameter list will not be visible outside of this definition or declaration
     int (*dac_set_mode)(struct dac_info *info, int mode);
                                ^~~~~~~~
   drivers/video/fbdev/arkfb.c:305:29: warning: 'struct dac_info' declared inside parameter list will not be visible outside of this definition or declaration
     int (*dac_get_freq)(struct dac_info *info, int channel);
                                ^~~~~~~~
   drivers/video/fbdev/arkfb.c:306:29: warning: 'struct dac_info' declared inside parameter list will not be visible outside of this definition or declaration
     int (*dac_set_freq)(struct dac_info *info, int channel, u32 freq);
                                ^~~~~~~~
   drivers/video/fbdev/arkfb.c:307:29: warning: 'struct dac_info' declared inside parameter list will not be visible outside of this definition or declaration
     void (*dac_release)(struct dac_info *info);
                                ^~~~~~~~
   drivers/video/fbdev/arkfb.c: In function 'dac_set_mode':
   drivers/video/fbdev/arkfb.c:339:36: error: passing argument 1 of 'info->dacops->dac_set_mode' from incompatible pointer type [-Werror=incompatible-pointer-types]
     return info->dacops->dac_set_mode(info, mode);
                                       ^~~~
   drivers/video/fbdev/arkfb.c:339:36: note: expected 'struct dac_info *' but argument is of type 'struct dac_info *'
   drivers/video/fbdev/arkfb.c: In function 'dac_set_freq':
   drivers/video/fbdev/arkfb.c:344:36: error: passing argument 1 of 'info->dacops->dac_set_freq' from incompatible pointer type [-Werror=incompatible-pointer-types]
     return info->dacops->dac_set_freq(info, channel, freq);
                                       ^~~~
   drivers/video/fbdev/arkfb.c:344:36: note: expected 'struct dac_info *' but argument is of type 'struct dac_info *'
   drivers/video/fbdev/arkfb.c: In function 'dac_release':
   drivers/video/fbdev/arkfb.c:349:28: error: passing argument 1 of 'info->dacops->dac_release' from incompatible pointer type [-Werror=incompatible-pointer-types]
     info->dacops->dac_release(info);
                               ^~~~
   drivers/video/fbdev/arkfb.c:349:28: note: expected 'struct dac_info *' but argument is of type 'struct dac_info *'
   drivers/video/fbdev/arkfb.c: At top level:
   drivers/video/fbdev/arkfb.c:426:18: error: initialization of 'int (*)(struct dac_info *, int)' from incompatible pointer type 'int (*)(struct dac_info *, int)' [-Werror=incompatible-pointer-types]
     .dac_set_mode = ics5342_set_mode,
                     ^~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:426:18: note: (near initialization for 'ics5342_ops.dac_set_mode')
   drivers/video/fbdev/arkfb.c:427:18: error: initialization of 'int (*)(struct dac_info *, int,  u32)' {aka 'int (*)(struct dac_info *, int,  unsigned int)'} from incompatible pointer type 'int (*)(struct dac_info *, int,  u32)' {aka 'int (*)(struct dac_info *, int,  unsigned int)'} [-Werror=incompatible-pointer-types]
     .dac_set_freq = ics5342_set_freq,
                     ^~~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:427:18: note: (near initialization for 'ics5342_ops.dac_set_freq')
   drivers/video/fbdev/arkfb.c:428:17: error: initialization of 'void (*)(struct dac_info *)' from incompatible pointer type 'void (*)(struct dac_info *)' [-Werror=incompatible-pointer-types]
     .dac_release = ics5342_release
                    ^~~~~~~~~~~~~~~
   drivers/video/fbdev/arkfb.c:428:17: note: (near initialization for 'ics5342_ops.dac_release')
   drivers/video/fbdev/arkfb.c: In function 'ark_dac_read_regs':
   drivers/video/fbdev/arkfb.c:461:23: error: dereferencing pointer to incomplete type 'struct arkfb_info'
     regval = vga_rseq(par->state.vgabase, 0x1C);
                          ^~
   drivers/video/fbdev/arkfb.c: In function 'ark_dac_write_regs':
   drivers/video/fbdev/arkfb.c:480:23: error: dereferencing pointer to incomplete type 'struct arkfb_info'
     regval = vga_rseq(par->state.vgabase, 0x1C);
                          ^~
   drivers/video/fbdev/arkfb.c: In function 'ark_set_pixclock':
   drivers/video/fbdev/arkfb.c:498:27: error: dereferencing pointer to incomplete type 'struct arkfb_info'
     int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);
                              ^~
   In file included from include/linux/seqlock.h:19,
                    from include/linux/mmzone.h:17,
                    from include/linux/gfp.h:7,
                    from include/linux/umh.h:4,
                    from include/linux/kmod.h:9,
                    from include/linux/module.h:18,
                    from drivers/video/fbdev/arkfb.c:15:
   drivers/video/fbdev/arkfb.c: In function 'arkfb_open':
   drivers/video/fbdev/arkfb.c:516:18: error: dereferencing pointer to incomplete type 'struct arkfb_info'
     mutex_lock(&(par->open_lock));
                     ^~
   include/linux/mutex.h:168:44: note: in definition of macro 'mutex_lock'
    #define mutex_lock(lock) mutex_lock_nested(lock, 0)
                                               ^~~~
   drivers/video/fbdev/arkfb.c: In function 'arkfb_release':
   drivers/video/fbdev/arkfb.c:540:18: error: dereferencing pointer to incomplete type 'struct arkfb_info'
     mutex_lock(&(par->open_lock));
                     ^~
   include/linux/mutex.h:168:44: note: in definition of macro 'mutex_lock'
    #define mutex_lock(lock) mutex_lock_nested(lock, 0)
                                               ^~~~
   drivers/video/fbdev/arkfb.c: In function 'arkfb_set_par':
   drivers/video/fbdev/arkfb.c:658:20: error: dereferencing pointer to incomplete type 'struct arkfb_info'
     svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
                       ^~
   drivers/video/fbdev/arkfb.c: In function 'arkfb_blank':
   drivers/video/fbdev/arkfb.c:881:21: error: dereferencing pointer to incomplete type 'struct arkfb_info'
      svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
                        ^~
   drivers/video/fbdev/arkfb.c: In function 'arkfb_pan_display':
   drivers/video/fbdev/arkfb.c:920:21: error: dereferencing pointer to incomplete type 'struct arkfb_info'
     svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, offset);
                        ^~
   drivers/video/fbdev/arkfb.c: In function 'ark_pci_probe':
   drivers/video/fbdev/arkfb.c:973:34: error: invalid application of 'sizeof' to incomplete type 'struct arkfb_info'
     info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev));
                                     ^~~~~~
   In file included from include/linux/seqlock.h:19,
                    from include/linux/mmzone.h:17,
                    from include/linux/gfp.h:7,
                    from include/linux/umh.h:4,
                    from include/linux/kmod.h:9,
--
   In file included from include/linux/svga.h:6,
                    from drivers/video/fbdev/vt8623fb.c:24:
   include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   In file included from drivers/video/fbdev/vt8623fb.c:28:
   include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   drivers/video/fbdev/vt8623fb.c:66:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_h_total_regs[]       = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:67:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_h_display_regs[]     = {{0x01, 0, 7}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:68:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:69:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_h_blank_end_regs[]   = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:70:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_h_sync_start_regs[]  = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:71:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_h_sync_end_regs[]    = {{0x05, 0, 4}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:73:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_v_total_regs[]       = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:74:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_v_display_regs[]     = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:75:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:76:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_v_blank_end_regs[]   = {{0x16, 0, 7}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:77:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:78:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:80:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:81:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:82:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:83:32: error: array type has incomplete element type 'struct vga_regset'
    static const struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623fb_tilecursor':
>> drivers/video/fbdev/vt8623fb.c:119:21: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     svga_tilecursor(par->state.vgabase, info, cursor);
                        ^~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623_set_pixclock':
   drivers/video/fbdev/vt8623fb.c:265:20: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     regval = vga_r(par->state.vgabase, VGA_MIS_R);
                       ^~
   In file included from include/linux/seqlock.h:19,
                    from include/linux/mmzone.h:17,
                    from include/linux/gfp.h:7,
                    from include/linux/umh.h:4,
                    from include/linux/kmod.h:9,
                    from include/linux/module.h:18,
                    from drivers/video/fbdev/vt8623fb.c:16:
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623fb_open':
   drivers/video/fbdev/vt8623fb.c:284:18: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     mutex_lock(&(par->open_lock));
                     ^~
   include/linux/mutex.h:168:44: note: in definition of macro 'mutex_lock'
    #define mutex_lock(lock) mutex_lock_nested(lock, 0)
                                               ^~~~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623fb_release':
   drivers/video/fbdev/vt8623fb.c:306:18: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     mutex_lock(&(par->open_lock));
                     ^~
   include/linux/mutex.h:168:44: note: in definition of macro 'mutex_lock'
    #define mutex_lock(lock) mutex_lock_nested(lock, 0)
                                               ^~~~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623fb_set_par':
   drivers/video/fbdev/vt8623fb.c:431:20: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     svga_wseq_mask(par->state.vgabase, 0x10, 0x01, 0x01);
                       ^~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623fb_blank':
   drivers/video/fbdev/vt8623fb.c:593:21: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
      svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
                        ^~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623fb_pan_display':
   drivers/video/fbdev/vt8623fb.c:639:21: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, offset);
                        ^~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623_pci_probe':
   drivers/video/fbdev/vt8623fb.c:690:34: error: invalid application of 'sizeof' to incomplete type 'struct vt8623fb_info'
     info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev));
                                     ^~~~~~
   In file included from include/linux/seqlock.h:19,
                    from include/linux/mmzone.h:17,
                    from include/linux/gfp.h:7,
                    from include/linux/umh.h:4,
                    from include/linux/kmod.h:9,
                    from include/linux/module.h:18,
                    from drivers/video/fbdev/vt8623fb.c:16:
   drivers/video/fbdev/vt8623fb.c:695:17: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     mutex_init(&par->open_lock);
                    ^~
   include/linux/mutex.h:64:16: note: in definition of macro 'mutex_init'
     __mutex_init((mutex), #mutex, &__key);    \
                   ^~~~~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623_pci_remove':
   drivers/video/fbdev/vt8623fb.c:823:23: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
      arch_phys_wc_del(par->wc_cookie);
                          ^~
   In file included from include/linux/seqlock.h:19,
                    from include/linux/mmzone.h:17,
                    from include/linux/gfp.h:7,
                    from include/linux/umh.h:4,
                    from include/linux/kmod.h:9,
                    from include/linux/module.h:18,
                    from drivers/video/fbdev/vt8623fb.c:16:
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623_pci_suspend':
   drivers/video/fbdev/vt8623fb.c:847:18: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     mutex_lock(&(par->open_lock));
                     ^~
   include/linux/mutex.h:168:44: note: in definition of macro 'mutex_lock'
    #define mutex_lock(lock) mutex_lock_nested(lock, 0)
                                               ^~~~
   drivers/video/fbdev/vt8623fb.c: In function 'vt8623_pci_resume':
   drivers/video/fbdev/vt8623fb.c:874:18: error: dereferencing pointer to incomplete type 'struct vt8623fb_info'
     mutex_lock(&(par->open_lock));
                     ^~
   include/linux/mutex.h:168:44: note: in definition of macro 'mutex_lock'
    #define mutex_lock(lock) mutex_lock_nested(lock, 0)
                                               ^~~~
   At top level:
   drivers/video/fbdev/vt8623fb.c:83:32: warning: 'vt8623_start_address_regs' defined but not used [-Wunused-variable]
    static const struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:82:32: warning: 'vt8623_fetch_count_regs' defined but not used [-Wunused-variable]
    static const struct vga_regset vt8623_fetch_count_regs[]   = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:81:32: warning: 'vt8623_line_compare_regs' defined but not used [-Wunused-variable]
    static const struct vga_regset vt8623_line_compare_regs[]  = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:80:32: warning: 'vt8623_offset_regs' defined but not used [-Wunused-variable]
    static const struct vga_regset vt8623_offset_regs[]        = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:78:32: warning: 'vt8623_v_sync_end_regs' defined but not used [-Wunused-variable]
    static const struct vga_regset vt8623_v_sync_end_regs[]    = {{0x11, 0, 3}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~
   drivers/video/fbdev/vt8623fb.c:77:32: warning: 'vt8623_v_sync_start_regs' defined but not used [-Wunused-variable]
    static const struct vga_regset vt8623_v_sync_start_regs[]  = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
                                   ^~~~~~~~~~~~~~~~~~~~~~~~
..


vim +152 drivers/video/fbdev/arkfb.c

681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   82  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   83  static const struct vga_regset ark_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END};
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  @84  static const struct vga_regset ark_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END};
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   85  static const struct vga_regset ark_offset_regs[]         = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END};
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   86  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   87  static const struct svga_timing_regs ark_timing_regs     = {
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   88  	ark_h_total_regs, ark_h_display_regs, ark_h_blank_start_regs,
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   89  	ark_h_blank_end_regs, ark_h_sync_start_regs, ark_h_sync_end_regs,
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   90  	ark_v_total_regs, ark_v_display_regs, ark_v_blank_start_regs,
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   91  	ark_v_blank_end_regs, ark_v_sync_start_regs, ark_v_sync_end_regs,
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   92  };
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   93  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   94  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   95  /* ------------------------------------------------------------------------- */
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   96  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   97  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   98  /* Module parameters */
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09   99  
48c68c4f1b5424 drivers/video/arkfb.c Greg Kroah-Hartman 2012-12-21  100  static char *mode_option = "640x480-8@60";
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  101  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  102  MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago@crfreenet.org>");
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  103  MODULE_LICENSE("GPL");
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  104  MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  105  
1abf91729faf2f drivers/video/arkfb.c Krzysztof Helt     2008-04-28  106  module_param(mode_option, charp, 0444);
1abf91729faf2f drivers/video/arkfb.c Krzysztof Helt     2008-04-28  107  MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
1abf91729faf2f drivers/video/arkfb.c Krzysztof Helt     2008-04-28  108  module_param_named(mode, mode_option, charp, 0444);
1abf91729faf2f drivers/video/arkfb.c Krzysztof Helt     2008-04-28  109  MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) (deprecated)");
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  110  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  111  static int threshold = 4;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  112  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  113  module_param(threshold, int, 0644);
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  114  MODULE_PARM_DESC(threshold, "FIFO threshold");
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  115  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  116  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  117  /* ------------------------------------------------------------------------- */
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  118  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  119  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  120  static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map)
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  121  {
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  122  	const u8 *font = map->data;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  123  	u8 __iomem *fb = (u8 __iomem *)info->screen_base;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  124  	int i, c;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  125  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  126  	if ((map->width != 8) || (map->height != 16) ||
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  127  	    (map->depth != 1) || (map->length != 256)) {
31b6780c15a4e3 drivers/video/arkfb.c Joe Perches        2013-09-19  128  		fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  129  		       map->width, map->height, map->depth, map->length);
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  130  		return;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  131  	}
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  132  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  133  	fb += 2;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  134  	for (c = 0; c < map->length; c++) {
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  135  		for (i = 0; i < map->height; i++) {
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  136  			fb_writeb(font[i], &fb[i * 4]);
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  137  			fb_writeb(font[i], &fb[i * 4 + (128 * 8)]);
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  138  		}
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  139  		fb += 128;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  140  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  141  		if ((c % 8) == 7)
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  142  			fb += 128*8;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  143  
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  144  		font += map->height;
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  145  	}
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  146  }
681e14730c73cc drivers/video/arkfb.c Ondrej Zajicek     2007-05-09  147  
55db0923884554 drivers/video/arkfb.c David Miller       2011-01-11  148  static void arkfb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
55db0923884554 drivers/video/arkfb.c David Miller       2011-01-11  149  {
55db0923884554 drivers/video/arkfb.c David Miller       2011-01-11  150  	struct arkfb_info *par = info->par;
55db0923884554 drivers/video/arkfb.c David Miller       2011-01-11  151  
55db0923884554 drivers/video/arkfb.c David Miller       2011-01-11 @152  	svga_tilecursor(par->state.vgabase, info, cursor);
55db0923884554 drivers/video/arkfb.c David Miller       2011-01-11  153  }
55db0923884554 drivers/video/arkfb.c David Miller       2011-01-11  154  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH 0/3] fbdev: Guard sysfs interfaces under CONFIG_FB_DEVICE
From: Chintan Patel @ 2025-12-10  4:26 UTC (permalink / raw)
  To: Andy Shevchenko, Helge Deller
  Cc: Thomas Zimmermann, linux-fbdev, linux-staging, linux-omap,
	linux-kernel, dri-devel, andy, gregkh
In-Reply-To: <CAHp75Vds8GP+daMe9WcEbOaNT91kMHUjidzGUN-1_kVDuWBtLw@mail.gmail.com>



On 12/9/25 06:25, Andy Shevchenko wrote:
> On Tue, Dec 9, 2025 at 10:23 AM Helge Deller <deller@gmx.de> wrote:
>> On 12/9/25 08:27, Thomas Zimmermann wrote:
> 
> ...
> 
>> This whole series adds a whole lot of ifdef'ery, which I think is the
>> worst approach. It makes the code less readable and leads to two code
>> paths, which may trigger different build errors depending on the config.
>>
>> I'm sure it must be possible to do the same without adding more #ifdefs,
>> e.g. by introducing a function like   dev_of_fbinfo(fbinfo)  which
>> simply returns NULL for the FB_DEVICE=n case.  Then, that value can be tested
>> like
>>          if (dev_of_fbinfo(fbinfo))
>>                  {...do-the-things...}
>> For the FB_DEVICE=n case this will then be optimized out by the compiler,
>> while you still have full compiler syntax checking.
>>
>> Thoughts?
> 
> I second you. I am also not a fan of ifdeffery when it can be avoided.
> 

Thank you for the review! Will do the change.

^ permalink raw reply

* Re: [PATCH 1/3] fbtft: Make sysfs and dev_*() logging conditional on FB_DEVICE
From: Chintan Patel @ 2025-12-10  4:24 UTC (permalink / raw)
  To: Thomas Zimmermann, linux-fbdev, linux-staging, linux-omap
  Cc: linux-kernel, dri-devel, andy, deller, gregkh
In-Reply-To: <329423e8-d778-4f30-904a-825b1be72ce2@suse.de>

Hi Thomas,

On 12/8/25 23:25, Thomas Zimmermann wrote:
> Hi
> 
> Am 09.12.25 um 05:27 schrieb Chintan Patel:
>> The fbtft core and sysfs implementation unconditionally dereference
>> fb_info->dev and register sysfs attributes. When FB_DEVICE=n, these
>> fields are unavailable, leading to build failures.
>>
>> This patch wraps all sysfs attribute creation/removal and dev_dbg/ 
>> dev_info
>> logging in #ifdef CONFIG_FB_DEVICE, with pr_*() fallbacks for the
>> non-FB_DEVICE case. This makes fbtft fully buildable when FB_DEVICE is
>> disabled.
>>
>> Signed-off-by: Chintan Patel <chintanlike@gmail.com>
>> ---
>>   drivers/staging/fbtft/fbtft-core.c  | 20 ++++++++++++++++++--
>>   drivers/staging/fbtft/fbtft-sysfs.c |  8 ++++++++
>>   2 files changed, 26 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/ 
>> fbtft/fbtft-core.c
>> index 9e7b84071174..dc967bdeabe8 100644
>> --- a/drivers/staging/fbtft/fbtft-core.c
>> +++ b/drivers/staging/fbtft/fbtft-core.c
>> @@ -365,9 +365,14 @@ static int fbtft_fb_setcolreg(unsigned int regno, 
>> unsigned int red,
>>       unsigned int val;
>>       int ret = 1;
>> +#ifdef CONFIG_FB_DEVICE
>>       dev_dbg(info->dev,
> 
> Rather use fb_dbg() [1] and similar helpers for logging. They only need 
> the info pointer and do the correct output by themselves.
> 
> [1] https://elixir.bootlin.com/linux/v6.18/source/include/linux/fb.h#L895

Thank you for this pointer - I actually didnt now this existed. Will do v2.

^ permalink raw reply

* Re: [PATCH v6 1/4] dt-bindings: backlight: Add max25014 support
From: Rob Herring @ 2025-12-09 19:07 UTC (permalink / raw)
  To: Maud Spierings
  Cc: Frank Li, Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek,
	Krzysztof Kozlowski, Conor Dooley, Helge Deller, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Liam Girdwood, Mark Brown, dri-devel, linux-leds, devicetree,
	linux-kernel, linux-fbdev, imx, linux-arm-kernel
In-Reply-To: <e428c3a9-49e2-4af5-b597-2cdfef7028f5@gocontroll.com>

On Mon, Dec 08, 2025 at 02:56:50PM +0100, Maud Spierings wrote:
> On 12/2/25 15:53, Frank Li wrote:
> > On Tue, Dec 02, 2025 at 08:46:21AM +0100, Maud Spierings wrote:
> > > On 12/1/25 17:52, Frank Li wrote:
> > > > On Mon, Dec 01, 2025 at 12:53:20PM +0100, Maud Spierings via B4 Relay wrote:
> > > > > From: Maud Spierings <maudspierings@gocontroll.com>
> > > > > 
> > > > > The Maxim MAX25014 is a 4-channel automotive grade backlight driver IC
> > > > > with integrated boost controller.
> > > > > 
> > > > > Signed-off-by: Maud Spierings <maudspierings@gocontroll.com>
> > > > > 
> > > > > ---
> > > > > 
> > > > > In the current implementation the control registers for channel 1,
> > > > > control all channels. So only one led subnode with led-sources is
> > > > > supported right now. If at some point the driver functionality is
> > > > > expanded the bindings can be easily extended with it.
> > > > > ---
> > > > >    .../bindings/leds/backlight/maxim,max25014.yaml    | 107 +++++++++++++++++++++
> > > > >    MAINTAINERS                                        |   5 +
> > > > >    2 files changed, 112 insertions(+)
> > > > > 
> > > > > diff --git a/Documentation/devicetree/bindings/leds/backlight/maxim,max25014.yaml b/Documentation/devicetree/bindings/leds/backlight/maxim,max25014.yaml
> > > > > new file mode 100644
> > > > > index 000000000000..e83723224b07
> > > > > --- /dev/null
> > > > > +++ b/Documentation/devicetree/bindings/leds/backlight/maxim,max25014.yaml
> > > > > @@ -0,0 +1,107 @@
> > > > > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > > > > +%YAML 1.2
> > > > > +---
> > > > > +$id: http://devicetree.org/schemas/leds/backlight/maxim,max25014.yaml#
> > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > +
> > > > > +title: Maxim max25014 backlight controller
> > > > > +
> > > > > +maintainers:
> > > > > +  - Maud Spierings <maudspierings@gocontroll.com>
> > > > > +
> > > > > +properties:
> > > > > +  compatible:
> > > > > +    enum:
> > > > > +      - maxim,max25014
> > > > > +
> > > > > +  reg:
> > > > > +    maxItems: 1
> > > > > +
> > > > > +  "#address-cells":
> > > > > +    const: 1
> > > > > +
> > > > > +  "#size-cells":
> > > > > +    const: 0
> > > > > +
> > > > > +  enable-gpios:
> > > > > +    maxItems: 1
> > > > > +
> > > > > +  interrupts:
> > > > > +    maxItems: 1
> > > > > +
> > > > > +  power-supply:
> > > > > +    description: Regulator which controls the boost converter input rail.
> > > > > +
> > > > > +  pwms:
> > > > > +    maxItems: 1
> > > > > +
> > > > > +  maxim,iset:
> > > > > +    $ref: /schemas/types.yaml#/definitions/uint32
> > > > > +    maximum: 15
> > > > > +    default: 11
> > > > > +    description:
> > > > > +      Value of the ISET field in the ISET register. This controls the current
> > > > > +      scale of the outputs, a higher number means more current.
> > > > > +
> > > > > +  led@0:
> > > > 
> > > > define whole binding, allow 0-3. binding is not related with driver's
> > > > implement.
> > > > 
> > > > it'd better put unders leds.
> > > > 
> > > 
> > > so like:
> > > 
> > > backlight: backlight@6f {
> > > 	compatible = "maxim,max25014";
> > > 	reg = <0x6f>;
> > > 	enable-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
> > > 	pinctrl-names = "default";
> > > 	pinctrl-0 = <&pinctrl_backlight>;
> > > 	maxim,iset = <7>;
> > > 
> > > 	leds {
> > > 		#address-cells = <1>;
> > > 		#size-cells = <0>;
> > > 
> > > 		led@0 {
> > > 			reg = <0>;
> > > 			led-sources = <0 1 2>;
> > > 			default-brightness = <50>;
> > > 		};
> > > 
> > > 		optional led@#....
> > > 	};
> > > };
> > > 
> > > right?
> > 
> > yes.
> > 
> 
> I am feeling a bit weird about these led sub nodes, because it is not
> programmed as a led driver, it is programmed as a backlight. I am trying to
> figure out how this would be used later when the led strings are
> individually controllable.
> 
> it isn't possible to link the seperate strings to different displays because
> it is only one backlight device, so I don't seen any reason why it would
> ever be used in another way than what it is now, were all strings are
> programmed by one register.
> 
> The only way I can make sense of it is if instead I program this device as a
> led driver and then use the led_bl driver as the actual backlight.
> 
> Thats a pretty big step in a different direction, but then the led subnodes
> at least can be properly used I feel.

If you don't have any use for anything other than driving a single 
backlight, then I'd just drop the led nodes completely.

Rob

^ permalink raw reply

* Re: [PATCH 0/3] fbdev: Guard sysfs interfaces under CONFIG_FB_DEVICE
From: Andy Shevchenko @ 2025-12-09 14:25 UTC (permalink / raw)
  To: Helge Deller
  Cc: Thomas Zimmermann, Chintan Patel, linux-fbdev, linux-staging,
	linux-omap, linux-kernel, dri-devel, andy, gregkh
In-Reply-To: <f5d50007-5b48-47cb-8133-72fca274d562@gmx.de>

On Tue, Dec 9, 2025 at 10:23 AM Helge Deller <deller@gmx.de> wrote:
> On 12/9/25 08:27, Thomas Zimmermann wrote:

...

> This whole series adds a whole lot of ifdef'ery, which I think is the
> worst approach. It makes the code less readable and leads to two code
> paths, which may trigger different build errors depending on the config.
>
> I'm sure it must be possible to do the same without adding more #ifdefs,
> e.g. by introducing a function like   dev_of_fbinfo(fbinfo)  which
> simply returns NULL for the FB_DEVICE=n case.  Then, that value can be tested
> like
>         if (dev_of_fbinfo(fbinfo))
>                 {...do-the-things...}
> For the FB_DEVICE=n case this will then be optimized out by the compiler,
> while you still have full compiler syntax checking.
>
> Thoughts?

I second you. I am also not a fan of ifdeffery when it can be avoided.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* Re: [PATCH v2 14/19] video/vga: Add VGA_IS0_R
From: Jani Nikula @ 2025-12-09 10:55 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx; +Cc: intel-xe, Helge Deller, linux-fbdev, dri-devel
In-Reply-To: <20251209075549.14051-1-ville.syrjala@linux.intel.com>

On Tue, 09 Dec 2025, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Add a proper name for the "Input status register 0" IO address.
> Currently we have some code that does read addressed using the
> aliasing VGA_MSR_W define, making it unclear what register we're
> actually reading.
>
> v2: Remove stray '?'
>
> Cc: Helge Deller <deller@gmx.de>
> Cc: linux-fbdev@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> ---
>  include/video/vga.h | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/include/video/vga.h b/include/video/vga.h
> index 468764d6727a..2f13c371800b 100644
> --- a/include/video/vga.h
> +++ b/include/video/vga.h
> @@ -46,6 +46,7 @@
>  #define VGA_MIS_R   	0x3CC	/* Misc Output Read Register */
>  #define VGA_MIS_W   	0x3C2	/* Misc Output Write Register */
>  #define VGA_FTC_R	0x3CA	/* Feature Control Read Register */
> +#define VGA_IS0_R	0x3C2	/* Input Status Register 0 */
>  #define VGA_IS1_RC  	0x3DA	/* Input Status Register 1 - color emulation */
>  #define VGA_IS1_RM  	0x3BA	/* Input Status Register 1 - mono emulation */
>  #define VGA_PEL_D   	0x3C9	/* PEL Data Register */

-- 
Jani Nikula, Intel

^ permalink raw reply

* Re: [PATCH] riva/fbdev: fix divide error in nv3_arb()
From: kernel test robot @ 2025-12-09  9:02 UTC (permalink / raw)
  To: Guangshuo Li, Antonino Daplas, Helge Deller, linux-fbdev,
	dri-devel, linux-kernel
  Cc: oe-kbuild-all, Guangshuo Li, stable
In-Reply-To: <20251207072532.518547-1-lgs201920130244@gmail.com>

Hi Guangshuo,

kernel test robot noticed the following build warnings:

[auto build test WARNING on drm-misc/drm-misc-next]
[also build test WARNING on drm-tip/drm-tip linus/master v6.18 next-20251209]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Guangshuo-Li/riva-fbdev-fix-divide-error-in-nv3_arb/20251207-152840
base:   https://gitlab.freedesktop.org/drm/misc/kernel.git drm-misc-next
patch link:    https://lore.kernel.org/r/20251207072532.518547-1-lgs201920130244%40gmail.com
patch subject: [PATCH] riva/fbdev: fix divide error in nv3_arb()
config: x86_64-randconfig-161-20251209 (https://download.01.org/0day-ci/archive/20251209/202512091641.0Nz2KxpF-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512091641.0Nz2KxpF-lkp@intel.com/

New smatch warnings:
drivers/video/fbdev/riva/riva_hw.c:439 nv3_arb() warn: inconsistent indenting

Old smatch warnings:
drivers/video/fbdev/riva/riva_hw.c:982 nv10CalcArbitration() warn: inconsistent indenting

vim +439 drivers/video/fbdev/riva/riva_hw.c

   154	
   155	typedef struct {
   156	  int gdrain_rate;
   157	  int vdrain_rate;
   158	  int mdrain_rate;
   159	  int gburst_size;
   160	  int vburst_size;
   161	  char vid_en;
   162	  char gr_en;
   163	  int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm;
   164	  int by_gfacc;
   165	  char vid_only_once;
   166	  char gr_only_once;
   167	  char first_vacc;
   168	  char first_gacc;
   169	  char first_macc;
   170	  int vocc;
   171	  int gocc;
   172	  int mocc;
   173	  char cur;
   174	  char engine_en;
   175	  char converged;
   176	  int priority;
   177	} nv3_arb_info;
   178	typedef struct {
   179	  int graphics_lwm;
   180	  int video_lwm;
   181	  int graphics_burst_size;
   182	  int video_burst_size;
   183	  int graphics_hi_priority;
   184	  int media_hi_priority;
   185	  int rtl_values;
   186	  int valid;
   187	} nv3_fifo_info;
   188	typedef struct {
   189	  char pix_bpp;
   190	  char enable_video;
   191	  char gr_during_vid;
   192	  char enable_mp;
   193	  int memory_width;
   194	  int video_scale;
   195	  int pclk_khz;
   196	  int mclk_khz;
   197	  int mem_page_miss;
   198	  int mem_latency;
   199	  char mem_aligned;
   200	} nv3_sim_state;
   201	typedef struct {
   202	  int graphics_lwm;
   203	  int video_lwm;
   204	  int graphics_burst_size;
   205	  int video_burst_size;
   206	  int valid;
   207	} nv4_fifo_info;
   208	typedef struct {
   209	  int pclk_khz;
   210	  int mclk_khz;
   211	  int nvclk_khz;
   212	  char mem_page_miss;
   213	  char mem_latency;
   214	  int memory_width;
   215	  char enable_video;
   216	  char gr_during_vid;
   217	  char pix_bpp;
   218	  char mem_aligned;
   219	  char enable_mp;
   220	} nv4_sim_state;
   221	typedef struct {
   222	  int graphics_lwm;
   223	  int video_lwm;
   224	  int graphics_burst_size;
   225	  int video_burst_size;
   226	  int valid;
   227	} nv10_fifo_info;
   228	typedef struct {
   229	  int pclk_khz;
   230	  int mclk_khz;
   231	  int nvclk_khz;
   232	  char mem_page_miss;
   233	  char mem_latency;
   234	  u32 memory_type;
   235	  int memory_width;
   236	  char enable_video;
   237	  char gr_during_vid;
   238	  char pix_bpp;
   239	  char mem_aligned;
   240	  char enable_mp;
   241	} nv10_sim_state;
   242	static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
   243	{
   244	    int iter = 0;
   245	    int tmp;
   246	    int vfsize, mfsize, gfsize;
   247	    int mburst_size = 32;
   248	    int mmisses, gmisses, vmisses;
   249	    int misses;
   250	    int vlwm, glwm;
   251	    int last, next, cur;
   252	    int max_gfsize ;
   253	    long ns;
   254	
   255	    vlwm = 0;
   256	    glwm = 0;
   257	    vfsize = 0;
   258	    gfsize = 0;
   259	    cur = ainfo->cur;
   260	    mmisses = 2;
   261	    gmisses = 2;
   262	    vmisses = 2;
   263	    if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128;
   264	    else  max_gfsize = GFIFO_SIZE;
   265	    max_gfsize = GFIFO_SIZE;
   266	    while (1)
   267	    {
   268	        if (ainfo->vid_en)
   269	        {
   270	            if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc;
   271	            if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ;
   272	            ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
   273	            vfsize = ns * ainfo->vdrain_rate / 1000000;
   274	            vfsize =  ainfo->wcvlwm - ainfo->vburst_size + vfsize;
   275	        }
   276	        if (state->enable_mp)
   277	        {
   278	            if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc;
   279	        }
   280	        if (ainfo->gr_en)
   281	        {
   282	            if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ;
   283	            if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc;
   284	            ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
   285	            gfsize = (ns * (long) ainfo->gdrain_rate)/1000000;
   286	            gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize;
   287	        }
   288	        mfsize = 0;
   289	        if (!state->gr_during_vid && ainfo->vid_en)
   290	            if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once)
   291	                next = VIDEO;
   292	            else if (ainfo->mocc < 0)
   293	                next = MPORT;
   294	            else if (ainfo->gocc< ainfo->by_gfacc)
   295	                next = GRAPHICS;
   296	            else return (0);
   297	        else switch (ainfo->priority)
   298	            {
   299	                case VIDEO:
   300	                    if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
   301	                        next = VIDEO;
   302	                    else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
   303	                        next = GRAPHICS;
   304	                    else if (ainfo->mocc<0)
   305	                        next = MPORT;
   306	                    else    return (0);
   307	                    break;
   308	                case GRAPHICS:
   309	                    if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
   310	                        next = GRAPHICS;
   311	                    else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
   312	                        next = VIDEO;
   313	                    else if (ainfo->mocc<0)
   314	                        next = MPORT;
   315	                    else    return (0);
   316	                    break;
   317	                default:
   318	                    if (ainfo->mocc<0)
   319	                        next = MPORT;
   320	                    else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
   321	                        next = GRAPHICS;
   322	                    else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
   323	                        next = VIDEO;
   324	                    else    return (0);
   325	                    break;
   326	            }
   327	        last = cur;
   328	        cur = next;
   329	        iter++;
   330	        switch (cur)
   331	        {
   332	            case VIDEO:
   333	                if (last==cur)    misses = 0;
   334	                else if (ainfo->first_vacc)   misses = vmisses;
   335	                else    misses = 1;
   336	                ainfo->first_vacc = 0;
   337	                if (last!=cur)
   338	                {
   339	                    ns =  1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; 
   340	                    vlwm = ns * ainfo->vdrain_rate/ 1000000;
   341	                    vlwm = ainfo->vocc - vlwm;
   342	                }
   343	                ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz;
   344	                ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000;
   345	                ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000;
   346	                ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000;
   347	                break;
   348	            case GRAPHICS:
   349	                if (last==cur)    misses = 0;
   350	                else if (ainfo->first_gacc)   misses = gmisses;
   351	                else    misses = 1;
   352	                ainfo->first_gacc = 0;
   353	                if (last!=cur)
   354	                {
   355	                    ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ;
   356	                    glwm = ns * ainfo->gdrain_rate/1000000;
   357	                    glwm = ainfo->gocc - glwm;
   358	                }
   359	                ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
   360	                ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
   361	                ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000;
   362	                ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000;
   363	                break;
   364	            default:
   365	                if (last==cur)    misses = 0;
   366	                else if (ainfo->first_macc)   misses = mmisses;
   367	                else    misses = 1;
   368	                ainfo->first_macc = 0;
   369	                ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz;
   370	                ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
   371	                ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000;
   372	                ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000;
   373	                break;
   374	        }
   375	        if (iter>100)
   376	        {
   377	            ainfo->converged = 0;
   378	            return (1);
   379	        }
   380	        ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz;
   381	        tmp = ns * ainfo->gdrain_rate/1000000;
   382	        if (abs(ainfo->gburst_size) + ((abs(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize)
   383	        {
   384	            ainfo->converged = 0;
   385	            return (1);
   386	        }
   387	        ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
   388	        tmp = ns * ainfo->vdrain_rate/1000000;
   389	        if (abs(ainfo->vburst_size) + (abs(ainfo->wcvlwm + 32) & ~0xf)  - tmp> VFIFO_SIZE)
   390	        {
   391	            ainfo->converged = 0;
   392	            return (1);
   393	        }
   394	        if (abs(ainfo->gocc) > max_gfsize)
   395	        {
   396	            ainfo->converged = 0;
   397	            return (1);
   398	        }
   399	        if (abs(ainfo->vocc) > VFIFO_SIZE)
   400	        {
   401	            ainfo->converged = 0;
   402	            return (1);
   403	        }
   404	        if (abs(ainfo->mocc) > MFIFO_SIZE)
   405	        {
   406	            ainfo->converged = 0;
   407	            return (1);
   408	        }
   409	        if (abs(vfsize) > VFIFO_SIZE)
   410	        {
   411	            ainfo->converged = 0;
   412	            return (1);
   413	        }
   414	        if (abs(gfsize) > max_gfsize)
   415	        {
   416	            ainfo->converged = 0;
   417	            return (1);
   418	        }
   419	        if (abs(mfsize) > MFIFO_SIZE)
   420	        {
   421	            ainfo->converged = 0;
   422	            return (1);
   423	        }
   424	    }
   425	}
   426	static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state,  nv3_arb_info *ainfo) 
   427	{
   428	    long ens, vns, mns, gns;
   429	    int mmisses, gmisses, vmisses, eburst_size, mburst_size;
   430	    int refresh_cycle;
   431	
   432	    refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5;
   433	    mmisses = 2;
   434	    if (state->mem_aligned) gmisses = 2;
   435	    else    gmisses = 3;
   436	    vmisses = 2;
   437	    eburst_size = state->memory_width * 1;
   438	    mburst_size = 32;
 > 439		if (!state->mclk_khz)
   440			return (0);
   441	
   442	    gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
   443	    ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000;
   444	    ainfo->wcmocc = 0;
   445	    ainfo->wcgocc = 0;
   446	    ainfo->wcvocc = 0;
   447	    ainfo->wcvlwm = 0;
   448	    ainfo->wcglwm = 0;
   449	    ainfo->engine_en = 1;
   450	    ainfo->converged = 1;
   451	    if (ainfo->engine_en)
   452	    {
   453	        ens =  1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz;
   454	        ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0;
   455	        ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0;
   456	        ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0;
   457	        ainfo->cur = ENGINE;
   458	        ainfo->first_vacc = 1;
   459	        ainfo->first_gacc = 1;
   460	        ainfo->first_macc = 1;
   461	        nv3_iterate(res_info, state,ainfo);
   462	    }
   463	    if (state->enable_mp)
   464	    {
   465	        mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
   466	        ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000;
   467	        ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000;
   468	        ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000;
   469	        ainfo->cur = MPORT;
   470	        ainfo->first_vacc = 1;
   471	        ainfo->first_gacc = 1;
   472	        ainfo->first_macc = 0;
   473	        nv3_iterate(res_info, state,ainfo);
   474	    }
   475	    if (ainfo->gr_en)
   476	    {
   477	        ainfo->first_vacc = 1;
   478	        ainfo->first_gacc = 0;
   479	        ainfo->first_macc = 1;
   480	        gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
   481	        ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000;
   482	        ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0;
   483	        ainfo->mocc = state->enable_mp ?  0-gns*ainfo->mdrain_rate/1000000: 0;
   484	        ainfo->cur = GRAPHICS;
   485	        nv3_iterate(res_info, state,ainfo);
   486	    }
   487	    if (ainfo->vid_en)
   488	    {
   489	        ainfo->first_vacc = 0;
   490	        ainfo->first_gacc = 1;
   491	        ainfo->first_macc = 1;
   492	        vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
   493	        ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000;
   494	        ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0;
   495	        ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ;
   496	        ainfo->cur = VIDEO;
   497	        nv3_iterate(res_info, state, ainfo);
   498	    }
   499	    if (ainfo->converged)
   500	    {
   501	        res_info->graphics_lwm = (int)abs(ainfo->wcglwm) + 16;
   502	        res_info->video_lwm = (int)abs(ainfo->wcvlwm) + 32;
   503	        res_info->graphics_burst_size = ainfo->gburst_size;
   504	        res_info->video_burst_size = ainfo->vburst_size;
   505	        res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS);
   506	        res_info->media_hi_priority = (ainfo->priority == MPORT);
   507	        if (res_info->video_lwm > 160)
   508	        {
   509	            res_info->graphics_lwm = 256;
   510	            res_info->video_lwm = 128;
   511	            res_info->graphics_burst_size = 64;
   512	            res_info->video_burst_size = 64;
   513	            res_info->graphics_hi_priority = 0;
   514	            res_info->media_hi_priority = 0;
   515	            ainfo->converged = 0;
   516	            return (0);
   517	        }
   518	        if (res_info->video_lwm > 128)
   519	        {
   520	            res_info->video_lwm = 128;
   521	        }
   522	        return (1);
   523	    }
   524	    else
   525	    {
   526	        res_info->graphics_lwm = 256;
   527	        res_info->video_lwm = 128;
   528	        res_info->graphics_burst_size = 64;
   529	        res_info->video_burst_size = 64;
   530	        res_info->graphics_hi_priority = 0;
   531	        res_info->media_hi_priority = 0;
   532	        return (0);
   533	    }
   534	}
   535	static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
   536	{
   537	    int done, g,v, p;
   538	    
   539	    done = 0;
   540	    for (p=0; p < 2; p++)
   541	    {
   542	        for (g=128 ; g > 32; g= g>> 1)
   543	        {
   544	            for (v=128; v >=32; v = v>> 1)
   545	            {
   546	                ainfo->priority = p;
   547	                ainfo->gburst_size = g;     
   548	                ainfo->vburst_size = v;
   549	                done = nv3_arb(res_info, state,ainfo);
   550	                if (done && (g==128))
   551	                    if ((res_info->graphics_lwm + g) > 256)
   552	                        done = 0;
   553	                if (done)
   554	                    goto Done;
   555	            }
   556	        }
   557	    }
   558	
   559	 Done:
   560	    return done;
   561	}
   562	static void nv3CalcArbitration 
   563	(
   564	    nv3_fifo_info * res_info,
   565	    nv3_sim_state * state
   566	)
   567	{
   568	    nv3_fifo_info save_info;
   569	    nv3_arb_info ainfo;
   570	    char   res_gr, res_vid;
   571	
   572	    ainfo.gr_en = 1;
   573	    ainfo.vid_en = state->enable_video;
   574	    ainfo.vid_only_once = 0;
   575	    ainfo.gr_only_once = 0;
   576	    ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
   577	    ainfo.vdrain_rate = (int) state->pclk_khz * 2;
   578	    if (state->video_scale != 0)
   579	        ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale;
   580	    ainfo.mdrain_rate = 33000;
   581	    res_info->rtl_values = 0;
   582	    if (!state->gr_during_vid && state->enable_video)
   583	    {
   584	        ainfo.gr_only_once = 1;
   585	        ainfo.gr_en = 1;
   586	        ainfo.gdrain_rate = 0;
   587	        res_vid = nv3_get_param(res_info, state,  &ainfo);
   588	        res_vid = ainfo.converged;
   589	        save_info.video_lwm = res_info->video_lwm;
   590	        save_info.video_burst_size = res_info->video_burst_size;
   591	        ainfo.vid_en = 1;
   592	        ainfo.vid_only_once = 1;
   593	        ainfo.gr_en = 1;
   594	        ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
   595	        ainfo.vdrain_rate = 0;
   596	        res_gr = nv3_get_param(res_info, state,  &ainfo);
   597	        res_gr = ainfo.converged;
   598	        res_info->video_lwm = save_info.video_lwm;
   599	        res_info->video_burst_size = save_info.video_burst_size;
   600	        res_info->valid = res_gr & res_vid;
   601	    }
   602	    else
   603	    {
   604	        if (!ainfo.gr_en) ainfo.gdrain_rate = 0;
   605	        if (!ainfo.vid_en) ainfo.vdrain_rate = 0;
   606	        res_gr = nv3_get_param(res_info, state,  &ainfo);
   607	        res_info->valid = ainfo.converged;
   608	    }
   609	}
   610	static void nv3UpdateArbitrationSettings
   611	(
   612	    unsigned      VClk, 
   613	    unsigned      pixelDepth, 
   614	    unsigned     *burst,
   615	    unsigned     *lwm,
   616	    RIVA_HW_INST *chip
   617	)
   618	{
   619	    nv3_fifo_info fifo_data;
   620	    nv3_sim_state sim_data;
   621	    unsigned int M, N, P, pll, MClk;
   622	    
   623	    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
   624	    M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
   625	    MClk = (N * chip->CrystalFreqKHz / M) >> P;
   626	    sim_data.pix_bpp        = (char)pixelDepth;
   627	    sim_data.enable_video   = 0;
   628	    sim_data.enable_mp      = 0;
   629	    sim_data.video_scale    = 1;
   630	    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
   631		128 : 64;
   632	    sim_data.memory_width   = 128;
   633	
   634	    sim_data.mem_latency    = 9;
   635	    sim_data.mem_aligned    = 1;
   636	    sim_data.mem_page_miss  = 11;
   637	    sim_data.gr_during_vid  = 0;
   638	    sim_data.pclk_khz       = VClk;
   639	    sim_data.mclk_khz       = MClk;
   640	    nv3CalcArbitration(&fifo_data, &sim_data);
   641	    if (fifo_data.valid)
   642	    {
   643	        int  b = fifo_data.graphics_burst_size >> 4;
   644	        *burst = 0;
   645	        while (b >>= 1)
   646		    (*burst)++;
   647	        *lwm   = fifo_data.graphics_lwm >> 3;
   648	    }
   649	    else
   650	    {
   651	        *lwm   = 0x24;
   652	        *burst = 0x2;
   653	    }
   654	}
   655	static void nv4CalcArbitration 
   656	(
   657	    nv4_fifo_info *fifo,
   658	    nv4_sim_state *arb
   659	)
   660	{
   661	    int data, pagemiss, cas,width, video_enable, bpp;
   662	    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
   663	    int found, mclk_extra, mclk_loop, cbs, m1, p1;
   664	    int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
   665	    int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
   666	    int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
   667	
   668	    fifo->valid = 1;
   669	    pclk_freq = arb->pclk_khz;
   670	    mclk_freq = arb->mclk_khz;
   671	    nvclk_freq = arb->nvclk_khz;
   672	    pagemiss = arb->mem_page_miss;
   673	    cas = arb->mem_latency;
   674	    width = arb->memory_width >> 6;
   675	    video_enable = arb->enable_video;
   676	    bpp = arb->pix_bpp;
   677	    mp_enable = arb->enable_mp;
   678	    clwm = 0;
   679	    vlwm = 0;
   680	    cbs = 128;
   681	    pclks = 2;
   682	    nvclks = 2;
   683	    nvclks += 2;
   684	    nvclks += 1;
   685	    mclks = 5;
   686	    mclks += 3;
   687	    mclks += 1;
   688	    mclks += cas;
   689	    mclks += 1;
   690	    mclks += 1;
   691	    mclks += 1;
   692	    mclks += 1;
   693	    mclk_extra = 3;
   694	    nvclks += 2;
   695	    nvclks += 1;
   696	    nvclks += 1;
   697	    nvclks += 1;
   698	    if (mp_enable)
   699	        mclks+=4;
   700	    nvclks += 0;
   701	    pclks += 0;
   702	    found = 0;
   703	    vbs = 0;
   704	    while (found != 1)
   705	    {
   706	        fifo->valid = 1;
   707	        found = 1;
   708	        mclk_loop = mclks+mclk_extra;
   709	        us_m = mclk_loop *1000*1000 / mclk_freq;
   710	        us_n = nvclks*1000*1000 / nvclk_freq;
   711	        us_p = nvclks*1000*1000 / pclk_freq;
   712	        if (video_enable)
   713	        {
   714	            video_drain_rate = pclk_freq * 2;
   715	            crtc_drain_rate = pclk_freq * bpp/8;
   716	            vpagemiss = 2;
   717	            vpagemiss += 1;
   718	            crtpagemiss = 2;
   719	            vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
   720	            if (nvclk_freq * 2 > mclk_freq * width)
   721	                video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
   722	            else
   723	                video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
   724	            us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
   725	            vlwm = us_video * video_drain_rate/(1000*1000);
   726	            vlwm++;
   727	            vbs = 128;
   728	            if (vlwm > 128) vbs = 64;
   729	            if (vlwm > (256-64)) vbs = 32;
   730	            if (nvclk_freq * 2 > mclk_freq * width)
   731	                video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
   732	            else
   733	                video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
   734	            cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
   735	            us_crt =
   736	            us_video
   737	            +video_fill_us
   738	            +cpm_us
   739	            +us_m + us_n +us_p
   740	            ;
   741	            clwm = us_crt * crtc_drain_rate/(1000*1000);
   742	            clwm++;
   743	        }
   744	        else
   745	        {
   746	            crtc_drain_rate = pclk_freq * bpp/8;
   747	            crtpagemiss = 2;
   748	            crtpagemiss += 1;
   749	            cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
   750	            us_crt =  cpm_us + us_m + us_n + us_p ;
   751	            clwm = us_crt * crtc_drain_rate/(1000*1000);
   752	            clwm++;
   753	        }
   754	        m1 = clwm + cbs - 512;
   755	        p1 = m1 * pclk_freq / mclk_freq;
   756	        p1 = p1 * bpp / 8;
   757	        if ((p1 < m1) && (m1 > 0))
   758	        {
   759	            fifo->valid = 0;
   760	            found = 0;
   761	            if (mclk_extra ==0)   found = 1;
   762	            mclk_extra--;
   763	        }
   764	        else if (video_enable)
   765	        {
   766	            if ((clwm > 511) || (vlwm > 255))
   767	            {
   768	                fifo->valid = 0;
   769	                found = 0;
   770	                if (mclk_extra ==0)   found = 1;
   771	                mclk_extra--;
   772	            }
   773	        }
   774	        else
   775	        {
   776	            if (clwm > 519)
   777	            {
   778	                fifo->valid = 0;
   779	                found = 0;
   780	                if (mclk_extra ==0)   found = 1;
   781	                mclk_extra--;
   782	            }
   783	        }
   784	        if (clwm < 384) clwm = 384;
   785	        if (vlwm < 128) vlwm = 128;
   786	        data = (int)(clwm);
   787	        fifo->graphics_lwm = data;
   788	        fifo->graphics_burst_size = 128;
   789	        data = (int)((vlwm+15));
   790	        fifo->video_lwm = data;
   791	        fifo->video_burst_size = vbs;
   792	    }
   793	}
   794	static void nv4UpdateArbitrationSettings
   795	(
   796	    unsigned      VClk, 
   797	    unsigned      pixelDepth, 
   798	    unsigned     *burst,
   799	    unsigned     *lwm,
   800	    RIVA_HW_INST *chip
   801	)
   802	{
   803	    nv4_fifo_info fifo_data;
   804	    nv4_sim_state sim_data;
   805	    unsigned int M, N, P, pll, MClk, NVClk, cfg1;
   806	
   807	    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
   808	    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
   809	    MClk  = (N * chip->CrystalFreqKHz / M) >> P;
   810	    pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
   811	    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
   812	    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
   813	    cfg1 = NV_RD32(&chip->PFB[0x00000204/4], 0);
   814	    sim_data.pix_bpp        = (char)pixelDepth;
   815	    sim_data.enable_video   = 0;
   816	    sim_data.enable_mp      = 0;
   817	    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
   818		128 : 64;
   819	    sim_data.mem_latency    = (char)cfg1 & 0x0F;
   820	    sim_data.mem_aligned    = 1;
   821	    sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
   822	    sim_data.gr_during_vid  = 0;
   823	    sim_data.pclk_khz       = VClk;
   824	    sim_data.mclk_khz       = MClk;
   825	    sim_data.nvclk_khz      = NVClk;
   826	    nv4CalcArbitration(&fifo_data, &sim_data);
   827	    if (fifo_data.valid)
   828	    {
   829	        int  b = fifo_data.graphics_burst_size >> 4;
   830	        *burst = 0;
   831	        while (b >>= 1)
   832		    (*burst)++;
   833	        *lwm   = fifo_data.graphics_lwm >> 3;
   834	    }
   835	}
   836	static void nv10CalcArbitration 
   837	(
   838	    nv10_fifo_info *fifo,
   839	    nv10_sim_state *arb
   840	)
   841	{
   842	    int data, pagemiss, width, video_enable, bpp;
   843	    int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
   844	    int nvclk_fill;
   845	    int found, mclk_extra, mclk_loop, cbs, m1;
   846	    int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
   847	    int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
   848	    int vus_m;
   849	    int vpm_us, us_video, cpm_us, us_crt,clwm;
   850	    int clwm_rnd_down;
   851	    int m2us, us_pipe_min, p1clk, p2;
   852	    int min_mclk_extra;
   853	    int us_min_mclk_extra;
   854	
   855	    fifo->valid = 1;
   856	    pclk_freq = arb->pclk_khz; /* freq in KHz */
   857	    mclk_freq = arb->mclk_khz;
   858	    nvclk_freq = arb->nvclk_khz;
   859	    pagemiss = arb->mem_page_miss;
   860	    width = arb->memory_width/64;
   861	    video_enable = arb->enable_video;
   862	    bpp = arb->pix_bpp;
   863	    mp_enable = arb->enable_mp;
   864	    clwm = 0;
   865	
   866	    cbs = 512;
   867	
   868	    pclks = 4; /* lwm detect. */
   869	
   870	    nvclks = 3; /* lwm -> sync. */
   871	    nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
   872	
   873	    mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
   874	
   875	    mclks += 1;   /* arb_hp_req */
   876	    mclks += 5;   /* ap_hp_req   tiling pipeline */
   877	
   878	    mclks += 2;    /* tc_req     latency fifo */
   879	    mclks += 2;    /* fb_cas_n_  memory request to fbio block */
   880	    mclks += 7;    /* sm_d_rdv   data returned from fbio block */
   881	
   882	    /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
   883	    if (arb->memory_type == 0)
   884	      if (arb->memory_width == 64) /* 64 bit bus */
   885	        mclks += 4;
   886	      else
   887	        mclks += 2;
   888	    else
   889	      if (arb->memory_width == 64) /* 64 bit bus */
   890	        mclks += 2;
   891	      else
   892	        mclks += 1;
   893	
   894	    if ((!video_enable) && (arb->memory_width == 128))
   895	    {  
   896	      mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
   897	      min_mclk_extra = 17;
   898	    }
   899	    else
   900	    {
   901	      mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
   902	      /* mclk_extra = 4; */ /* Margin of error */
   903	      min_mclk_extra = 18;
   904	    }
   905	
   906	    nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
   907	    nvclks += 1; /* fbi_d_rdv_n */
   908	    nvclks += 1; /* Fbi_d_rdata */
   909	    nvclks += 1; /* crtfifo load */
   910	
   911	    if(mp_enable)
   912	      mclks+=4; /* Mp can get in with a burst of 8. */
   913	    /* Extra clocks determined by heuristics */
   914	
   915	    nvclks += 0;
   916	    pclks += 0;
   917	    found = 0;
   918	    while(found != 1) {
   919	      fifo->valid = 1;
   920	      found = 1;
   921	      mclk_loop = mclks+mclk_extra;
   922	      us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
   923	      us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
   924	      us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
   925	      us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
   926	      us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
   927	      us_pipe_min = us_m_min + us_n + us_p;
   928	
   929	      vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
   930	
   931	      if(video_enable) {
   932	        crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
   933	
   934	        vpagemiss = 1; /* self generating page miss */
   935	        vpagemiss += 1; /* One higher priority before */
   936	
   937	        crtpagemiss = 2; /* self generating page miss */
   938	        if(mp_enable)
   939	            crtpagemiss += 1; /* if MA0 conflict */
   940	
   941	        vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
   942	
   943	        us_video = vpm_us + vus_m; /* Video has separate read return path */
   944	
   945	        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
   946	        us_crt =
   947	          us_video  /* Wait for video */
   948	          +cpm_us /* CRT Page miss */
   949	          +us_m + us_n +us_p /* other latency */
   950	          ;
   951	
   952	        clwm = us_crt * crtc_drain_rate/(1000*1000);
   953	        clwm++; /* fixed point <= float_point - 1.  Fixes that */
   954	      } else {
   955	        crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
   956	
   957	        crtpagemiss = 1; /* self generating page miss */
   958	        crtpagemiss += 1; /* MA0 page miss */
   959	        if(mp_enable)
   960	            crtpagemiss += 1; /* if MA0 conflict */
   961	        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
   962	        us_crt =  cpm_us + us_m + us_n + us_p ;
   963	        clwm = us_crt * crtc_drain_rate/(1000*1000);
   964	        clwm++; /* fixed point <= float_point - 1.  Fixes that */
   965	
   966	  /*
   967	          //
   968	          // Another concern, only for high pclks so don't do this
   969	          // with video:
   970	          // What happens if the latency to fetch the cbs is so large that
   971	          // fifo empties.  In that case we need to have an alternate clwm value
   972	          // based off the total burst fetch
   973	          //
   974	          us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
   975	          us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq;
   976	          clwm_mt = us_crt * crtc_drain_rate/(1000*1000);
   977	          clwm_mt ++;
   978	          if(clwm_mt > clwm)
   979	              clwm = clwm_mt;
   980	  */
   981	          /* Finally, a heuristic check when width == 64 bits */
   982	          if(width == 1){
   983	              nvclk_fill = nvclk_freq * 8;
   984	              if(crtc_drain_rate * 100 >= nvclk_fill * 102)
   985	                      clwm = 0xfff; /*Large number to fail */
   986	
   987	              else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
   988	                  clwm = 1024;
   989	                  cbs = 512;
   990	              }
   991	          }
   992	      }
   993	
   994	
   995	      /*
   996	        Overfill check:
   997	
   998	        */
   999	
  1000	      clwm_rnd_down = ((int)clwm/8)*8;
  1001	      if (clwm_rnd_down < clwm)
  1002	          clwm += 8;
  1003	
  1004	      m1 = clwm + cbs -  1024; /* Amount of overfill */
  1005	      m2us = us_pipe_min + us_min_mclk_extra;
  1006	
  1007	      /* pclk cycles to drain */
  1008	      p1clk = m2us * pclk_freq/(1000*1000); 
  1009	      p2 = p1clk * bpp / 8; /* bytes drained. */
  1010	
  1011	      if((p2 < m1) && (m1 > 0)) {
  1012	          fifo->valid = 0;
  1013	          found = 0;
  1014	          if(min_mclk_extra == 0)   {
  1015	            if(cbs <= 32) {
  1016	              found = 1; /* Can't adjust anymore! */
  1017	            } else {
  1018	              cbs = cbs/2;  /* reduce the burst size */
  1019	            }
  1020	          } else {
  1021	            min_mclk_extra--;
  1022	          }
  1023	      } else {
  1024	        if (clwm > 1023){ /* Have some margin */
  1025	          fifo->valid = 0;
  1026	          found = 0;
  1027	          if(min_mclk_extra == 0)   
  1028	              found = 1; /* Can't adjust anymore! */
  1029	          else 
  1030	              min_mclk_extra--;
  1031	        }
  1032	      }
  1033	
  1034	      if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
  1035	      data = (int)(clwm);
  1036	      /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
  1037	      fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
  1038	
  1039	      /*  printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */
  1040	      fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
  1041	    }
  1042	}
  1043	static void nv10UpdateArbitrationSettings
  1044	(
  1045	    unsigned      VClk, 
  1046	    unsigned      pixelDepth, 
  1047	    unsigned     *burst,
  1048	    unsigned     *lwm,
  1049	    RIVA_HW_INST *chip
  1050	)
  1051	{
  1052	    nv10_fifo_info fifo_data;
  1053	    nv10_sim_state sim_data;
  1054	    unsigned int M, N, P, pll, MClk, NVClk, cfg1;
  1055	
  1056	    pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
  1057	    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
  1058	    MClk  = (N * chip->CrystalFreqKHz / M) >> P;
  1059	    pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
  1060	    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
  1061	    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
  1062	    cfg1 = NV_RD32(&chip->PFB[0x00000204/4], 0);
  1063	    sim_data.pix_bpp        = (char)pixelDepth;
  1064	    sim_data.enable_video   = 0;
  1065	    sim_data.enable_mp      = 0;
  1066	    sim_data.memory_type    = (NV_RD32(&chip->PFB[0x00000200/4], 0) & 0x01) ?
  1067		1 : 0;
  1068	    sim_data.memory_width   = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
  1069		128 : 64;
  1070	    sim_data.mem_latency    = (char)cfg1 & 0x0F;
  1071	    sim_data.mem_aligned    = 1;
  1072	    sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
  1073	    sim_data.gr_during_vid  = 0;
  1074	    sim_data.pclk_khz       = VClk;
  1075	    sim_data.mclk_khz       = MClk;
  1076	    sim_data.nvclk_khz      = NVClk;
  1077	    nv10CalcArbitration(&fifo_data, &sim_data);
  1078	    if (fifo_data.valid)
  1079	    {
  1080	        int  b = fifo_data.graphics_burst_size >> 4;
  1081	        *burst = 0;
  1082	        while (b >>= 1)
  1083		    (*burst)++;
  1084	        *lwm   = fifo_data.graphics_lwm >> 3;
  1085	    }
  1086	}
  1087	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH 0/3] fbdev: Guard sysfs interfaces under CONFIG_FB_DEVICE
From: Thomas Zimmermann @ 2025-12-09  8:42 UTC (permalink / raw)
  To: Helge Deller, Chintan Patel, linux-fbdev, linux-staging,
	linux-omap
  Cc: linux-kernel, dri-devel, andy, gregkh
In-Reply-To: <f5d50007-5b48-47cb-8133-72fca274d562@gmx.de>

Hi

Am 09.12.25 um 09:22 schrieb Helge Deller:
> On 12/9/25 08:27, Thomas Zimmermann wrote:
>> Hi
>>
>> Am 09.12.25 um 05:27 schrieb Chintan Patel:
>>> Hi all,
>>>
>>> This small series makes several legacy fbdev drivers buildable with
>>> CONFIG_FB_DEVICE=n. Currently, multiple fbdev drivers rely on 
>>> fb_info->dev
>>> and sysfs attribute registration unconditionally, which leads to build
>>> failures whenever FB_DEVICE is disabled.
>>>
>>> Thomas previously noted that FB_DEVICE should eventually become 
>>> optional
>>> and that drivers should not depend on sysfs or fb_info->dev being 
>>> present
>>> unless the Kconfig explicitly selects it. This series pushes in that
>>> direction by tightening the FB_DEVICE dependency boundary without 
>>> changing
>>> any runtime behaviour when FB_DEVICE=y.
>>>
>>> What this series does *not* change
>>>
>>> - No functional behaviour changes when FB_DEVICE=y.
>>> - No removal of sysfs interfaces.
>>> - No changes to fbops, memory allocation, or display update paths.
>>>
>>> Build & test coverage
>>>
>>> Tested with the following combinations:
>>>
>>> 1. **FB=y, FB_DEVICE=y**
>>>     - Baseline configuration; no regressions expected.
>>>
>>> 2. **FB=y, FB_DEVICE=n**
>>>     - Drivers build successfully.
>>>     - No sysfs attributes are created.
>>>     - fbdev devices operate normally (where applicable).
>>>
>>> 3. **FB=n**
>>>     - Drivers depend on FB, so they properly do not build, unchanged.
>>>
>>> Motivation
>>>
>>> This moves fbdev closer to supporting FB_DEVICE as truly optional, 
>>> helps
>>> reduce Kconfig entanglement, and clears several long-standing TODO 
>>> items
>>> as suggested by Thomas Zimmermann around legacy sysfs usage inside 
>>> fbdev
>>> drivers.
>>>
>>> Feedback is welcome, especially on whether the guard boundaries around
>>> sysfs are placed correctly or whether more logic should be pulled under
>>> CONFIG_FB_DEVICE.
>>
>> I left a comment on the first patch. If things still build nicely, then
>>
>> Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
>>
>> for the series.
>
> This whole series adds a whole lot of ifdef'ery, which I think is the
> worst approach. It makes the code less readable and leads to two code
> paths, which may trigger different build errors depending on the config.
>
> I'm sure it must be possible to do the same without adding more #ifdefs,
> e.g. by introducing a function like   dev_of_fbinfo(fbinfo)  which
> simply returns NULL for the FB_DEVICE=n case.  Then, that value can be 
> tested
> like
>     if (dev_of_fbinfo(fbinfo))
>         {...do-the-things...}
> For the FB_DEVICE=n case this will then be optimized out by the compiler,
> while you still have full compiler syntax checking.
>
> Thoughts?

Your choice. I don't see this as an important fix. The FB_DEVICE=n case 
is mostly useful for DRM-based systems that do not want to expose fbdev 
interfaces to user space. Those are the vast majority today. The very 
few special builds with fbdev drivers would likely use FB_DEVICE=y anyway.

Best regards
Thomas

>
> Helge
>

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)



^ permalink raw reply

* Re: [PATCH 0/3] fbdev: Guard sysfs interfaces under CONFIG_FB_DEVICE
From: Helge Deller @ 2025-12-09  8:22 UTC (permalink / raw)
  To: Thomas Zimmermann, Chintan Patel, linux-fbdev, linux-staging,
	linux-omap
  Cc: linux-kernel, dri-devel, andy, gregkh
In-Reply-To: <19e8a1b0-75e3-4c8d-911a-15fd70f60bea@suse.de>

On 12/9/25 08:27, Thomas Zimmermann wrote:
> Hi
> 
> Am 09.12.25 um 05:27 schrieb Chintan Patel:
>> Hi all,
>>
>> This small series makes several legacy fbdev drivers buildable with
>> CONFIG_FB_DEVICE=n. Currently, multiple fbdev drivers rely on fb_info->dev
>> and sysfs attribute registration unconditionally, which leads to build
>> failures whenever FB_DEVICE is disabled.
>>
>> Thomas previously noted that FB_DEVICE should eventually become optional
>> and that drivers should not depend on sysfs or fb_info->dev being present
>> unless the Kconfig explicitly selects it. This series pushes in that
>> direction by tightening the FB_DEVICE dependency boundary without changing
>> any runtime behaviour when FB_DEVICE=y.
>>
>> What this series does *not* change
>>
>> - No functional behaviour changes when FB_DEVICE=y.
>> - No removal of sysfs interfaces.
>> - No changes to fbops, memory allocation, or display update paths.
>>
>> Build & test coverage
>>
>> Tested with the following combinations:
>>
>> 1. **FB=y, FB_DEVICE=y**
>>     - Baseline configuration; no regressions expected.
>>
>> 2. **FB=y, FB_DEVICE=n**
>>     - Drivers build successfully.
>>     - No sysfs attributes are created.
>>     - fbdev devices operate normally (where applicable).
>>
>> 3. **FB=n**
>>     - Drivers depend on FB, so they properly do not build, unchanged.
>>
>> Motivation
>>
>> This moves fbdev closer to supporting FB_DEVICE as truly optional, helps
>> reduce Kconfig entanglement, and clears several long-standing TODO items
>> as suggested by Thomas Zimmermann around legacy sysfs usage inside fbdev
>> drivers.
>>
>> Feedback is welcome, especially on whether the guard boundaries around
>> sysfs are placed correctly or whether more logic should be pulled under
>> CONFIG_FB_DEVICE.
> 
> I left a comment on the first patch. If things still build nicely, then
> 
> Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
> 
> for the series.

This whole series adds a whole lot of ifdef'ery, which I think is the
worst approach. It makes the code less readable and leads to two code
paths, which may trigger different build errors depending on the config.

I'm sure it must be possible to do the same without adding more #ifdefs,
e.g. by introducing a function like   dev_of_fbinfo(fbinfo)  which
simply returns NULL for the FB_DEVICE=n case.  Then, that value can be tested
like
	if (dev_of_fbinfo(fbinfo))
		{...do-the-things...}
For the FB_DEVICE=n case this will then be optimized out by the compiler,
while you still have full compiler syntax checking.

Thoughts?

Helge

^ permalink raw reply

* [PATCH v2 14/19] video/vga: Add VGA_IS0_R
From: Ville Syrjala @ 2025-12-09  7:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: intel-xe, Helge Deller, linux-fbdev, dri-devel
In-Reply-To: <20251208182637.334-15-ville.syrjala@linux.intel.com>

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add a proper name for the "Input status register 0" IO address.
Currently we have some code that does read addressed using the
aliasing VGA_MSR_W define, making it unclear what register we're
actually reading.

v2: Remove stray '?'

Cc: Helge Deller <deller@gmx.de>
Cc: linux-fbdev@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/video/vga.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/video/vga.h b/include/video/vga.h
index 468764d6727a..2f13c371800b 100644
--- a/include/video/vga.h
+++ b/include/video/vga.h
@@ -46,6 +46,7 @@
 #define VGA_MIS_R   	0x3CC	/* Misc Output Read Register */
 #define VGA_MIS_W   	0x3C2	/* Misc Output Write Register */
 #define VGA_FTC_R	0x3CA	/* Feature Control Read Register */
+#define VGA_IS0_R	0x3C2	/* Input Status Register 0 */
 #define VGA_IS1_RC  	0x3DA	/* Input Status Register 1 - color emulation */
 #define VGA_IS1_RM  	0x3BA	/* Input Status Register 1 - mono emulation */
 #define VGA_PEL_D   	0x3C9	/* PEL Data Register */
-- 
2.51.2


^ permalink raw reply related

* Re: [PATCH 0/3] fbdev: Guard sysfs interfaces under CONFIG_FB_DEVICE
From: Thomas Zimmermann @ 2025-12-09  7:27 UTC (permalink / raw)
  To: Chintan Patel, linux-fbdev, linux-staging, linux-omap
  Cc: linux-kernel, dri-devel, andy, deller, gregkh
In-Reply-To: <20251209042744.7875-1-chintanlike@gmail.com>

Hi

Am 09.12.25 um 05:27 schrieb Chintan Patel:
> Hi all,
>
> This small series makes several legacy fbdev drivers buildable with
> CONFIG_FB_DEVICE=n. Currently, multiple fbdev drivers rely on fb_info->dev
> and sysfs attribute registration unconditionally, which leads to build
> failures whenever FB_DEVICE is disabled.
>
> Thomas previously noted that FB_DEVICE should eventually become optional
> and that drivers should not depend on sysfs or fb_info->dev being present
> unless the Kconfig explicitly selects it. This series pushes in that
> direction by tightening the FB_DEVICE dependency boundary without changing
> any runtime behaviour when FB_DEVICE=y.
>
> What this series does *not* change
>
> - No functional behaviour changes when FB_DEVICE=y.
> - No removal of sysfs interfaces.
> - No changes to fbops, memory allocation, or display update paths.
>
> Build & test coverage
>
> Tested with the following combinations:
>
> 1. **FB=y, FB_DEVICE=y**
>     - Baseline configuration; no regressions expected.
>
> 2. **FB=y, FB_DEVICE=n**
>     - Drivers build successfully.
>     - No sysfs attributes are created.
>     - fbdev devices operate normally (where applicable).
>
> 3. **FB=n**
>     - Drivers depend on FB, so they properly do not build, unchanged.
>
> Motivation
>
> This moves fbdev closer to supporting FB_DEVICE as truly optional, helps
> reduce Kconfig entanglement, and clears several long-standing TODO items
> as suggested by Thomas Zimmermann around legacy sysfs usage inside fbdev
> drivers.
>
> Feedback is welcome, especially on whether the guard boundaries around
> sysfs are placed correctly or whether more logic should be pulled under
> CONFIG_FB_DEVICE.

I left a comment on the first patch. If things still build nicely, then

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

for the series.

Best regards
Thomas

>
> Thanks,
> Chintan
>
> Chintan Patel (3):
>    fbtft: Make sysfs and dev_*() logging conditional on FB_DEVICE
>    omapfb: Guard sysfs code under CONFIG_FB_DEVICE
>    sh_mobile_lcdc: Guard overlay sysfs interfaces under CONFIG_FB_DEVICE
>
>   drivers/staging/fbtft/fbtft-core.c            | 20 +++++++++++++++++--
>   drivers/staging/fbtft/fbtft-sysfs.c           |  8 ++++++++
>   drivers/video/fbdev/omap2/omapfb/Kconfig      |  2 +-
>   .../video/fbdev/omap2/omapfb/omapfb-sysfs.c   | 11 ++++++++++
>   drivers/video/fbdev/sh_mobile_lcdcfb.c        |  4 ++++
>   5 files changed, 42 insertions(+), 3 deletions(-)
>

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)



^ permalink raw reply

* Re: [PATCH 1/3] fbtft: Make sysfs and dev_*() logging conditional on FB_DEVICE
From: Thomas Zimmermann @ 2025-12-09  7:25 UTC (permalink / raw)
  To: Chintan Patel, linux-fbdev, linux-staging, linux-omap
  Cc: linux-kernel, dri-devel, andy, deller, gregkh
In-Reply-To: <20251209042744.7875-2-chintanlike@gmail.com>

Hi

Am 09.12.25 um 05:27 schrieb Chintan Patel:
> The fbtft core and sysfs implementation unconditionally dereference
> fb_info->dev and register sysfs attributes. When FB_DEVICE=n, these
> fields are unavailable, leading to build failures.
>
> This patch wraps all sysfs attribute creation/removal and dev_dbg/dev_info
> logging in #ifdef CONFIG_FB_DEVICE, with pr_*() fallbacks for the
> non-FB_DEVICE case. This makes fbtft fully buildable when FB_DEVICE is
> disabled.
>
> Signed-off-by: Chintan Patel <chintanlike@gmail.com>
> ---
>   drivers/staging/fbtft/fbtft-core.c  | 20 ++++++++++++++++++--
>   drivers/staging/fbtft/fbtft-sysfs.c |  8 ++++++++
>   2 files changed, 26 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
> index 9e7b84071174..dc967bdeabe8 100644
> --- a/drivers/staging/fbtft/fbtft-core.c
> +++ b/drivers/staging/fbtft/fbtft-core.c
> @@ -365,9 +365,14 @@ static int fbtft_fb_setcolreg(unsigned int regno, unsigned int red,
>   	unsigned int val;
>   	int ret = 1;
>   
> +#ifdef CONFIG_FB_DEVICE
>   	dev_dbg(info->dev,

Rather use fb_dbg() [1] and similar helpers for logging. They only need 
the info pointer and do the correct output by themselves.

[1] https://elixir.bootlin.com/linux/v6.18/source/include/linux/fb.h#L895

>   		"%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n",
>   		__func__, regno, red, green, blue, transp);
> +#else
> +	pr_debug("%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n",
> +		 __func__, regno, red, green, blue, transp);
> +#endif
>   
>   	switch (info->fix.visual) {
>   	case FB_VISUAL_TRUECOLOR:
> @@ -391,8 +396,11 @@ static int fbtft_fb_blank(int blank, struct fb_info *info)
>   	struct fbtft_par *par = info->par;
>   	int ret = -EINVAL;
>   
> -	dev_dbg(info->dev, "%s(blank=%d)\n",
> -		__func__, blank);
> +#ifdef CONFIG_FB_DEVICE
> +	dev_dbg(info->dev, "%s(blank=%d)\n", __func__, blank);
> +#else
> +	pr_debug("%s(blank=%d)\n", __func__, blank);
> +#endif
>   
>   	if (!par->fbtftops.blank)
>   		return ret;
> @@ -793,6 +801,8 @@ int fbtft_register_framebuffer(struct fb_info *fb_info)
>   	if (spi)
>   		sprintf(text2, ", spi%d.%d at %d MHz", spi->controller->bus_num,
>   			spi_get_chipselect(spi, 0), spi->max_speed_hz / 1000000);
> +
> +#ifdef CONFIG_FB_DEVICE
>   	dev_info(fb_info->dev,

Same here with fb_info().

Best regards
Thomas

>   		 "%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n",
>   		 fb_info->fix.id, fb_info->var.xres, fb_info->var.yres,
> @@ -804,6 +814,12 @@ int fbtft_register_framebuffer(struct fb_info *fb_info)
>   		fb_info->bl_dev->props.power = BACKLIGHT_POWER_ON;
>   		fb_info->bl_dev->ops->update_status(fb_info->bl_dev);
>   	}
> +#else
> +	pr_info("%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n",
> +		fb_info->fix.id, fb_info->var.xres, fb_info->var.yres,
> +		fb_info->fix.smem_len >> 10, text1,
> +		HZ / fb_info->fbdefio->delay, text2);
> +#endif
>   
>   	return 0;
>   
> diff --git a/drivers/staging/fbtft/fbtft-sysfs.c b/drivers/staging/fbtft/fbtft-sysfs.c
> index e45c90a03a90..944f74f592d0 100644
> --- a/drivers/staging/fbtft/fbtft-sysfs.c
> +++ b/drivers/staging/fbtft/fbtft-sysfs.c
> @@ -89,6 +89,7 @@ int fbtft_gamma_parse_str(struct fbtft_par *par, u32 *curves,
>   	return ret;
>   }
>   
> +#ifdef CONFIG_FB_DEVICE
>   static ssize_t
>   sprintf_gamma(struct fbtft_par *par, u32 *curves, char *buf)
>   {
> @@ -145,6 +146,7 @@ static ssize_t show_gamma_curve(struct device *device,
>   static struct device_attribute gamma_device_attrs[] = {
>   	__ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve),
>   };
> +#endif
>   
>   void fbtft_expand_debug_value(unsigned long *debug)
>   {
> @@ -173,6 +175,7 @@ void fbtft_expand_debug_value(unsigned long *debug)
>   	}
>   }
>   
> +#ifdef CONFIG_FB_DEVICE
>   static ssize_t store_debug(struct device *device,
>   			   struct device_attribute *attr,
>   			   const char *buf, size_t count)
> @@ -200,17 +203,22 @@ static ssize_t show_debug(struct device *device,
>   
>   static struct device_attribute debug_device_attr =
>   	__ATTR(debug, 0660, show_debug, store_debug);
> +#endif
>   
>   void fbtft_sysfs_init(struct fbtft_par *par)
>   {
> +#ifdef CONFIG_FB_DEVICE
>   	device_create_file(par->info->dev, &debug_device_attr);
>   	if (par->gamma.curves && par->fbtftops.set_gamma)
>   		device_create_file(par->info->dev, &gamma_device_attrs[0]);
> +#endif
>   }
>   
>   void fbtft_sysfs_exit(struct fbtft_par *par)
>   {
> +#ifdef CONFIG_FB_DEVICE
>   	device_remove_file(par->info->dev, &debug_device_attr);
>   	if (par->gamma.curves && par->fbtftops.set_gamma)
>   		device_remove_file(par->info->dev, &gamma_device_attrs[0]);
> +#endif
>   }

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)



^ permalink raw reply

* [PATCH 3/3] sh_mobile_lcdc: Guard overlay sysfs interfaces under CONFIG_FB_DEVICE
From: Chintan Patel @ 2025-12-09  4:27 UTC (permalink / raw)
  To: linux-fbdev, linux-staging, linux-omap
  Cc: linux-kernel, dri-devel, tzimmermann, andy, deller, gregkh,
	Chintan Patel
In-Reply-To: <20251209042744.7875-1-chintanlike@gmail.com>

The SH Mobile LCDC driver exposes overlay configuration via sysfs.
These attributes depend on FB_DEVICE and cause build failures when
FB_DEVICE=n.

Wrap all overlay sysfs attribute definitions and group registrations
within CONFIG_FB_DEVICE. When FB_DEVICE is disabled, the driver still
loads but without sysfs entries.

Signed-off-by: Chintan Patel <chintanlike@gmail.com>
---
 drivers/video/fbdev/sh_mobile_lcdcfb.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index dd950e4ab5ce..a46da10789c3 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -1182,6 +1182,7 @@ static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
  * Frame buffer operations - Overlays
  */
 
+#ifdef CONFIG_FB_DEVICE
 static ssize_t
 overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -1351,6 +1352,7 @@ static struct attribute *overlay_sysfs_attrs[] = {
 	NULL,
 };
 ATTRIBUTE_GROUPS(overlay_sysfs);
+#endif
 
 static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix  = {
 	.id =		"SH Mobile LCDC",
@@ -2637,7 +2639,9 @@ static int sh_mobile_lcdc_probe(struct platform_device *pdev)
 static struct platform_driver sh_mobile_lcdc_driver = {
 	.driver		= {
 		.name		= "sh_mobile_lcdc_fb",
+#ifdef CONFIG_FB_DEVICE
 		.dev_groups	= overlay_sysfs_groups,
+#endif
 		.pm		= &sh_mobile_lcdc_dev_pm_ops,
 	},
 	.probe		= sh_mobile_lcdc_probe,
-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/3] omapfb: Guard sysfs code under CONFIG_FB_DEVICE
From: Chintan Patel @ 2025-12-09  4:27 UTC (permalink / raw)
  To: linux-fbdev, linux-staging, linux-omap
  Cc: linux-kernel, dri-devel, tzimmermann, andy, deller, gregkh,
	Chintan Patel
In-Reply-To: <20251209042744.7875-1-chintanlike@gmail.com>

omapfb implements multiple sysfs attributes for framebuffer rotation,
overlays, and debug information. These interfaces depend on FB_DEVICE
being enabled.

This patch wraps all sysfs attribute definitions, registration, and
removal in #ifdef CONFIG_FB_DEVICE. For FB_DEVICE=n, lightweight stub
functions are provided so that the driver builds and runs without
exposing sysfs interfaces.

Signed-off-by: Chintan Patel <chintanlike@gmail.com>
---
 drivers/video/fbdev/omap2/omapfb/Kconfig        |  2 +-
 drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c | 11 +++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/omap2/omapfb/Kconfig b/drivers/video/fbdev/omap2/omapfb/Kconfig
index f4cdf999a080..ee664decbb64 100644
--- a/drivers/video/fbdev/omap2/omapfb/Kconfig
+++ b/drivers/video/fbdev/omap2/omapfb/Kconfig
@@ -5,7 +5,6 @@ config OMAP2_VRFB
 menuconfig FB_OMAP2
 	tristate "OMAP2+ frame buffer support"
 	depends on FB
-	depends on FB_DEVICE
 	depends on DRM_OMAP = n
 	depends on GPIOLIB
 	select FB_OMAP2_DSS
@@ -13,6 +12,7 @@ menuconfig FB_OMAP2
 	select FB_IOMEM_HELPERS
 	help
 	  Frame buffer driver for OMAP2+ based boards.
+	  Selecting FB_DEVICE enables additional sysfs interfaces.
 
 if FB_OMAP2
 
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c b/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
index 831b2c2fbdf9..0a340f69484f 100644
--- a/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
@@ -24,6 +24,7 @@
 
 #include "omapfb.h"
 
+#ifdef CONFIG_FB_DEVICE
 static ssize_t show_rotate_type(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -585,4 +586,14 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
 					&omapfb_attrs[t]);
 	}
 }
+#else
+int omapfb_create_sysfs(struct omapfb2_device *fbdev)
+{
+	return 0;
+}
+
+void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
+{
+}
+#endif
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/3] fbtft: Make sysfs and dev_*() logging conditional on FB_DEVICE
From: Chintan Patel @ 2025-12-09  4:27 UTC (permalink / raw)
  To: linux-fbdev, linux-staging, linux-omap
  Cc: linux-kernel, dri-devel, tzimmermann, andy, deller, gregkh,
	Chintan Patel
In-Reply-To: <20251209042744.7875-1-chintanlike@gmail.com>

The fbtft core and sysfs implementation unconditionally dereference
fb_info->dev and register sysfs attributes. When FB_DEVICE=n, these
fields are unavailable, leading to build failures.

This patch wraps all sysfs attribute creation/removal and dev_dbg/dev_info
logging in #ifdef CONFIG_FB_DEVICE, with pr_*() fallbacks for the
non-FB_DEVICE case. This makes fbtft fully buildable when FB_DEVICE is
disabled.

Signed-off-by: Chintan Patel <chintanlike@gmail.com>
---
 drivers/staging/fbtft/fbtft-core.c  | 20 ++++++++++++++++++--
 drivers/staging/fbtft/fbtft-sysfs.c |  8 ++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 9e7b84071174..dc967bdeabe8 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -365,9 +365,14 @@ static int fbtft_fb_setcolreg(unsigned int regno, unsigned int red,
 	unsigned int val;
 	int ret = 1;
 
+#ifdef CONFIG_FB_DEVICE
 	dev_dbg(info->dev,
 		"%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n",
 		__func__, regno, red, green, blue, transp);
+#else
+	pr_debug("%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n",
+		 __func__, regno, red, green, blue, transp);
+#endif
 
 	switch (info->fix.visual) {
 	case FB_VISUAL_TRUECOLOR:
@@ -391,8 +396,11 @@ static int fbtft_fb_blank(int blank, struct fb_info *info)
 	struct fbtft_par *par = info->par;
 	int ret = -EINVAL;
 
-	dev_dbg(info->dev, "%s(blank=%d)\n",
-		__func__, blank);
+#ifdef CONFIG_FB_DEVICE
+	dev_dbg(info->dev, "%s(blank=%d)\n", __func__, blank);
+#else
+	pr_debug("%s(blank=%d)\n", __func__, blank);
+#endif
 
 	if (!par->fbtftops.blank)
 		return ret;
@@ -793,6 +801,8 @@ int fbtft_register_framebuffer(struct fb_info *fb_info)
 	if (spi)
 		sprintf(text2, ", spi%d.%d at %d MHz", spi->controller->bus_num,
 			spi_get_chipselect(spi, 0), spi->max_speed_hz / 1000000);
+
+#ifdef CONFIG_FB_DEVICE
 	dev_info(fb_info->dev,
 		 "%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n",
 		 fb_info->fix.id, fb_info->var.xres, fb_info->var.yres,
@@ -804,6 +814,12 @@ int fbtft_register_framebuffer(struct fb_info *fb_info)
 		fb_info->bl_dev->props.power = BACKLIGHT_POWER_ON;
 		fb_info->bl_dev->ops->update_status(fb_info->bl_dev);
 	}
+#else
+	pr_info("%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n",
+		fb_info->fix.id, fb_info->var.xres, fb_info->var.yres,
+		fb_info->fix.smem_len >> 10, text1,
+		HZ / fb_info->fbdefio->delay, text2);
+#endif
 
 	return 0;
 
diff --git a/drivers/staging/fbtft/fbtft-sysfs.c b/drivers/staging/fbtft/fbtft-sysfs.c
index e45c90a03a90..944f74f592d0 100644
--- a/drivers/staging/fbtft/fbtft-sysfs.c
+++ b/drivers/staging/fbtft/fbtft-sysfs.c
@@ -89,6 +89,7 @@ int fbtft_gamma_parse_str(struct fbtft_par *par, u32 *curves,
 	return ret;
 }
 
+#ifdef CONFIG_FB_DEVICE
 static ssize_t
 sprintf_gamma(struct fbtft_par *par, u32 *curves, char *buf)
 {
@@ -145,6 +146,7 @@ static ssize_t show_gamma_curve(struct device *device,
 static struct device_attribute gamma_device_attrs[] = {
 	__ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve),
 };
+#endif
 
 void fbtft_expand_debug_value(unsigned long *debug)
 {
@@ -173,6 +175,7 @@ void fbtft_expand_debug_value(unsigned long *debug)
 	}
 }
 
+#ifdef CONFIG_FB_DEVICE
 static ssize_t store_debug(struct device *device,
 			   struct device_attribute *attr,
 			   const char *buf, size_t count)
@@ -200,17 +203,22 @@ static ssize_t show_debug(struct device *device,
 
 static struct device_attribute debug_device_attr =
 	__ATTR(debug, 0660, show_debug, store_debug);
+#endif
 
 void fbtft_sysfs_init(struct fbtft_par *par)
 {
+#ifdef CONFIG_FB_DEVICE
 	device_create_file(par->info->dev, &debug_device_attr);
 	if (par->gamma.curves && par->fbtftops.set_gamma)
 		device_create_file(par->info->dev, &gamma_device_attrs[0]);
+#endif
 }
 
 void fbtft_sysfs_exit(struct fbtft_par *par)
 {
+#ifdef CONFIG_FB_DEVICE
 	device_remove_file(par->info->dev, &debug_device_attr);
 	if (par->gamma.curves && par->fbtftops.set_gamma)
 		device_remove_file(par->info->dev, &gamma_device_attrs[0]);
+#endif
 }
-- 
2.43.0


^ permalink raw reply related

* [PATCH 0/3] fbdev: Guard sysfs interfaces under CONFIG_FB_DEVICE
From: Chintan Patel @ 2025-12-09  4:27 UTC (permalink / raw)
  To: linux-fbdev, linux-staging, linux-omap
  Cc: linux-kernel, dri-devel, tzimmermann, andy, deller, gregkh,
	Chintan Patel

Hi all,

This small series makes several legacy fbdev drivers buildable with
CONFIG_FB_DEVICE=n. Currently, multiple fbdev drivers rely on fb_info->dev
and sysfs attribute registration unconditionally, which leads to build
failures whenever FB_DEVICE is disabled.

Thomas previously noted that FB_DEVICE should eventually become optional
and that drivers should not depend on sysfs or fb_info->dev being present
unless the Kconfig explicitly selects it. This series pushes in that
direction by tightening the FB_DEVICE dependency boundary without changing
any runtime behaviour when FB_DEVICE=y.

What this series does *not* change

- No functional behaviour changes when FB_DEVICE=y.
- No removal of sysfs interfaces.
- No changes to fbops, memory allocation, or display update paths.

Build & test coverage

Tested with the following combinations:

1. **FB=y, FB_DEVICE=y**  
   - Baseline configuration; no regressions expected.

2. **FB=y, FB_DEVICE=n**  
   - Drivers build successfully.
   - No sysfs attributes are created.
   - fbdev devices operate normally (where applicable).

3. **FB=n**  
   - Drivers depend on FB, so they properly do not build, unchanged.

Motivation

This moves fbdev closer to supporting FB_DEVICE as truly optional, helps
reduce Kconfig entanglement, and clears several long-standing TODO items
as suggested by Thomas Zimmermann around legacy sysfs usage inside fbdev 
drivers.

Feedback is welcome, especially on whether the guard boundaries around
sysfs are placed correctly or whether more logic should be pulled under
CONFIG_FB_DEVICE.

Thanks,
Chintan

Chintan Patel (3):
  fbtft: Make sysfs and dev_*() logging conditional on FB_DEVICE
  omapfb: Guard sysfs code under CONFIG_FB_DEVICE
  sh_mobile_lcdc: Guard overlay sysfs interfaces under CONFIG_FB_DEVICE

 drivers/staging/fbtft/fbtft-core.c            | 20 +++++++++++++++++--
 drivers/staging/fbtft/fbtft-sysfs.c           |  8 ++++++++
 drivers/video/fbdev/omap2/omapfb/Kconfig      |  2 +-
 .../video/fbdev/omap2/omapfb/omapfb-sysfs.c   | 11 ++++++++++
 drivers/video/fbdev/sh_mobile_lcdcfb.c        |  4 ++++
 5 files changed, 42 insertions(+), 3 deletions(-)

-- 
2.43.0


^ permalink raw reply

* Re: [PATCH 14/19] video/vga: Add VGA_IS0_R
From: kernel test robot @ 2025-12-08 22:22 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx
  Cc: oe-kbuild-all, intel-xe, Helge Deller, linux-fbdev, dri-devel
In-Reply-To: <20251208182637.334-15-ville.syrjala@linux.intel.com>

Hi Ville,

kernel test robot noticed the following build warnings:

[auto build test WARNING on drm-tip/drm-tip]
[cannot apply to drm-i915/for-linux-next drm-i915/for-linux-next-fixes linus/master v6.18 next-20251208]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ville-Syrjala/drm-i915-vga-Register-vgaarb-client-later/20251209-030730
base:   https://gitlab.freedesktop.org/drm/tip.git drm-tip
patch link:    https://lore.kernel.org/r/20251208182637.334-15-ville.syrjala%40linux.intel.com
patch subject: [PATCH 14/19] video/vga: Add VGA_IS0_R
config: i386-randconfig-141-20251209 (https://download.01.org/0day-ci/archive/20251209/202512090603.ycfxEuHJ-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251209/202512090603.ycfxEuHJ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512090603.ycfxEuHJ-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/gpu/drm/tiny/bochs.c:29:
   include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
     489 | ?
         | ^
   In file included from include/linux/module.h:23,
                    from drivers/gpu/drm/tiny/bochs.c:5:
   drivers/gpu/drm/tiny/bochs.c: In function '__check_modeset':
   drivers/gpu/drm/tiny/bochs.c:66:29: error: 'bochs_modeset' undeclared (first use in this function)
      66 | module_param_named(modeset, bochs_modeset, int, 0444);
         |                             ^~~~~~~~~~~~~
   include/linux/moduleparam.h:430:75: note: in definition of macro '__param_check'
     430 |         static inline type __always_unused *__check_##name(void) { return(p); }
         |                                                                           ^
   include/linux/moduleparam.h:155:9: note: in expansion of macro 'param_check_int'
     155 |         param_check_##type(name, &(value));                                \
         |         ^~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:66:1: note: in expansion of macro 'module_param_named'
      66 | module_param_named(modeset, bochs_modeset, int, 0444);
         | ^~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:66:29: note: each undeclared identifier is reported only once for each function it appears in
      66 | module_param_named(modeset, bochs_modeset, int, 0444);
         |                             ^~~~~~~~~~~~~
   include/linux/moduleparam.h:430:75: note: in definition of macro '__param_check'
     430 |         static inline type __always_unused *__check_##name(void) { return(p); }
         |                                                                           ^
   include/linux/moduleparam.h:155:9: note: in expansion of macro 'param_check_int'
     155 |         param_check_##type(name, &(value));                                \
         |         ^~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:66:1: note: in expansion of macro 'module_param_named'
      66 | module_param_named(modeset, bochs_modeset, int, 0444);
         | ^~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c: At top level:
   drivers/gpu/drm/tiny/bochs.c:66:29: error: 'bochs_modeset' undeclared here (not in a function)
      66 | module_param_named(modeset, bochs_modeset, int, 0444);
         |                             ^~~~~~~~~~~~~
   include/linux/moduleparam.h:298:61: note: in definition of macro '__module_param_call'
     298 |             VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } }
         |                                                             ^~~
   include/linux/moduleparam.h:156:9: note: in expansion of macro 'module_param_cb'
     156 |         module_param_cb(name, &param_ops_##type, &value, perm);            \
         |         ^~~~~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:66:1: note: in expansion of macro 'module_param_named'
      66 | module_param_named(modeset, bochs_modeset, int, 0444);
         | ^~~~~~~~~~~~~~~~~~
   In file included from include/linux/device.h:32,
                    from include/linux/pci.h:37,
                    from drivers/gpu/drm/tiny/bochs.c:6:
   drivers/gpu/drm/tiny/bochs.c: In function 'bochs_pci_driver_init':
>> include/linux/device/driver.h:261:1: warning: control reaches end of non-void function [-Wreturn-type]
     261 | } \
         | ^
   include/drm/drm_module.h:93:9: note: in expansion of macro 'module_driver'
      93 |         module_driver(__pci_drv, drm_pci_register_driver_if_modeset, \
         |         ^~~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:835:1: note: in expansion of macro 'drm_module_pci_driver_if_modeset'
     835 | drm_module_pci_driver_if_modeset(bochs_pci_driver, bochs_modeset);
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +261 include/linux/device/driver.h

4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  242  
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  243  /**
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  244   * module_driver() - Helper macro for drivers that don't do anything
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  245   * special in module init/exit. This eliminates a lot of boilerplate.
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  246   * Each module may only use this macro once, and calling it replaces
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  247   * module_init() and module_exit().
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  248   *
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  249   * @__driver: driver name
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  250   * @__register: register function for this driver type
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  251   * @__unregister: unregister function for this driver type
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  252   * @...: Additional arguments to be passed to __register and __unregister.
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  253   *
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  254   * Use this macro to construct bus specific macros for registering
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  255   * drivers, and do not use it on its own.
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  256   */
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  257  #define module_driver(__driver, __register, __unregister, ...) \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  258  static int __init __driver##_init(void) \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  259  { \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  260  	return __register(&(__driver) , ##__VA_ARGS__); \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09 @261  } \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  262  module_init(__driver##_init); \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  263  static void __exit __driver##_exit(void) \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  264  { \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  265  	__unregister(&(__driver) , ##__VA_ARGS__); \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  266  } \
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  267  module_exit(__driver##_exit);
4c002c978b7f2f Greg Kroah-Hartman 2019-12-09  268  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH] riva/fbdev: fix divide error in nv3_arb()
From: Helge Deller @ 2025-12-08 22:02 UTC (permalink / raw)
  To: Guangshuo Li, Antonino Daplas, linux-fbdev, dri-devel,
	linux-kernel; +Cc: stable
In-Reply-To: <20251207072532.518547-1-lgs201920130244@gmail.com>

On 12/7/25 08:25, Guangshuo Li wrote:
> A userspace program can trigger the RIVA NV3 arbitration code by
> calling the FBIOPUT_VSCREENINFO ioctl on /dev/fb*. When doing so,
> the driver recomputes FIFO arbitration parameters in nv3_arb(), using
> state->mclk_khz (derived from the PRAMDAC MCLK PLL) as a divisor
> without validating it first.
> 
> In a normal setup, state->mclk_khz is provided by the real hardware
> and is non-zero. However, an attacker can construct a malicious or
> misconfigured device (e.g. a crafted/emulated PCI device) that exposes
> a bogus PLL configuration, causing state->mclk_khz to become zero.
> Once nv3_get_param() calls nv3_arb(), the division by state->mclk_khz in
> the gns calculation causes a divide error and crashes the kernel.
> 
> Fix this by checking whether state->mclk_khz is zero and bailing out before doing the division.
> 
> The following log reveals it:
> 
> rivafb: setting virtual Y resolution to 2184
> divide error: 0000 [#1] PREEMPT SMP KASAN PTI
> CPU: 0 PID: 2187 Comm: syz-executor.0 Not tainted 5.18.0-rc1+ #1
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014
> RIP: 0010:nv3_arb drivers/video/fbdev/riva/riva_hw.c:439 [inline]
> RIP: 0010:nv3_get_param+0x3ab/0x13b0 drivers/video/fbdev/riva/riva_hw.c:546
> Code: c1 e8 03 42 0f b6 14 38 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 b7 0e 00 00 41 8b 46 18 01 d8 69 c0 40 42 0f 00 99 <41> f7 fc 48 63 c8 4c 89 e8 48 c1 e8 03 42 0f b6 14 38 4c 89 e8 83
> RSP: 0018:ffff888013b2f318 EFLAGS: 00010206
> RAX: 0000000001d905c0 RBX: 0000000000000016 RCX: 0000000000040000
> RDX: 0000000000000000 RSI: 0000000000000080 RDI: ffff888013b2f6f0
> RBP: 0000000000000002 R08: ffffffff82226288 R09: 0000000000000001
> R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
> R13: ffff888013b2f4d8 R14: ffff888013b2f6d8 R15: dffffc0000000000
> Call Trace:
>    nv3CalcArbitration.constprop.0+0x255/0x460 drivers/video/fbdev/riva/riva_hw.c:603
>    nv3UpdateArbitrationSettings drivers/video/fbdev/riva/riva_hw.c:637 [inline]
>    CalcStateExt+0x447/0x1b90 drivers/video/fbdev/riva/riva_hw.c:1246
>    riva_load_video_mode+0x8a9/0xea0 drivers/video/fbdev/riva/fbdev.c:779
>    rivafb_set_par+0xc0/0x5f0 drivers/video/fbdev/riva/fbdev.c:1196

Doesn't it make sense to check mclk_khz (or the various variables which
lead to mclk_khz) in rivafb_set_par() or any of the other functions mentioned
in this trace?
If in doubt, mclk_khz could be initialized to a sane value?

Helge


>    fb_set_var+0x604/0xeb0 drivers/video/fbdev/core/fbmem.c:1033
>    do_fb_ioctl+0x234/0x670 drivers/video/fbdev/core/fbmem.c:1109
>    fb_ioctl+0xdd/0x130 drivers/video/fbdev/core/fbmem.c:1188
>    __x64_sys_ioctl+0x122/0x190 fs/ioctl.c:856
> 
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@vger.kernel.org
> Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
> ---
>   drivers/video/fbdev/riva/riva_hw.c | 3 +++
>   1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/video/fbdev/riva/riva_hw.c b/drivers/video/fbdev/riva/riva_hw.c
> index 8b829b720064..d70c6c4d28e8 100644
> --- a/drivers/video/fbdev/riva/riva_hw.c
> +++ b/drivers/video/fbdev/riva/riva_hw.c
> @@ -436,6 +436,9 @@ static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state,  nv3_arb_in
>       vmisses = 2;
>       eburst_size = state->memory_width * 1;
>       mburst_size = 32;
> +	if (!state->mclk_khz)
> +		return (0);
> +
>       gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
>       ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000;
>       ainfo->wcmocc = 0;


^ permalink raw reply

* Re: [PATCH 14/19] video/vga: Add VGA_IS0_R
From: kernel test robot @ 2025-12-08 21:18 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx
  Cc: llvm, oe-kbuild-all, intel-xe, Helge Deller, linux-fbdev,
	dri-devel
In-Reply-To: <20251208182637.334-15-ville.syrjala@linux.intel.com>

Hi Ville,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-tip/drm-tip]
[cannot apply to drm-i915/for-linux-next drm-i915/for-linux-next-fixes linus/master v6.18 next-20251208]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ville-Syrjala/drm-i915-vga-Register-vgaarb-client-later/20251209-030730
base:   https://gitlab.freedesktop.org/drm/tip.git drm-tip
patch link:    https://lore.kernel.org/r/20251208182637.334-15-ville.syrjala%40linux.intel.com
patch subject: [PATCH 14/19] video/vga: Add VGA_IS0_R
config: x86_64-allnoconfig (https://download.01.org/0day-ci/archive/20251209/202512090554.7pZ9xOQ5-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251209/202512090554.7pZ9xOQ5-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512090554.7pZ9xOQ5-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from drivers/video/console/vgacon.c:51:
>> include/video/vga.h:489:1: error: expected identifier or '('
     489 | ?
         | ^
>> drivers/video/console/vgacon.c:126:25: error: use of undeclared identifier 'vga_lock'; did you mean 'pgd_lock'?
     126 |         raw_spin_lock_irqsave(&vga_lock, flags);
         |                                ^~~~~~~~
         |                                pgd_lock
   include/linux/spinlock.h:266:26: note: expanded from macro 'raw_spin_lock_irqsave'
     266 |                 _raw_spin_lock_irqsave(lock, flags);    \
         |                                        ^
   include/linux/spinlock_api_up.h:69:60: note: expanded from macro '_raw_spin_lock_irqsave'
      69 | #define _raw_spin_lock_irqsave(lock, flags)     __LOCK_IRQSAVE(lock, flags)
         |                                                                ^
   include/linux/spinlock_api_up.h:40:38: note: expanded from macro '__LOCK_IRQSAVE'
      40 |   do { local_irq_save(flags); __LOCK(lock); } while (0)
         |                                      ^
   include/linux/spinlock_api_up.h:31:35: note: expanded from macro '__LOCK'
      31 |   do { preempt_disable(); ___LOCK(lock); } while (0)
         |                                   ^
   include/linux/spinlock_api_up.h:28:32: note: expanded from macro '___LOCK'
      28 |   do { __acquire(lock); (void)(lock); } while (0)
         |                                ^
   arch/x86/include/asm/pgtable.h:58:19: note: 'pgd_lock' declared here
      58 | extern spinlock_t pgd_lock;
         |                   ^
   drivers/video/console/vgacon.c:131:30: error: use of undeclared identifier 'vga_lock'; did you mean 'pgd_lock'?
     131 |         raw_spin_unlock_irqrestore(&vga_lock, flags);
         |                                     ^~~~~~~~
         |                                     pgd_lock
   include/linux/spinlock.h:282:31: note: expanded from macro 'raw_spin_unlock_irqrestore'
     282 |                 _raw_spin_unlock_irqrestore(lock, flags);       \
         |                                             ^
   include/linux/spinlock_api_up.h:86:26: note: expanded from macro '_raw_spin_unlock_irqrestore'
      86 |                                         __UNLOCK_IRQRESTORE(lock, flags)
         |                                                             ^
   include/linux/spinlock_api_up.h:56:43: note: expanded from macro '__UNLOCK_IRQRESTORE'
      56 |   do { local_irq_restore(flags); __UNLOCK(lock); } while (0)
         |                                           ^
   include/linux/spinlock_api_up.h:46:36: note: expanded from macro '__UNLOCK'
      46 |   do { preempt_enable(); ___UNLOCK(lock); } while (0)
         |                                    ^
   include/linux/spinlock_api_up.h:43:32: note: expanded from macro '___UNLOCK'
      43 |   do { __release(lock); (void)(lock); } while (0)
         |                                ^
   arch/x86/include/asm/pgtable.h:58:19: note: 'pgd_lock' declared here
      58 | extern spinlock_t pgd_lock;
         |                   ^
   drivers/video/console/vgacon.c:485:25: error: use of undeclared identifier 'vga_lock'; did you mean 'pgd_lock'?
     485 |         raw_spin_lock_irqsave(&vga_lock, flags);
         |                                ^~~~~~~~
         |                                pgd_lock
   include/linux/spinlock.h:266:26: note: expanded from macro 'raw_spin_lock_irqsave'
     266 |                 _raw_spin_lock_irqsave(lock, flags);    \
         |                                        ^
   include/linux/spinlock_api_up.h:69:60: note: expanded from macro '_raw_spin_lock_irqsave'
      69 | #define _raw_spin_lock_irqsave(lock, flags)     __LOCK_IRQSAVE(lock, flags)
         |                                                                ^
   include/linux/spinlock_api_up.h:40:38: note: expanded from macro '__LOCK_IRQSAVE'
      40 |   do { local_irq_save(flags); __LOCK(lock); } while (0)
         |                                      ^
   include/linux/spinlock_api_up.h:31:35: note: expanded from macro '__LOCK'
      31 |   do { preempt_disable(); ___LOCK(lock); } while (0)
         |                                   ^
   include/linux/spinlock_api_up.h:28:32: note: expanded from macro '___LOCK'
      28 |   do { __acquire(lock); (void)(lock); } while (0)
         |                                ^
   arch/x86/include/asm/pgtable.h:58:19: note: 'pgd_lock' declared here
      58 | extern spinlock_t pgd_lock;
         |                   ^
   drivers/video/console/vgacon.c:503:30: error: use of undeclared identifier 'vga_lock'; did you mean 'pgd_lock'?
     503 |         raw_spin_unlock_irqrestore(&vga_lock, flags);
         |                                     ^~~~~~~~
         |                                     pgd_lock
   include/linux/spinlock.h:282:31: note: expanded from macro 'raw_spin_unlock_irqrestore'
     282 |                 _raw_spin_unlock_irqrestore(lock, flags);       \
         |                                             ^
   include/linux/spinlock_api_up.h:86:26: note: expanded from macro '_raw_spin_unlock_irqrestore'
      86 |                                         __UNLOCK_IRQRESTORE(lock, flags)
         |                                                             ^
   include/linux/spinlock_api_up.h:56:43: note: expanded from macro '__UNLOCK_IRQRESTORE'
      56 |   do { local_irq_restore(flags); __UNLOCK(lock); } while (0)
         |                                           ^
   include/linux/spinlock_api_up.h:46:36: note: expanded from macro '__UNLOCK'
      46 |   do { preempt_enable(); ___UNLOCK(lock); } while (0)
         |                                    ^
   include/linux/spinlock_api_up.h:43:32: note: expanded from macro '___UNLOCK'
      43 |   do { __release(lock); (void)(lock); } while (0)
         |                                ^
   arch/x86/include/asm/pgtable.h:58:19: note: 'pgd_lock' declared here
      58 | extern spinlock_t pgd_lock;
         |                   ^
   drivers/video/console/vgacon.c:563:25: error: use of undeclared identifier 'vga_lock'; did you mean 'pgd_lock'?
     563 |         raw_spin_lock_irqsave(&vga_lock, flags);
         |                                ^~~~~~~~
         |                                pgd_lock
   include/linux/spinlock.h:266:26: note: expanded from macro 'raw_spin_lock_irqsave'
     266 |                 _raw_spin_lock_irqsave(lock, flags);    \
         |                                        ^
   include/linux/spinlock_api_up.h:69:60: note: expanded from macro '_raw_spin_lock_irqsave'
      69 | #define _raw_spin_lock_irqsave(lock, flags)     __LOCK_IRQSAVE(lock, flags)
         |                                                                ^
   include/linux/spinlock_api_up.h:40:38: note: expanded from macro '__LOCK_IRQSAVE'
      40 |   do { local_irq_save(flags); __LOCK(lock); } while (0)
         |                                      ^


vim +489 include/video/vga.h

   487	
   488	#endif /* __linux_video_vga_h__ */
 > 489	?

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH 14/19] video/vga: Add VGA_IS0_R
From: kernel test robot @ 2025-12-08 21:07 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx
  Cc: oe-kbuild-all, intel-xe, Helge Deller, linux-fbdev, dri-devel
In-Reply-To: <20251208182637.334-15-ville.syrjala@linux.intel.com>

Hi Ville,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-tip/drm-tip]
[cannot apply to drm-i915/for-linux-next drm-i915/for-linux-next-fixes linus/master v6.18 next-20251208]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ville-Syrjala/drm-i915-vga-Register-vgaarb-client-later/20251209-030730
base:   https://gitlab.freedesktop.org/drm/tip.git drm-tip
patch link:    https://lore.kernel.org/r/20251208182637.334-15-ville.syrjala%40linux.intel.com
patch subject: [PATCH 14/19] video/vga: Add VGA_IS0_R
config: microblaze-randconfig-r072-20251209 (https://download.01.org/0day-ci/archive/20251209/202512090434.DRy1Kvan-lkp@intel.com/config)
compiler: microblaze-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251209/202512090434.DRy1Kvan-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512090434.DRy1Kvan-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/vgaarb.h:15,
                    from drivers/video/aperture.c:12:
>> include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   In file included from drivers/video/aperture.c:14:
>> include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   drivers/video/aperture.c: In function 'devm_aperture_acquire_release':
>> drivers/video/aperture.c:153:21: error: dereferencing pointer to incomplete type 'struct aperture_range'
     bool detached = !ap->dev;
                        ^~
   In file included from include/linux/bits.h:30,
                    from include/linux/ratelimit_types.h:5,
                    from include/linux/ratelimit.h:5,
                    from include/linux/dev_printk.h:16,
                    from include/linux/device.h:15,
                    from drivers/video/aperture.c:4:
   drivers/video/aperture.c: In function 'devm_aperture_acquire':
>> include/linux/container_of.h:21:47: error: dereferencing pointer to incomplete type 'struct aperture_range'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
                                                  ^~
   include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
    #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
                                                           ^~~~
   include/linux/container_of.h:21:2: note: in expansion of macro 'static_assert'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
     ^~~~~~~~~~~~~
   include/linux/container_of.h:21:16: note: in expansion of macro '__same_type'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
                   ^~~~~~~~~~~
   drivers/video/aperture.c:174:8: note: in expansion of macro 'container_of'
      ap = container_of(pos, struct aperture_range, lh);
           ^~~~~~~~~~~~
   include/linux/compiler_types.h:537:27: error: expression in static assertion is not an integer
    #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
    #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
                                                           ^~~~
   include/linux/container_of.h:21:2: note: in expansion of macro 'static_assert'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
     ^~~~~~~~~~~~~
   include/linux/container_of.h:21:16: note: in expansion of macro '__same_type'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
                   ^~~~~~~~~~~
   drivers/video/aperture.c:174:8: note: in expansion of macro 'container_of'
      ap = container_of(pos, struct aperture_range, lh);
           ^~~~~~~~~~~~
   In file included from include/uapi/linux/posix_types.h:5,
                    from include/uapi/linux/types.h:14,
                    from include/linux/types.h:6,
                    from include/linux/aperture.h:6,
                    from drivers/video/aperture.c:3:
>> include/linux/stddef.h:16:32: error: invalid use of undefined type 'struct aperture_range'
    #define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
                                   ^~~~~~~~~~~~~~~~~~
   include/linux/container_of.h:24:21: note: in expansion of macro 'offsetof'
     ((type *)(__mptr - offsetof(type, member))); })
                        ^~~~~~~~
   drivers/video/aperture.c:174:8: note: in expansion of macro 'container_of'
      ap = container_of(pos, struct aperture_range, lh);
           ^~~~~~~~~~~~
   In file included from include/linux/bits.h:30,
                    from include/linux/ratelimit_types.h:5,
                    from include/linux/ratelimit.h:5,
                    from include/linux/dev_printk.h:16,
                    from include/linux/device.h:15,
                    from drivers/video/aperture.c:4:
   drivers/video/aperture.c: In function 'aperture_detach_devices':
>> include/linux/container_of.h:21:47: error: dereferencing pointer to incomplete type 'struct aperture_range'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
                                                  ^~
   include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
    #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
                                                           ^~~~
   include/linux/container_of.h:21:2: note: in expansion of macro 'static_assert'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
     ^~~~~~~~~~~~~
   include/linux/container_of.h:21:16: note: in expansion of macro '__same_type'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
                   ^~~~~~~~~~~
   drivers/video/aperture.c:255:31: note: in expansion of macro 'container_of'
      struct aperture_range *ap = container_of(pos, struct aperture_range, lh);
                                  ^~~~~~~~~~~~
   include/linux/compiler_types.h:537:27: error: expression in static assertion is not an integer
    #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
    #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
                                                           ^~~~
   include/linux/container_of.h:21:2: note: in expansion of macro 'static_assert'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
     ^~~~~~~~~~~~~
   include/linux/container_of.h:21:16: note: in expansion of macro '__same_type'
     static_assert(__same_type(*(ptr), ((type *)0)->member) || \
                   ^~~~~~~~~~~
   drivers/video/aperture.c:255:31: note: in expansion of macro 'container_of'
      struct aperture_range *ap = container_of(pos, struct aperture_range, lh);
                                  ^~~~~~~~~~~~
   In file included from include/uapi/linux/posix_types.h:5,
                    from include/uapi/linux/types.h:14,
                    from include/linux/types.h:6,
                    from include/linux/aperture.h:6,
                    from drivers/video/aperture.c:3:
>> include/linux/stddef.h:16:32: error: invalid use of undefined type 'struct aperture_range'
    #define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
                                   ^~~~~~~~~~~~~~~~~~
   include/linux/container_of.h:24:21: note: in expansion of macro 'offsetof'
     ((type *)(__mptr - offsetof(type, member))); })
                        ^~~~~~~~
   drivers/video/aperture.c:255:31: note: in expansion of macro 'container_of'
      struct aperture_range *ap = container_of(pos, struct aperture_range, lh);
                                  ^~~~~~~~~~~~
--
   In file included from drivers/gpu/drm/mgag200/mgag200_drv.h:13,
                    from drivers/gpu/drm/mgag200/mgag200_bmc.c:10:
>> include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   In file included from include/linux/dma-buf.h:16,
                    from include/drm/drm_gem.h:38,
                    from drivers/gpu/drm/mgag200/mgag200_drv.h:18,
                    from drivers/gpu/drm/mgag200/mgag200_bmc.c:10:
>> include/linux/iosys-map.h:183:47: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline void iosys_map_set_vaddr(struct iosys_map *map, void *vaddr)
                                                  ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_set_vaddr':
>> include/linux/iosys-map.h:185:5: error: dereferencing pointer to incomplete type 'struct iosys_map'
     map->vaddr = vaddr;
        ^~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:196:53: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline void iosys_map_set_vaddr_iomem(struct iosys_map *map,
                                                        ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_set_vaddr_iomem':
   include/linux/iosys-map.h:199:5: error: dereferencing pointer to incomplete type 'struct iosys_map'
     map->vaddr_iomem = vaddr_iomem;
        ^~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:214:52: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline bool iosys_map_is_equal(const struct iosys_map *lhs,
                                                       ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_is_equal':
>> include/linux/iosys-map.h:217:9: error: dereferencing pointer to incomplete type 'const struct iosys_map'
     if (lhs->is_iomem != rhs->is_iomem)
            ^~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:235:51: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline bool iosys_map_is_null(const struct iosys_map *map)
                                                      ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_is_null':
   include/linux/iosys-map.h:237:9: error: dereferencing pointer to incomplete type 'const struct iosys_map'
     if (map->is_iomem)
            ^~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:252:50: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline bool iosys_map_is_set(const struct iosys_map *map)
                                                     ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_is_set':
>> include/linux/iosys-map.h:254:28: error: passing argument 1 of 'iosys_map_is_null' from incompatible pointer type [-Werror=incompatible-pointer-types]
     return !iosys_map_is_null(map);
                               ^~~
   include/linux/iosys-map.h:235:62: note: expected 'const struct iosys_map *' but argument is of type 'const struct iosys_map *'
    static inline bool iosys_map_is_null(const struct iosys_map *map)
                                         ~~~~~~~~~~~~~~~~~~~~~~~~^~~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:265:43: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline void iosys_map_clear(struct iosys_map *map)
                                              ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_clear':
   include/linux/iosys-map.h:267:24: error: dereferencing pointer to incomplete type 'struct iosys_map'
     memset(map, 0, sizeof(*map));
                           ^~~~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:281:47: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline void iosys_map_memcpy_to(struct iosys_map *dst, size_t dst_offset,
                                                  ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_memcpy_to':
   include/linux/iosys-map.h:284:9: error: dereferencing pointer to incomplete type 'struct iosys_map'
     if (dst->is_iomem)
            ^~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:301:66: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline void iosys_map_memcpy_from(void *dst, const struct iosys_map *src,
                                                                     ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_memcpy_from':
   include/linux/iosys-map.h:304:9: error: dereferencing pointer to incomplete type 'const struct iosys_map'
     if (src->is_iomem)
            ^~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:318:42: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline void iosys_map_incr(struct iosys_map *map, size_t incr)
                                             ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_incr':
   include/linux/iosys-map.h:320:9: error: dereferencing pointer to incomplete type 'struct iosys_map'
     if (map->is_iomem)
            ^~
   include/linux/iosys-map.h: At top level:
   include/linux/iosys-map.h:336:44: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
    static inline void iosys_map_memset(struct iosys_map *dst, size_t offset,
                                               ^~~~~~~~~
   include/linux/iosys-map.h: In function 'iosys_map_memset':
   include/linux/iosys-map.h:339:9: error: dereferencing pointer to incomplete type 'struct iosys_map'
     if (dst->is_iomem)
            ^~
   In file included from include/drm/drm_gem.h:38,
                    from drivers/gpu/drm/mgag200/mgag200_drv.h:18,
                    from drivers/gpu/drm/mgag200/mgag200_bmc.c:10:
   include/linux/dma-buf.h: At top level:
>> include/linux/dma-buf.h:277:45: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
     int (*vmap)(struct dma_buf *dmabuf, struct iosys_map *map);
                                                ^~~~~~~~~
   include/linux/dma-buf.h:278:48: warning: 'struct iosys_map' declared inside parameter list will not be visible outside of this definition or declaration
     void (*vunmap)(struct dma_buf *dmabuf, struct iosys_map *map);
                                                   ^~~~~~~~~
>> include/linux/dma-buf.h:332:19: error: field 'vmap_ptr' has incomplete type
     struct iosys_map vmap_ptr;
                      ^~~~~~~~
   cc1: some warnings being treated as errors
--
   In file included from drivers/gpu/drm/mgag200/mgag200_drv.h:13,
                    from drivers/gpu/drm/mgag200/mgag200_ddc.c:36:
>> include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
--
   In file included from drivers/gpu/drm/mgag200/mgag200_drv.h:13,
                    from drivers/gpu/drm/mgag200/mgag200_drv.c:25:
>> include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   In file included from include/linux/dma-buf.h:16,
                    from include/drm/drm_gem.h:38,
                    from drivers/gpu/drm/mgag200/mgag200_drv.h:18,
                    from drivers/gpu/drm/mgag200/mgag200_drv.c:25:
   include/linux/iosys-map.h: In function 'iosys_map_set_vaddr':
>> include/linux/iosys-map.h:185:5: error: dereferencing pointer to incomplete type 'struct iosys_map'
     map->vaddr = vaddr;
        ^~
   include/linux/iosys-map.h: In function 'iosys_map_is_equal':
>> include/linux/iosys-map.h:217:9: error: dereferencing pointer to incomplete type 'const struct iosys_map'
     if (lhs->is_iomem != rhs->is_iomem)
            ^~
   In file included from include/drm/drm_gem.h:38,
                    from drivers/gpu/drm/mgag200/mgag200_drv.h:18,
                    from drivers/gpu/drm/mgag200/mgag200_drv.c:25:
   include/linux/dma-buf.h: At top level:
>> include/linux/dma-buf.h:332:19: error: field 'vmap_ptr' has incomplete type
     struct iosys_map vmap_ptr;
                      ^~~~~~~~
--
   In file included from drivers/gpu/drm/tiny/bochs.c:29:
>> include/video/vga.h:489:1: error: expected identifier or '(' before '?' token
    ?
    ^
   In file included from include/linux/module.h:23,
                    from drivers/gpu/drm/tiny/bochs.c:5:
   drivers/gpu/drm/tiny/bochs.c: In function '__check_modeset':
>> drivers/gpu/drm/tiny/bochs.c:66:29: error: 'bochs_modeset' undeclared (first use in this function); did you mean 'drm_mode_set'?
    module_param_named(modeset, bochs_modeset, int, 0444);
                                ^~~~~~~~~~~~~
   include/linux/moduleparam.h:430:68: note: in definition of macro '__param_check'
     static inline type __always_unused *__check_##name(void) { return(p); }
                                                                       ^
   include/linux/moduleparam.h:155:2: note: in expansion of macro 'param_check_int'
     param_check_##type(name, &(value));       \
     ^~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:66:1: note: in expansion of macro 'module_param_named'
    module_param_named(modeset, bochs_modeset, int, 0444);
    ^~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:66:29: note: each undeclared identifier is reported only once for each function it appears in
    module_param_named(modeset, bochs_modeset, int, 0444);
                                ^~~~~~~~~~~~~
   include/linux/moduleparam.h:430:68: note: in definition of macro '__param_check'
     static inline type __always_unused *__check_##name(void) { return(p); }
                                                                       ^
   include/linux/moduleparam.h:155:2: note: in expansion of macro 'param_check_int'
     param_check_##type(name, &(value));       \
     ^~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:66:1: note: in expansion of macro 'module_param_named'
    module_param_named(modeset, bochs_modeset, int, 0444);
    ^~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c: At top level:
>> drivers/gpu/drm/tiny/bochs.c:66:29: error: 'bochs_modeset' undeclared here (not in a function); did you mean 'drm_mode_set'?
    module_param_named(modeset, bochs_modeset, int, 0444);
                                ^~~~~~~~~~~~~
   include/linux/moduleparam.h:298:54: note: in definition of macro '__module_param_call'
         VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } }
                                                         ^~~
   include/linux/moduleparam.h:156:2: note: in expansion of macro 'module_param_cb'
     module_param_cb(name, &param_ops_##type, &value, perm);     \
     ^~~~~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c:66:1: note: in expansion of macro 'module_param_named'
    module_param_named(modeset, bochs_modeset, int, 0444);
    ^~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/tiny/bochs.c: In function 'bochs_pci_driver_init':
   drivers/gpu/drm/tiny/bochs.c:835:1: warning: control reaches end of non-void function [-Wreturn-type]
    drm_module_pci_driver_if_modeset(bochs_pci_driver, bochs_modeset);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..


vim +489 include/video/vga.h

   487	
   488	#endif /* __linux_video_vga_h__ */
 > 489	?

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox