2018-01-17 16:28:11

by Vadim Pasternak

[permalink] [raw]
Subject: [patch v9 0/4] drivers/platform: Replace module x86/mlxcpld-hotplug with mellanox/mlxreg-hotplug

The patchset:
- replaces modules include/linux/platform_data/mlxcpld-hotplug.h and
drivers/platform/x86/mlxcpld-hotplug.c with the modules
include/linux/platform_data/mlxreg.h and
drivers/platform/mellanox/mlxreg-hotplug.c;
relevant Makefile and Kconfig are updated;
- modifies Mellanox hotplug driver for making it architecture
independent. Drivers has been tested for x86 and ARM based systems.
- includes code cleanup;
- introduces regmap interface for mlxreg-hotplug driver to allow hotplug
event functionality over programmable devices logic, when these devices
can be attached to different interfaces types, like I2C, LPC, SPI;
driver drivers/platform/x86/mlx-platform.c is updated according to new
interface.

Vadim Pasternak (4):
platform/x86: Move Mellanox hardware platform hotplug driver to
platform/mellanox
platform/mellanox: mlxreg-hotplug: Allow driver for ARM architecture
platform/mellanox: mlxreg-hotplug: Code cleanup
platform/mellanox: mlxreg-hotplug: Modify to use a regmap interface

MAINTAINERS | 7 +-
drivers/platform/Kconfig | 2 +
drivers/platform/Makefile | 1 +
drivers/platform/mellanox/Kconfig | 26 ++
drivers/platform/mellanox/Makefile | 6 +
drivers/platform/mellanox/mlxreg-hotplug.c | 622 ++++++++++++++++++++++++++
drivers/platform/x86/Kconfig | 8 -
drivers/platform/x86/Makefile | 1 -
drivers/platform/x86/mlx-platform.c | 237 +++++++---
drivers/platform/x86/mlxcpld-hotplug.c | 515 ---------------------
include/linux/platform_data/mlxcpld-hotplug.h | 99 ----
include/linux/platform_data/mlxreg.h | 144 ++++++
12 files changed, 990 insertions(+), 678 deletions(-)
create mode 100644 drivers/platform/mellanox/Kconfig
create mode 100644 drivers/platform/mellanox/Makefile
create mode 100644 drivers/platform/mellanox/mlxreg-hotplug.c
delete mode 100644 drivers/platform/x86/mlxcpld-hotplug.c
delete mode 100644 include/linux/platform_data/mlxcpld-hotplug.h
create mode 100644 include/linux/platform_data/mlxreg.h

--
2.1.4



2018-01-17 16:26:55

by Vadim Pasternak

[permalink] [raw]
Subject: [patch v9 4/4] platform/mellanox: mlxreg-hotplug: Modify to use a regmap interface

Restructure mlxreg header for unification of hotplug item definitions.

Unify hotplug items to allow any kind of item (power controller, fan
eeprom, psu eeprom, asic health) in common way.

Use a hardware independent regmap interface, enabling the support of
hotplug events over programmable devices attached to different bus
types, such as I2C, LPC, or SPI

[dvhart: Simplify exit path]
Simplify exit path: Several functions use a "goto access_error" pattern
result in a duplicated exit path at the end of the function. Address this
by using a single exit path, and checking for (ret) prior to printing the
error message. This adds a conditional, but only in the failure case, and
simplifies the exit path.

[dvhart: Cleanup local variable declarations]
Cleanup local variable declarations: Make the local variable declarations
more consistent throughout the driver. Separate inline initial assignments
when it cleans up the declaration block.

Signed-off-by: Vadim Pasternak <[email protected]>
Acked-by: Andy Shevchenko <[email protected]>
---
v8->v9:
Fixes provideded by Vadim:
- Simplify exit path in mlxreg-hotplug
- Cleanup local variable declarations
driver. Separate inline initial assignments when it cleans up the
declaration block.
v7->v8
v6->v7
Fixes added by Vadim:
- Remove include <linux/io.h> in mlxreg-hotplug.c in this patch.
v5->v6:
Fixes added by Vadim:
- rename mlxreg_core_led_platform_data to common name
mlxreg_core_platform_data;
- add cell_low and mask_low fields to
mlxreg_core_hotplug_platform_data for low aggregation interrupt
registers and check for these fields in mlxreg_hotplug_set_irq and
mlxreg_hotplug_unset_irq;
v4->v5:
Comments pointed out by Andy:
- use suffix OFFSET instead of ADDR for aggregation registers;
- return back MACROS;
- rearrange mlxreg_hotplug_attr_init routine;
---
drivers/platform/mellanox/Kconfig | 1 +
drivers/platform/mellanox/mlxreg-hotplug.c | 608 +++++++++++++++++------------
drivers/platform/x86/mlx-platform.c | 231 ++++++++---
include/linux/platform_data/mlxreg.h | 126 ++++--
4 files changed, 630 insertions(+), 336 deletions(-)

diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
index 0267e1d..591bccd 100644
--- a/drivers/platform/mellanox/Kconfig
+++ b/drivers/platform/mellanox/Kconfig
@@ -16,6 +16,7 @@ if MELLANOX_PLATFORM

config MLXREG_HOTPLUG
tristate "Mellanox platform hotplug driver support"
+ depends on REGMAP
depends on HWMON
depends on I2C
---help---
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index 556e612..18f3f3f 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -37,92 +37,88 @@
#include <linux/hwmon-sysfs.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
-#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_data/mlxreg.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/workqueue.h>

-/* Offset of event and mask registers from status register */
+/* Offset of event and mask registers from status register. */
#define MLXREG_HOTPLUG_EVENT_OFF 1
-#define MLXREG_HOTPLUG_MASK_OFF 2
+#define MLXREG_HOTPLUG_MASK_OFF 2
#define MLXREG_HOTPLUG_AGGR_MASK_OFF 1

-#define MLXREG_HOTPLUG_ATTRS_NUM 8
+/* ASIC health parameters. */
+#define MLXREG_HOTPLUG_HEALTH_MASK 0x02
+#define MLXREG_HOTPLUG_RST_CNTR 3

-/**
- * enum mlxreg_hotplug_attr_type - sysfs attributes for hotplug events:
- * @MLXREG_HOTPLUG_ATTR_TYPE_PSU: power supply unit attribute;
- * @MLXREG_HOTPLUG_ATTR_TYPE_PWR: power cable attribute;
- * @MLXREG_HOTPLUG_ATTR_TYPE_FAN: FAN drawer attribute;
- */
-enum mlxreg_hotplug_attr_type {
- MLXREG_HOTPLUG_ATTR_TYPE_PSU,
- MLXREG_HOTPLUG_ATTR_TYPE_PWR,
- MLXREG_HOTPLUG_ATTR_TYPE_FAN,
-};
+#define MLXREG_HOTPLUG_ATTRS_MAX 24

/**
* struct mlxreg_hotplug_priv_data - platform private data:
- * @irq: platform interrupt number;
+ * @irq: platform device interrupt number;
* @pdev: platform device;
* @plat: platform data;
+ * @dwork: delayed work template;
+ * @lock: spin lock;
* @hwmon: hwmon device;
* @mlxreg_hotplug_attr: sysfs attributes array;
* @mlxreg_hotplug_dev_attr: sysfs sensor device attribute array;
* @group: sysfs attribute group;
* @groups: list of sysfs attribute group for hwmon registration;
- * @dwork: delayed work template;
- * @lock: spin lock;
+ * @cell: location of top aggregation interrupt register;
+ * @mask: top aggregation interrupt common mask;
* @aggr_cache: last value of aggregation register status;
- * @psu_cache: last value of PSU register status;
- * @pwr_cache: last value of power register status;
- * @fan_cache: last value of FAN register status;
*/
struct mlxreg_hotplug_priv_data {
int irq;
+ struct device *dev;
struct platform_device *pdev;
struct mlxreg_hotplug_platform_data *plat;
+ struct regmap *regmap;
+ struct delayed_work dwork_irq;
+ struct delayed_work dwork;
+ spinlock_t lock; /* sync with interrupt */
struct device *hwmon;
- struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_NUM + 1];
+ struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1];
struct sensor_device_attribute_2
- mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_NUM];
+ mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_MAX];
struct attribute_group group;
const struct attribute_group *groups[2];
- struct delayed_work dwork;
- spinlock_t lock;
- u8 aggr_cache;
- u8 psu_cache;
- u8 pwr_cache;
- u8 fan_cache;
+ u32 cell;
+ u32 mask;
+ u32 aggr_cache;
+ bool after_probe;
};

-static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_device *data)
+static int mlxreg_hotplug_device_create(struct mlxreg_core_data *data)
{
- data->adapter = i2c_get_adapter(data->nr);
- if (!data->adapter)
+ data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
+ if (!data->hpdev.adapter)
return -EFAULT;

- data->client = i2c_new_device(data->adapter, &data->brdinfo);
- if (!data->client) {
- i2c_put_adapter(data->adapter);
- data->adapter = NULL;
+ data->hpdev.client = i2c_new_device(data->hpdev.adapter,
+ data->hpdev.brdinfo);
+ if (!data->hpdev.client) {
+ i2c_put_adapter(data->hpdev.adapter);
+ data->hpdev.adapter = NULL;
return -EFAULT;
}

return 0;
}

-static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *data)
+static void mlxreg_hotplug_device_destroy(struct mlxreg_core_data *data)
{
- if (data->client) {
- i2c_unregister_device(data->client);
- data->client = NULL;
+ if (data->hpdev.client) {
+ i2c_unregister_device(data->hpdev.client);
+ data->hpdev.client = NULL;
}

- if (data->adapter) {
- i2c_put_adapter(data->adapter);
- data->adapter = NULL;
+ if (data->hpdev.adapter) {
+ i2c_put_adapter(data->hpdev.adapter);
+ data->hpdev.adapter = NULL;
}
}

@@ -130,41 +126,76 @@ static ssize_t mlxreg_hotplug_attr_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct mlxreg_hotplug_priv_data *priv = platform_get_drvdata(pdev);
+ struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(dev);
+ struct mlxreg_core_hotplug_platform_data *pdata;
int index = to_sensor_dev_attr_2(attr)->index;
int nr = to_sensor_dev_attr_2(attr)->nr;
- u8 reg_val = 0;
-
- switch (nr) {
- case MLXREG_HOTPLUG_ATTR_TYPE_PSU:
- /* Bit = 0 : PSU is present. */
- reg_val = !!!(inb(priv->plat->psu_reg_offset) & BIT(index));
- break;
-
- case MLXREG_HOTPLUG_ATTR_TYPE_PWR:
- /* Bit = 1 : power cable is attached. */
- reg_val = !!(inb(priv->plat->pwr_reg_offset) & BIT(index %
- priv->plat->pwr_count));
- break;
-
- case MLXREG_HOTPLUG_ATTR_TYPE_FAN:
- /* Bit = 0 : FAN is present. */
- reg_val = !!!(inb(priv->plat->fan_reg_offset) & BIT(index %
- priv->plat->fan_count));
- break;
+ struct mlxreg_core_item *item;
+ struct mlxreg_core_data *data;
+ u32 regval;
+ int ret;
+
+ pdata = dev_get_platdata(&priv->pdev->dev);
+ item = pdata->items + nr;
+ data = item->data + index;
+
+ ret = regmap_read(priv->regmap, data->reg, &regval);
+ if (ret)
+ return ret;
+
+ if (item->health) {
+ regval &= data->mask;
+ } else {
+ /* Bit = 0 : functional if item->inversed is true. */
+ if (item->inversed)
+ regval = !(regval & data->mask);
+ else
+ regval = !!(regval & data->mask);
}

- return sprintf(buf, "%u\n", reg_val);
+ return sprintf(buf, "%u\n", regval);
}

#define PRIV_ATTR(i) priv->mlxreg_hotplug_attr[i]
#define PRIV_DEV_ATTR(i) priv->mlxreg_hotplug_dev_attr[i]
+
static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
{
- int num_attrs = priv->plat->psu_count + priv->plat->pwr_count +
- priv->plat->fan_count;
- int i;
+ struct mlxreg_core_hotplug_platform_data *pdata;
+ struct mlxreg_core_item *item;
+ struct mlxreg_core_data *data;
+ int num_attrs = 0, id = 0, i, j;
+
+ pdata = dev_get_platdata(&priv->pdev->dev);
+ item = pdata->items;
+
+ /* Go over all kinds of items - psu, pwr, fan. */
+ for (i = 0; i < pdata->counter; i++, item++) {
+ num_attrs += item->count;
+ data = item->data;
+ /* Go over all units within the item. */
+ for (j = 0; j < item->count; j++, data++, id++) {
+ PRIV_ATTR(id) = &PRIV_DEV_ATTR(id).dev_attr.attr;
+ PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev,
+ GFP_KERNEL,
+ data->label);
+
+ if (!PRIV_ATTR(id)->name) {
+ dev_err(priv->dev, "Memory allocation failed for attr %d.\n",
+ id);
+ return -ENOMEM;
+ }
+
+ PRIV_DEV_ATTR(id).dev_attr.attr.name =
+ PRIV_ATTR(id)->name;
+ PRIV_DEV_ATTR(id).dev_attr.attr.mode = 0444;
+ PRIV_DEV_ATTR(id).dev_attr.show =
+ mlxreg_hotplug_attr_show;
+ PRIV_DEV_ATTR(id).nr = i;
+ PRIV_DEV_ATTR(id).index = j;
+ sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr);
+ }
+ }

priv->group.attrs = devm_kzalloc(&priv->pdev->dev, num_attrs *
sizeof(struct attribute *),
@@ -172,38 +203,6 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
if (!priv->group.attrs)
return -ENOMEM;

- for (i = 0; i < num_attrs; i++) {
- PRIV_ATTR(i) = &PRIV_DEV_ATTR(i).dev_attr.attr;
-
- if (i < priv->plat->psu_count) {
- PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
- GFP_KERNEL, "psu%u", i + 1);
- PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_PSU;
- } else if (i < priv->plat->psu_count + priv->plat->pwr_count) {
- PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
- GFP_KERNEL, "pwr%u", i %
- priv->plat->pwr_count + 1);
- PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_PWR;
- } else {
- PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
- GFP_KERNEL, "fan%u", i %
- priv->plat->fan_count + 1);
- PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_FAN;
- }
-
- if (!PRIV_ATTR(i)->name) {
- dev_err(&priv->pdev->dev, "Memory allocation failed for sysfs attribute %d.\n",
- i + 1);
- return -ENOMEM;
- }
-
- PRIV_DEV_ATTR(i).dev_attr.attr.name = PRIV_ATTR(i)->name;
- PRIV_DEV_ATTR(i).dev_attr.attr.mode = S_IRUGO;
- PRIV_DEV_ATTR(i).dev_attr.show = mlxreg_hotplug_attr_show;
- PRIV_DEV_ATTR(i).index = i;
- sysfs_attr_init(&PRIV_DEV_ATTR(i).dev_attr.attr);
- }
-
priv->group.attrs = priv->mlxreg_hotplug_attr;
priv->groups[0] = &priv->group;
priv->groups[1] = NULL;
@@ -211,20 +210,13 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
return 0;
}

-static inline void
-mlxreg_hotplug_work_helper(struct device *dev,
- struct mlxreg_hotplug_device *item, u8 is_inverse,
- u16 offset, u8 mask, u8 *cache)
+static void
+mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
+ struct mlxreg_core_item *item)
{
- u8 val, asserted;
- int bit;
-
- /* Mask event. */
- outb(0, offset + MLXREG_HOTPLUG_MASK_OFF);
- /* Read status. */
- val = inb(offset) & mask;
- asserted = *cache ^ val;
- *cache = val;
+ struct mlxreg_core_data *data;
+ u32 asserted, regval, bit;
+ int ret;

/*
* Validate if item related to received signal type is valid.
@@ -234,86 +226,177 @@ mlxreg_hotplug_work_helper(struct device *dev,
* signals from other devices if any.
*/
if (unlikely(!item)) {
- dev_err(dev, "False signal is received: register at offset 0x%02x, mask 0x%02x.\n",
- offset, mask);
+ dev_err(priv->dev, "False signal: at offset:mask 0x%02x:0x%02x.\n",
+ item->reg, item->mask);
+
return;
}

+ /* Mask event. */
+ ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
+ 0);
+ if (ret)
+ goto out;
+
+ /* Read status. */
+ ret = regmap_read(priv->regmap, item->reg, &regval);
+ if (ret)
+ goto out;
+
+ /* Set asserted bits and save last status. */
+ regval &= item->mask;
+ asserted = item->cache ^ regval;
+ item->cache = regval;
+
for_each_set_bit(bit, (unsigned long *)&asserted, 8) {
- if (val & BIT(bit)) {
- if (is_inverse)
- mlxreg_hotplug_device_destroy(item + bit);
+ data = item->data + bit;
+ if (regval & BIT(bit)) {
+ if (item->inversed)
+ mlxreg_hotplug_device_destroy(data);
else
- mlxreg_hotplug_device_create(item + bit);
+ mlxreg_hotplug_device_create(data);
} else {
- if (is_inverse)
- mlxreg_hotplug_device_create(item + bit);
+ if (item->inversed)
+ mlxreg_hotplug_device_create(data);
else
- mlxreg_hotplug_device_destroy(item + bit);
+ mlxreg_hotplug_device_destroy(data);
}
}

/* Acknowledge event. */
- outb(0, offset + MLXREG_HOTPLUG_EVENT_OFF);
+ ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_EVENT_OFF,
+ 0);
+ if (ret)
+ goto out;
+
/* Unmask event. */
- outb(mask, offset + MLXREG_HOTPLUG_MASK_OFF);
+ ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
+ item->mask);
+
+ out:
+ if (ret)
+ dev_err(priv->dev, "Failed to complete workqueue.\n");
+}
+
+static void
+mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
+ struct mlxreg_core_item *item)
+{
+ struct mlxreg_core_data *data = item->data;
+ u32 regval;
+ int i, ret;
+
+ for (i = 0; i < item->count; i++, data++) {
+ /* Mask event. */
+ ret = regmap_write(priv->regmap, data->reg +
+ MLXREG_HOTPLUG_MASK_OFF, 0);
+ if (ret)
+ goto out;
+
+ /* Read status. */
+ ret = regmap_read(priv->regmap, data->reg, &regval);
+ if (ret)
+ goto out;
+
+ regval &= data->mask;
+ item->cache = regval;
+ if (regval == MLXREG_HOTPLUG_HEALTH_MASK) {
+ if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) ||
+ !priv->after_probe) {
+ mlxreg_hotplug_device_create(data);
+ data->attached = true;
+ }
+ } else {
+ if (data->attached) {
+ mlxreg_hotplug_device_destroy(data);
+ data->attached = false;
+ data->health_cntr = 0;
+ }
+ }
+
+ /* Acknowledge event. */
+ ret = regmap_write(priv->regmap, data->reg +
+ MLXREG_HOTPLUG_EVENT_OFF, 0);
+ if (ret)
+ goto out;
+
+ /* Unmask event. */
+ ret = regmap_write(priv->regmap, data->reg +
+ MLXREG_HOTPLUG_MASK_OFF, data->mask);
+ if (ret)
+ goto out;
+ }
+
+ out:
+ if (ret)
+ dev_err(priv->dev, "Failed to complete workqueue.\n");
}

/*
- * mlxreg_hotplug_work_handler - performs traversing of CPLD interrupt
+ * mlxreg_hotplug_work_handler - performs traversing of device interrupt
* registers according to the below hierarchy schema:
*
- * Aggregation registers (status/mask)
- * PSU registers: *---*
- * *-----------------* | |
- * |status/event/mask|----->| * |
- * *-----------------* | |
- * Power registers: | |
- * *-----------------* | |
- * |status/event/mask|----->| * |---> CPU
- * *-----------------* | |
- * FAN registers:
- * *-----------------* | |
- * |status/event/mask|----->| * |
- * *-----------------* | |
- * *---*
+ * Aggregation registers (status/mask)
+ * PSU registers: *---*
+ * *-----------------* | |
+ * |status/event/mask|-----> | * |
+ * *-----------------* | |
+ * Power registers: | |
+ * *-----------------* | |
+ * |status/event/mask|-----> | * |
+ * *-----------------* | |
+ * FAN registers: | |--> CPU
+ * *-----------------* | |
+ * |status/event/mask|-----> | * |
+ * *-----------------* | |
+ * ASIC registers: | |
+ * *-----------------* | |
+ * |status/event/mask|-----> | * |
+ * *-----------------* | |
+ * *---*
+ *
* In case some system changed are detected: FAN in/out, PSU in/out, power
- * cable attached/detached, relevant device is created or destroyed.
+ * cable attached/detached, ASIC helath good/bad, relevant device is created
+ * or destroyed.
*/
static void mlxreg_hotplug_work_handler(struct work_struct *work)
{
- struct mlxreg_hotplug_priv_data *priv = container_of(work,
- struct mlxreg_hotplug_priv_data, dwork.work);
- u8 val, aggr_asserted;
+ struct mlxreg_core_hotplug_platform_data *pdata;
+ struct mlxreg_hotplug_priv_data *priv;
+ struct mlxreg_core_item *item;
+ u32 regval, aggr_asserted;
unsigned long flags;
+ int i, ret;
+
+ priv = container_of(work, struct mlxreg_hotplug_priv_data,
+ dwork_irq.work);
+ pdata = dev_get_platdata(&priv->pdev->dev);
+ item = pdata->items;

/* Mask aggregation event. */
- outb(0, priv->plat->top_aggr_offset + MLXREG_HOTPLUG_AGGR_MASK_OFF);
+ ret = regmap_write(priv->regmap, pdata->cell +
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
+ if (ret < 0)
+ goto out;
+
/* Read aggregation status. */
- val = inb(priv->plat->top_aggr_offset) & priv->plat->top_aggr_mask;
- aggr_asserted = priv->aggr_cache ^ val;
- priv->aggr_cache = val;
-
- /* Handle PSU configuration changes. */
- if (aggr_asserted & priv->plat->top_aggr_psu_mask)
- mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->psu,
- 1, priv->plat->psu_reg_offset,
- priv->plat->psu_mask,
- &priv->psu_cache);
-
- /* Handle power cable configuration changes. */
- if (aggr_asserted & priv->plat->top_aggr_pwr_mask)
- mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->pwr,
- 0, priv->plat->pwr_reg_offset,
- priv->plat->pwr_mask,
- &priv->pwr_cache);
-
- /* Handle FAN configuration changes. */
- if (aggr_asserted & priv->plat->top_aggr_fan_mask)
- mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->fan,
- 1, priv->plat->fan_reg_offset,
- priv->plat->fan_mask,
- &priv->fan_cache);
+ ret = regmap_read(priv->regmap, pdata->cell, &regval);
+ if (ret)
+ goto out;
+
+ regval &= pdata->mask;
+ aggr_asserted = priv->aggr_cache ^ regval;
+ priv->aggr_cache = regval;
+
+ /* Handle topology and health configuration changes. */
+ for (i = 0; i < pdata->counter; i++, item++) {
+ if (aggr_asserted & item->aggr_mask) {
+ if (item->health)
+ mlxreg_hotplug_health_work_helper(priv, item);
+ else
+ mlxreg_hotplug_work_helper(priv, item);
+ }
+ }

if (aggr_asserted) {
spin_lock_irqsave(&priv->lock, flags);
@@ -328,8 +411,8 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
* validates that no new signals have been received during
* masking.
*/
- cancel_delayed_work(&priv->dwork);
- schedule_delayed_work(&priv->dwork, 0);
+ cancel_delayed_work(&priv->dwork_irq);
+ schedule_delayed_work(&priv->dwork_irq, 0);

spin_unlock_irqrestore(&priv->lock, flags);

@@ -337,92 +420,119 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
}

/* Unmask aggregation event (no need acknowledge). */
- outb(priv->plat->top_aggr_mask, priv->plat->top_aggr_offset +
- MLXREG_HOTPLUG_AGGR_MASK_OFF);
+ ret = regmap_write(priv->regmap, pdata->cell +
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
+
+ out:
+ if (ret)
+ dev_err(priv->dev, "Failed to complete workqueue.\n");
}

-static void mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
+static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
{
- /* Clear psu presense event. */
- outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
- /* Set psu initial status as mask and unmask psu event. */
- priv->psu_cache = priv->plat->psu_mask;
- outb(priv->plat->psu_mask, priv->plat->psu_reg_offset +
- MLXREG_HOTPLUG_MASK_OFF);
-
- /* Clear power cable event. */
- outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
- /* Keep power initial status as zero and unmask power event. */
- outb(priv->plat->pwr_mask, priv->plat->pwr_reg_offset +
- MLXREG_HOTPLUG_MASK_OFF);
-
- /* Clear fan presense event. */
- outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
- /* Set fan initial status as mask and unmask fan event. */
- priv->fan_cache = priv->plat->fan_mask;
- outb(priv->plat->fan_mask, priv->plat->fan_reg_offset +
- MLXREG_HOTPLUG_MASK_OFF);
+ struct mlxreg_core_hotplug_platform_data *pdata;
+ struct mlxreg_core_item *item;
+ int i, ret;
+
+ pdata = dev_get_platdata(&priv->pdev->dev);
+ item = pdata->items;
+
+ for (i = 0; i < pdata->counter; i++, item++) {
+ /* Clear group presense event. */
+ ret = regmap_write(priv->regmap, item->reg +
+ MLXREG_HOTPLUG_EVENT_OFF, 0);
+ if (ret)
+ goto out;
+
+ /* Set group initial status as mask and unmask group event. */
+ if (item->inversed) {
+ item->cache = item->mask;
+ ret = regmap_write(priv->regmap, item->reg +
+ MLXREG_HOTPLUG_MASK_OFF,
+ item->mask);
+ if (ret)
+ goto out;
+ }
+ }

/* Keep aggregation initial status as zero and unmask events. */
- outb(priv->plat->top_aggr_mask, priv->plat->top_aggr_offset +
- MLXREG_HOTPLUG_AGGR_MASK_OFF);
+ ret = regmap_write(priv->regmap, pdata->cell +
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
+ if (ret)
+ goto out;
+
+ /* Keep low aggregation initial status as zero and unmask events. */
+ if (pdata->cell_low) {
+ ret = regmap_write(priv->regmap, pdata->cell_low +
+ MLXREG_HOTPLUG_AGGR_MASK_OFF,
+ pdata->mask_low);
+ if (ret)
+ goto out;
+ }

/* Invoke work handler for initializing hot plug devices setting. */
- mlxreg_hotplug_work_handler(&priv->dwork.work);
+ mlxreg_hotplug_work_handler(&priv->dwork_irq.work);

+ out:
+ if (ret)
+ dev_err(priv->dev, "Failed to set interrupts.\n");
enable_irq(priv->irq);
+ return ret;
}

static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
{
- int i;
+ struct mlxreg_core_hotplug_platform_data *pdata;
+ struct mlxreg_core_item *item;
+ struct mlxreg_core_data *data;
+ int count, i, j;

+ pdata = dev_get_platdata(&priv->pdev->dev);
+ item = pdata->items;
disable_irq(priv->irq);
- cancel_delayed_work_sync(&priv->dwork);
-
- /* Mask aggregation event. */
- outb(0, priv->plat->top_aggr_offset + MLXREG_HOTPLUG_AGGR_MASK_OFF);
-
- /* Mask psu presense event. */
- outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
- /* Clear psu presense event. */
- outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
-
- /* Mask power cable event. */
- outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
- /* Clear power cable event. */
- outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
-
- /* Mask fan presense event. */
- outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
- /* Clear fan presense event. */
- outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
-
- /* Remove all the attached devices. */
- for (i = 0; i < priv->plat->psu_count; i++)
- mlxreg_hotplug_device_destroy(priv->plat->psu + i);
+ cancel_delayed_work_sync(&priv->dwork_irq);

- for (i = 0; i < priv->plat->pwr_count; i++)
- mlxreg_hotplug_device_destroy(priv->plat->pwr + i);
+ /* Mask low aggregation event, if defined. */
+ if (pdata->cell_low)
+ regmap_write(priv->regmap, pdata->cell_low +
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);

- for (i = 0; i < priv->plat->fan_count; i++)
- mlxreg_hotplug_device_destroy(priv->plat->fan + i);
+ /* Mask aggregation event. */
+ regmap_write(priv->regmap, pdata->cell + MLXREG_HOTPLUG_AGGR_MASK_OFF,
+ 0);
+
+ /* Clear topology configurations. */
+ for (i = 0; i < pdata->counter; i++, item++) {
+ data = item->data;
+ /* Mask group presense event. */
+ regmap_write(priv->regmap, data->reg + MLXREG_HOTPLUG_MASK_OFF,
+ 0);
+ /* Clear group presense event. */
+ regmap_write(priv->regmap, data->reg +
+ MLXREG_HOTPLUG_EVENT_OFF, 0);
+
+ /* Remove all the attached devices in group. */
+ count = item->count;
+ for (j = 0; j < count; j++, data++)
+ mlxreg_hotplug_device_destroy(data);
+ }
}

static irqreturn_t mlxreg_hotplug_irq_handler(int irq, void *dev)
{
- struct mlxreg_hotplug_priv_data *priv =
- (struct mlxreg_hotplug_priv_data *)dev;
+ struct mlxreg_hotplug_priv_data *priv;
+
+ priv = (struct mlxreg_hotplug_priv_data *)dev;

/* Schedule work task for immediate execution.*/
- schedule_delayed_work(&priv->dwork, 0);
+ schedule_delayed_work(&priv->dwork_irq, 0);

return IRQ_HANDLED;
}

static int mlxreg_hotplug_probe(struct platform_device *pdev)
{
- struct mlxreg_hotplug_platform_data *pdata;
+ struct mlxreg_core_hotplug_platform_data *pdata;
struct mlxreg_hotplug_priv_data *priv;
int err;

@@ -436,31 +546,42 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;

- priv->pdev = pdev;
- priv->plat = pdata;
-
- priv->irq = platform_get_irq(pdev, 0);
- if (priv->irq < 0) {
- dev_err(&pdev->dev, "Failed to get platform irq: %d\n",
- priv->irq);
- return priv->irq;
+ if (pdata->irq) {
+ priv->irq = pdata->irq;
+ } else {
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq < 0) {
+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n",
+ priv->irq);
+ return priv->irq;
+ }
}

+ priv->regmap = pdata->regmap;
+ priv->dev = pdev->dev.parent;
+ priv->pdev = pdev;
+
err = devm_request_irq(&pdev->dev, priv->irq,
- mlxreg_hotplug_irq_handler, 0, pdev->name,
- priv);
+ mlxreg_hotplug_irq_handler, IRQF_TRIGGER_FALLING
+ | IRQF_SHARED, "mlxreg-hotplug", priv);
if (err) {
dev_err(&pdev->dev, "Failed to request irq: %d\n", err);
return err;
}
- disable_irq(priv->irq);

- INIT_DELAYED_WORK(&priv->dwork, mlxreg_hotplug_work_handler);
+ disable_irq(priv->irq);
spin_lock_init(&priv->lock);
+ INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler);
+ /* Perform initial interrupts setup. */
+ mlxreg_hotplug_set_irq(priv);
+
+ priv->after_probe = true;
+ dev_set_drvdata(&pdev->dev, priv);

err = mlxreg_hotplug_attr_init(priv);
if (err) {
- dev_err(&pdev->dev, "Failed to allocate attributes: %d\n", err);
+ dev_err(&pdev->dev, "Failed to allocate attributes: %d\n",
+ err);
return err;
}

@@ -472,17 +593,12 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
return PTR_ERR(priv->hwmon);
}

- platform_set_drvdata(pdev, priv);
-
- /* Perform initial interrupts setup. */
- mlxreg_hotplug_set_irq(priv);
-
return 0;
}

static int mlxreg_hotplug_remove(struct platform_device *pdev)
{
- struct mlxreg_hotplug_priv_data *priv = platform_get_drvdata(pdev);
+ struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(&pdev->dev);

/* Clean interrupts setup. */
mlxreg_hotplug_unset_irq(priv);
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 5601714..03c9e7a 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -35,20 +35,22 @@
#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
+#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_data/i2c-mux-reg.h>
#include <linux/platform_data/mlxreg.h>
+#include <linux/regmap.h>

#define MLX_PLAT_DEVICE_NAME "mlxplat"

/* LPC bus IO offsets */
#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
-#define MLXPLAT_CPLD_LPC_REG_AGGR_ADRR 0x253a
-#define MLXPLAT_CPLD_LPC_REG_PSU_ADRR 0x2558
-#define MLXPLAT_CPLD_LPC_REG_PWR_ADRR 0x2564
-#define MLXPLAT_CPLD_LPC_REG_FAN_ADRR 0x2588
+#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
+#define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58
+#define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64
+#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88
#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
@@ -138,78 +140,194 @@ static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
};

/* Platform hotplug devices */
-static struct mlxreg_hotplug_device mlxplat_mlxcpld_psu[] = {
+static struct i2c_board_info mlxplat_mlxcpld_psu[] = {
{
- .brdinfo = { I2C_BOARD_INFO("24c02", 0x51) },
- .nr = 10,
+ I2C_BOARD_INFO("24c02", 0x51),
},
{
- .brdinfo = { I2C_BOARD_INFO("24c02", 0x50) },
- .nr = 10,
+ I2C_BOARD_INFO("24c02", 0x50),
},
};

-static struct mlxreg_hotplug_device mlxplat_mlxcpld_pwr[] = {
+static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
{
- .brdinfo = { I2C_BOARD_INFO("dps460", 0x59) },
- .nr = 10,
+ I2C_BOARD_INFO("dps460", 0x59),
},
{
- .brdinfo = { I2C_BOARD_INFO("dps460", 0x58) },
- .nr = 10,
+ I2C_BOARD_INFO("dps460", 0x58),
},
};

-static struct mlxreg_hotplug_device mlxplat_mlxcpld_fan[] = {
+static struct i2c_board_info mlxplat_mlxcpld_fan[] = {
{
- .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
- .nr = 11,
+ I2C_BOARD_INFO("24c32", 0x50),
},
{
- .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
- .nr = 12,
+ I2C_BOARD_INFO("24c32", 0x50),
},
{
- .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
- .nr = 13,
+ I2C_BOARD_INFO("24c32", 0x50),
},
{
- .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
- .nr = 14,
+ I2C_BOARD_INFO("24c32", 0x50),
},
};

/* Platform hotplug default data */
+static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = {
+ {
+ .label = "psu1",
+ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
+ .mask = BIT(0),
+ .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
+ .hpdev.nr = 10,
+ },
+ {
+ .label = "psu2",
+ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
+ .mask = BIT(1),
+ .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
+ .hpdev.nr = 10,
+ },
+};
+
+static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = {
+ {
+ .label = "pwr1",
+ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
+ .mask = BIT(0),
+ .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
+ .hpdev.nr = 10,
+ },
+ {
+ .label = "pwr2",
+ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
+ .mask = BIT(1),
+ .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
+ .hpdev.nr = 10,
+ },
+};
+
+static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = {
+ {
+ .label = "fan1",
+ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
+ .mask = BIT(0),
+ .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0],
+ .hpdev.nr = 11,
+ },
+ {
+ .label = "fan2",
+ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
+ .mask = BIT(1),
+ .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1],
+ .hpdev.nr = 12,
+ },
+ {
+ .label = "fan3",
+ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
+ .mask = BIT(2),
+ .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2],
+ .hpdev.nr = 13,
+ },
+ {
+ .label = "fan4",
+ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
+ .mask = BIT(3),
+ .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3],
+ .hpdev.nr = 14,
+ },
+};
+
+static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
+ {
+ .data = mlxplat_mlxcpld_default_psu_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
+ .mask = MLXPLAT_CPLD_PSU_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
+ .inversed = 1,
+ .health = false,
+ },
+ {
+ .data = mlxplat_mlxcpld_default_pwr_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
+ .mask = MLXPLAT_CPLD_PWR_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
+ .inversed = 0,
+ .health = false,
+ },
+ {
+ .data = mlxplat_mlxcpld_default_fan_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
+ .mask = MLXPLAT_CPLD_FAN_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
+ .inversed = 1,
+ .health = false,
+ },
+};
+
static
-struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_default_data = {
- .top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR,
- .top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
- .top_aggr_psu_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
- .psu_reg_offset = MLXPLAT_CPLD_LPC_REG_PSU_ADRR,
- .psu_mask = MLXPLAT_CPLD_PSU_MASK,
- .psu_count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
- .psu = mlxplat_mlxcpld_psu,
- .top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
- .pwr_reg_offset = MLXPLAT_CPLD_LPC_REG_PWR_ADRR,
- .pwr_mask = MLXPLAT_CPLD_PWR_MASK,
- .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
- .pwr = mlxplat_mlxcpld_pwr,
- .top_aggr_fan_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
- .fan_reg_offset = MLXPLAT_CPLD_LPC_REG_FAN_ADRR,
- .fan_mask = MLXPLAT_CPLD_FAN_MASK,
- .fan_count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
- .fan = mlxplat_mlxcpld_fan,
+struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
+ .items = mlxplat_mlxcpld_default_items,
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items),
+ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
+ .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
};

/* Platform hotplug MSN21xx system family data */
+static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = {
+ {
+ .data = mlxplat_mlxcpld_default_pwr_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
+ .mask = MLXPLAT_CPLD_PWR_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
+ .inversed = 0,
+ .health = false,
+ },
+};
+
static
-struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
- .top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR,
- .top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX,
- .top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX,
- .pwr_reg_offset = MLXPLAT_CPLD_LPC_REG_PWR_ADRR,
- .pwr_mask = MLXPLAT_CPLD_PWR_MASK,
- .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
+struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
+ .items = mlxplat_mlxcpld_msn21xx_items,
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items),
+ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
+ .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
+};
+
+struct mlxplat_mlxcpld_regmap_context {
+ void __iomem *base;
+};
+
+static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx;
+
+static int
+mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct mlxplat_mlxcpld_regmap_context *ctx = context;
+
+ *val = ioread8(ctx->base + reg);
+ return 0;
+}
+
+static int
+mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct mlxplat_mlxcpld_regmap_context *ctx = context;
+
+ iowrite8(val, ctx->base + reg);
+ return 0;
+}
+
+static const struct regmap_config mlxplat_mlxcpld_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 255,
+ .reg_read = mlxplat_mlxcpld_reg_read,
+ .reg_write = mlxplat_mlxcpld_reg_write,
};

static struct resource mlxplat_mlxcpld_resources[] = {
@@ -217,7 +335,7 @@ static struct resource mlxplat_mlxcpld_resources[] = {
};

static struct platform_device *mlxplat_dev;
-static struct mlxreg_hotplug_platform_data *mlxplat_hotplug;
+static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;

static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
{
@@ -328,6 +446,21 @@ static int __init mlxplat_init(void)
}
}

+ mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev,
+ mlxplat_lpc_resources[1].start, 1);
+ if (IS_ERR(mlxplat_mlxcpld_regmap_ctx.base)) {
+ err = PTR_ERR(mlxplat_mlxcpld_regmap_ctx.base);
+ goto fail_platform_mux_register;
+ }
+
+ mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
+ &mlxplat_mlxcpld_regmap_ctx,
+ &mlxplat_mlxcpld_regmap_config);
+ if (IS_ERR(mlxplat_hotplug->regmap)) {
+ err = PTR_ERR(mlxplat_hotplug->regmap);
+ goto fail_platform_mux_register;
+ }
+
priv->pdev_hotplug = platform_device_register_resndata(
&mlxplat_dev->dev, "mlxreg-hotplug",
PLATFORM_DEVID_NONE,
diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
index 5c98ad1..c25623b 100644
--- a/include/linux/platform_data/mlxreg.h
+++ b/include/linux/platform_data/mlxreg.h
@@ -34,13 +34,15 @@
#ifndef __LINUX_PLATFORM_DATA_MLXREG_H
#define __LINUX_PLATFORM_DATA_MLXREG_H

+#define MLXREG_CORE_LABEL_MAX_SIZE 32
+
/**
* struct mlxreg_hotplug_device - I2C device data:
+ *
* @adapter: I2C device adapter;
* @client: I2C device client;
* @brdinfo: device board information;
* @nr: I2C device adapter number, to which device is to be attached;
- * @np - pointer to node platform associated with attribute;
*
* Structure represents I2C hotplug device static data (board topology) and
* dynamic data (related kernel objects handles).
@@ -48,53 +50,95 @@
struct mlxreg_hotplug_device {
struct i2c_adapter *adapter;
struct i2c_client *client;
- struct i2c_board_info brdinfo;
+ struct i2c_board_info *brdinfo;
int nr;
+};
+
+/**
+ * struct mlxreg_core_data - attributes control data:
+ *
+ * @label: attribute label;
+ * @label: attribute register offset;
+ * @reg: attribute register;
+ * @mask: attribute access mask;
+ * @mode: access mode;
+ * @bit: attribute effective bit;
+ * @np - pointer to node platform associated with attribute;
+ * @hpdev - hotplug device data;
+ * @health_cntr: dynamic device health indication counter;
+ * @attached: true if device has been attached after good helath indication;
+ */
+struct mlxreg_core_data {
+ char label[MLXREG_CORE_LABEL_MAX_SIZE];
+ u32 reg;
+ u32 mask;
+ u32 bit;
+ umode_t mode;
struct device_node *np;
+ struct mlxreg_hotplug_device hpdev;
+ u8 health_cntr;
+ bool attached;
+};
+
+/**
+ * struct mlxreg_core_item - same type components controlled by the driver:
+ *
+ * @data: component data;
+ * @aggr_mask: group aggregation mask;
+ * @reg: group interrupt status register;
+ * @mask: group interrupt mask;
+ * @cache: last status value for elements fro the same group;
+ * @count: number of available elements in the group;
+ * @ind: element's index inside the group;
+ * @inversed: if 0: 0 for signal status is OK, if 1 - 1 is OK;
+ * @health: true if device has health indication, false in other case;
+ */
+struct mlxreg_core_item {
+ struct mlxreg_core_data *data;
+ u32 aggr_mask;
+ u32 reg;
+ u32 mask;
+ u32 cache;
+ u8 count;
+ u8 ind;
+ u8 inversed;
+ u8 health;
+};
+
+/**
+ * struct mlxreg_core_platform_data - platform data:
+ *
+ * @led_data: led private data;
+ * @regmap: register map of parent device;
+ * @counter: number of led instances;
+ */
+struct mlxreg_core_platform_data {
+ struct mlxreg_core_data *data;
+ void *regmap;
+ int counter;
};

/**
- * struct mlxreg_hotplug_platform_data - device platform data:
- * @top_aggr_offset: offset of top aggregation interrupt register;
- * @top_aggr_mask: top aggregation interrupt common mask;
- * @top_aggr_psu_mask: top aggregation interrupt PSU mask;
- * @psu_reg_offset: offset of PSU interrupt register;
- * @psu_mask: PSU interrupt mask;
- * @psu_count: number of equipped replaceable PSUs;
- * @psu: pointer to PSU devices data array;
- * @top_aggr_pwr_mask: top aggregation interrupt power mask;
- * @pwr_reg_offset: offset of power interrupt register
- * @pwr_mask: power interrupt mask;
- * @pwr_count: number of power sources;
- * @pwr: pointer to power devices data array;
- * @top_aggr_fan_mask: top aggregation interrupt FAN mask;
- * @fan_reg_offset: offset of FAN interrupt register;
- * @fan_mask: FAN interrupt mask;
- * @fan_count: number of equipped replaceable FANs;
- * @fan: pointer to FAN devices data array;
+ * struct mlxreg_core_hotplug_platform_data - hotplug platform data:
*
- * Structure represents board platform data, related to system hotplug events,
- * like FAN, PSU, power cable insertion and removing. This data provides the
- * number of hot-pluggable devices and hardware description for event handling.
+ * @items: same type components with the hotplug capability;
+ * @irq: platform interrupt number;
+ * @regmap: register map of parent device;
+ * @counter: number of the components with the hotplug capability;
+ * @cell: location of top aggregation interrupt register;
+ * @mask: top aggregation interrupt common mask;
+ * @cell_low: location of low aggregation interrupt register;
+ * @mask_low: low aggregation interrupt common mask;
*/
-struct mlxreg_hotplug_platform_data {
- u16 top_aggr_offset;
- u8 top_aggr_mask;
- u8 top_aggr_psu_mask;
- u16 psu_reg_offset;
- u8 psu_mask;
- u8 psu_count;
- struct mlxreg_hotplug_device *psu;
- u8 top_aggr_pwr_mask;
- u16 pwr_reg_offset;
- u8 pwr_mask;
- u8 pwr_count;
- struct mlxreg_hotplug_device *pwr;
- u8 top_aggr_fan_mask;
- u16 fan_reg_offset;
- u8 fan_mask;
- u8 fan_count;
- struct mlxreg_hotplug_device *fan;
+struct mlxreg_core_hotplug_platform_data {
+ struct mlxreg_core_item *items;
+ int irq;
+ void *regmap;
+ int counter;
+ u32 cell;
+ u32 mask;
+ u32 cell_low;
+ u32 mask_low;
};

#endif /* __LINUX_PLATFORM_DATA_MLXREG_H */
--
2.1.4


2018-01-17 16:27:19

by Vadim Pasternak

[permalink] [raw]
Subject: [patch v9 2/4] platform/mellanox: mlxreg-hotplug: Allow driver for ARM architecture

It allows driver to run on x86 and ARM architecture based systems.

Signed-off-by: Vadim Pasternak <[email protected]>
---
v9->v8
Comments pointed out by Darren:
- Leave in this patch only the code related to ARM architecture.
Move other code to a separate patch, since it is not related to
subject.
---
drivers/platform/mellanox/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
index d735292..0267e1d 100644
--- a/drivers/platform/mellanox/Kconfig
+++ b/drivers/platform/mellanox/Kconfig
@@ -5,7 +5,7 @@

menuconfig MELLANOX_PLATFORM
bool "Platform support for Mellanox hardware"
- depends on X86 || COMPILE_TEST
+ depends on X86 || ARM || COMPILE_TEST
---help---
Say Y here to get to see options for platform support for
Mellanox systems. This option alone does not add any kernel code.
--
2.1.4


2018-01-17 16:27:31

by Vadim Pasternak

[permalink] [raw]
Subject: [patch v9 3/4] platform/mellanox: mlxreg-hotplug: Code cleanup

Renaming field bus in structure mlxreg_hotplug_device to nr to have a name
consistent with Linux i2c naming.

Removing unnecessary includes.

Removing from mlxreg_hotplug_device_create dev_err to upper layer should
produce error on EFAULT return.

Relocation mlxreg_hotplug_device_create/destroy to the beginning of the
mlxreg-hotplug.c in order to have attribute related code at the same
location.

Add to structure mlxreg_hotplug_device device node handle for devices
defined in device table tree;

Signed-off-by: Vadim Pasternak <[email protected]>
Acked-by: Andy Shevchenko <[email protected]>
---
v9->v8
Comments pointed out by Darren:
- Remove from this patch code related to ARM architecture.
v7->v8
Fixes added by Vadim:
- Drop routines using of_update_property. It causes Kbuild error for
ia64 arch during on modpost, since of_update_property is not exported.
The intension of these routines was the dynamic enabling and disabling
of the device tree node, when relevant signal is received. Such node
has been supposed to set with the property disabled in DTS, and
changing property by using of_update_property just flips the device.
It was OK for arm and sparc, but not for ia64.
v6->v7
Fixes added by Vadim:
- Dont remove include <linux/io.h> in mlxreg-hotplug.c to avoid Kbuild
errors. Make this change in patch 3/3.
v5->v6:
v4->v5:
Comments pointed out by Andy:
- remove unnessecary logic in Kconfig;
- remove !COMPILE_TEST in mlxreg-hotplug;
---
drivers/platform/mellanox/mlxreg-hotplug.c | 70 +++++++++++++-----------------
drivers/platform/x86/mlx-platform.c | 16 +++----
include/linux/platform_data/mlxreg.h | 6 ++-
3 files changed, 43 insertions(+), 49 deletions(-)

diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index 2866c76..556e612 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -41,8 +41,6 @@
#include <linux/module.h>
#include <linux/platform_data/mlxreg.h>
#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
#include <linux/workqueue.h>

/* Offset of event and mask registers from status register */
@@ -99,6 +97,35 @@ struct mlxreg_hotplug_priv_data {
u8 fan_cache;
};

+static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_device *data)
+{
+ data->adapter = i2c_get_adapter(data->nr);
+ if (!data->adapter)
+ return -EFAULT;
+
+ data->client = i2c_new_device(data->adapter, &data->brdinfo);
+ if (!data->client) {
+ i2c_put_adapter(data->adapter);
+ data->adapter = NULL;
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *data)
+{
+ if (data->client) {
+ i2c_unregister_device(data->client);
+ data->client = NULL;
+ }
+
+ if (data->adapter) {
+ i2c_put_adapter(data->adapter);
+ data->adapter = NULL;
+ }
+}
+
static ssize_t mlxreg_hotplug_attr_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -184,41 +211,6 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
return 0;
}

-static int mlxreg_hotplug_device_create(struct device *dev,
- struct mlxreg_hotplug_device *item)
-{
- item->adapter = i2c_get_adapter(item->bus);
- if (!item->adapter) {
- dev_err(dev, "Failed to get adapter for bus %d\n",
- item->bus);
- return -EFAULT;
- }
-
- item->client = i2c_new_device(item->adapter, &item->brdinfo);
- if (!item->client) {
- dev_err(dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
- item->brdinfo.type, item->bus, item->brdinfo.addr);
- i2c_put_adapter(item->adapter);
- item->adapter = NULL;
- return -EFAULT;
- }
-
- return 0;
-}
-
-static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *item)
-{
- if (item->client) {
- i2c_unregister_device(item->client);
- item->client = NULL;
- }
-
- if (item->adapter) {
- i2c_put_adapter(item->adapter);
- item->adapter = NULL;
- }
-}
-
static inline void
mlxreg_hotplug_work_helper(struct device *dev,
struct mlxreg_hotplug_device *item, u8 is_inverse,
@@ -252,10 +244,10 @@ mlxreg_hotplug_work_helper(struct device *dev,
if (is_inverse)
mlxreg_hotplug_device_destroy(item + bit);
else
- mlxreg_hotplug_device_create(dev, item + bit);
+ mlxreg_hotplug_device_create(item + bit);
} else {
if (is_inverse)
- mlxreg_hotplug_device_create(dev, item + bit);
+ mlxreg_hotplug_device_create(item + bit);
else
mlxreg_hotplug_device_destroy(item + bit);
}
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 0fbec1f..5601714 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -141,41 +141,41 @@ static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
static struct mlxreg_hotplug_device mlxplat_mlxcpld_psu[] = {
{
.brdinfo = { I2C_BOARD_INFO("24c02", 0x51) },
- .bus = 10,
+ .nr = 10,
},
{
.brdinfo = { I2C_BOARD_INFO("24c02", 0x50) },
- .bus = 10,
+ .nr = 10,
},
};

static struct mlxreg_hotplug_device mlxplat_mlxcpld_pwr[] = {
{
.brdinfo = { I2C_BOARD_INFO("dps460", 0x59) },
- .bus = 10,
+ .nr = 10,
},
{
.brdinfo = { I2C_BOARD_INFO("dps460", 0x58) },
- .bus = 10,
+ .nr = 10,
},
};

static struct mlxreg_hotplug_device mlxplat_mlxcpld_fan[] = {
{
.brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
- .bus = 11,
+ .nr = 11,
},
{
.brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
- .bus = 12,
+ .nr = 12,
},
{
.brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
- .bus = 13,
+ .nr = 13,
},
{
.brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
- .bus = 14,
+ .nr = 14,
},
};

diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
index 8dcbb8e..5c98ad1 100644
--- a/include/linux/platform_data/mlxreg.h
+++ b/include/linux/platform_data/mlxreg.h
@@ -39,7 +39,8 @@
* @adapter: I2C device adapter;
* @client: I2C device client;
* @brdinfo: device board information;
- * @bus: I2C bus, where device is attached;
+ * @nr: I2C device adapter number, to which device is to be attached;
+ * @np - pointer to node platform associated with attribute;
*
* Structure represents I2C hotplug device static data (board topology) and
* dynamic data (related kernel objects handles).
@@ -48,7 +49,8 @@ struct mlxreg_hotplug_device {
struct i2c_adapter *adapter;
struct i2c_client *client;
struct i2c_board_info brdinfo;
- u16 bus;
+ int nr;
+ struct device_node *np;
};

/**
--
2.1.4


2018-01-17 16:27:44

by Vadim Pasternak

[permalink] [raw]
Subject: [patch v9 1/4] platform/x86: Move Mellanox hardware platform hotplug driver to platform/mellanox

It moves drivers/platform/x86/mlxcpld-hotplug.c to
drivers/platform/mellanox/mlxreg-hotplug.c and
include/linux/platform_data/mlxcpld-hotplug.h to
include/linux/platform_data/mlxreg.h for making hotplug driver usable for
the different machine architectures.

Signed-off-by: Vadim Pasternak <[email protected]>
Acked-by: Andy Shevchenko <[email protected]>
---
v9->v8:
Comments pointed out by Darren:
- make removing of X86_64 dependency of mlx-platform to a separate patch
since it is not related to the moving hotplug driver to
platform/mellanox;
v7->v8:
v6->v7:
Fixes added by Vadim:
- remove dependency on X86_64 to allow also X86 architecture;
v5->v6:
Fixes added by Vadim:
- add SPD license record to Kconfig and Makefile;
v4->v5:
Comments pointed out by Andy:
- arrange MAINTAINERS in correct alphabetic order;
v3->v4:
Comments pointed out by Darren:
- Refactor the patches to provide the changes in patchset in incremental
order;
- Modify MAINTAINERS records;
- Use git-mv for the replaced files;
Commnets pointed out by Colin:
- Make structures mlxplat_dev and mlxplat_hotplug static;
---
MAINTAINERS | 7 +-
drivers/platform/Kconfig | 2 +
drivers/platform/Makefile | 1 +
drivers/platform/mellanox/Kconfig | 25 +++
drivers/platform/mellanox/Makefile | 6 +
.../mlxreg-hotplug.c} | 223 ++++++++++-----------
drivers/platform/x86/Kconfig | 8 -
drivers/platform/x86/Makefile | 1 -
drivers/platform/x86/mlx-platform.c | 18 +-
.../platform_data/{mlxcpld-hotplug.h => mlxreg.h} | 25 ++-
10 files changed, 170 insertions(+), 146 deletions(-)
create mode 100644 drivers/platform/mellanox/Kconfig
create mode 100644 drivers/platform/mellanox/Makefile
rename drivers/platform/{x86/mlxcpld-hotplug.c => mellanox/mlxreg-hotplug.c} (65%)
rename include/linux/platform_data/{mlxcpld-hotplug.h => mlxreg.h} (84%)

diff --git a/MAINTAINERS b/MAINTAINERS
index bc4d776..c07e114 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8860,12 +8860,13 @@ W: http://www.mellanox.com
Q: http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/mellanox/mlxfw/

-MELLANOX MLX CPLD HOTPLUG DRIVER
+MELLANOX HARDWARE PLATFORM SUPPORT
+M: Andy Shevchenko <[email protected]>
+M: Darren Hart <[email protected]>
M: Vadim Pasternak <[email protected]>
L: [email protected]
S: Supported
-F: drivers/platform/x86/mlxcpld-hotplug.c
-F: include/linux/platform_data/mlxcpld-hotplug.h
+F: drivers/platform/mellanox/

MELLANOX MLX4 core VPI driver
M: Tariq Toukan <[email protected]>
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index c11db8b..d4c2e42 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -8,3 +8,5 @@ endif
source "drivers/platform/goldfish/Kconfig"

source "drivers/platform/chrome/Kconfig"
+
+source "drivers/platform/mellanox/Kconfig"
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index d3a6630..4b2ce58 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -4,6 +4,7 @@
#

obj-$(CONFIG_X86) += x86/
+obj-$(CONFIG_MELLANOX_PLATFORM) += mellanox/
obj-$(CONFIG_MIPS) += mips/
obj-$(CONFIG_OLPC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
new file mode 100644
index 0000000..d735292
--- /dev/null
+++ b/drivers/platform/mellanox/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Platform support for Mellanox hardware
+#
+
+menuconfig MELLANOX_PLATFORM
+ bool "Platform support for Mellanox hardware"
+ depends on X86 || COMPILE_TEST
+ ---help---
+ Say Y here to get to see options for platform support for
+ Mellanox systems. This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and disabled.
+
+if MELLANOX_PLATFORM
+
+config MLXREG_HOTPLUG
+ tristate "Mellanox platform hotplug driver support"
+ depends on HWMON
+ depends on I2C
+ ---help---
+ This driver handles hot-plug events for the power suppliers, power
+ cables and fans on the wide range Mellanox IB and Ethernet systems.
+
+endif # MELLANOX_PLATFORM
diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile
new file mode 100644
index 0000000..7c8385e
--- /dev/null
+++ b/drivers/platform/mellanox/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for linux/drivers/platform/mellanox
+# Mellanox Platform-Specific Drivers
+#
+obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o
diff --git a/drivers/platform/x86/mlxcpld-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
similarity index 65%
rename from drivers/platform/x86/mlxcpld-hotplug.c
rename to drivers/platform/mellanox/mlxreg-hotplug.c
index aff3686..2866c76 100644
--- a/drivers/platform/x86/mlxcpld-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -1,7 +1,6 @@
/*
- * drivers/platform/x86/mlxcpld-hotplug.c
- * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2016 Vadim Pasternak <[email protected]>
+ * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2017 Vadim Pasternak <[email protected]>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -40,39 +39,39 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/platform_data/mlxcpld-hotplug.h>
+#include <linux/platform_data/mlxreg.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/workqueue.h>

/* Offset of event and mask registers from status register */
-#define MLXCPLD_HOTPLUG_EVENT_OFF 1
-#define MLXCPLD_HOTPLUG_MASK_OFF 2
-#define MLXCPLD_HOTPLUG_AGGR_MASK_OFF 1
+#define MLXREG_HOTPLUG_EVENT_OFF 1
+#define MLXREG_HOTPLUG_MASK_OFF 2
+#define MLXREG_HOTPLUG_AGGR_MASK_OFF 1

-#define MLXCPLD_HOTPLUG_ATTRS_NUM 8
+#define MLXREG_HOTPLUG_ATTRS_NUM 8

/**
- * enum mlxcpld_hotplug_attr_type - sysfs attributes for hotplug events:
- * @MLXCPLD_HOTPLUG_ATTR_TYPE_PSU: power supply unit attribute;
- * @MLXCPLD_HOTPLUG_ATTR_TYPE_PWR: power cable attribute;
- * @MLXCPLD_HOTPLUG_ATTR_TYPE_FAN: FAN drawer attribute;
+ * enum mlxreg_hotplug_attr_type - sysfs attributes for hotplug events:
+ * @MLXREG_HOTPLUG_ATTR_TYPE_PSU: power supply unit attribute;
+ * @MLXREG_HOTPLUG_ATTR_TYPE_PWR: power cable attribute;
+ * @MLXREG_HOTPLUG_ATTR_TYPE_FAN: FAN drawer attribute;
*/
-enum mlxcpld_hotplug_attr_type {
- MLXCPLD_HOTPLUG_ATTR_TYPE_PSU,
- MLXCPLD_HOTPLUG_ATTR_TYPE_PWR,
- MLXCPLD_HOTPLUG_ATTR_TYPE_FAN,
+enum mlxreg_hotplug_attr_type {
+ MLXREG_HOTPLUG_ATTR_TYPE_PSU,
+ MLXREG_HOTPLUG_ATTR_TYPE_PWR,
+ MLXREG_HOTPLUG_ATTR_TYPE_FAN,
};

/**
- * struct mlxcpld_hotplug_priv_data - platform private data:
+ * struct mlxreg_hotplug_priv_data - platform private data:
* @irq: platform interrupt number;
* @pdev: platform device;
* @plat: platform data;
* @hwmon: hwmon device;
- * @mlxcpld_hotplug_attr: sysfs attributes array;
- * @mlxcpld_hotplug_dev_attr: sysfs sensor device attribute array;
+ * @mlxreg_hotplug_attr: sysfs attributes array;
+ * @mlxreg_hotplug_dev_attr: sysfs sensor device attribute array;
* @group: sysfs attribute group;
* @groups: list of sysfs attribute group for hwmon registration;
* @dwork: delayed work template;
@@ -82,14 +81,14 @@ enum mlxcpld_hotplug_attr_type {
* @pwr_cache: last value of power register status;
* @fan_cache: last value of FAN register status;
*/
-struct mlxcpld_hotplug_priv_data {
+struct mlxreg_hotplug_priv_data {
int irq;
struct platform_device *pdev;
- struct mlxcpld_hotplug_platform_data *plat;
+ struct mlxreg_hotplug_platform_data *plat;
struct device *hwmon;
- struct attribute *mlxcpld_hotplug_attr[MLXCPLD_HOTPLUG_ATTRS_NUM + 1];
+ struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_NUM + 1];
struct sensor_device_attribute_2
- mlxcpld_hotplug_dev_attr[MLXCPLD_HOTPLUG_ATTRS_NUM];
+ mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_NUM];
struct attribute_group group;
const struct attribute_group *groups[2];
struct delayed_work dwork;
@@ -100,29 +99,29 @@ struct mlxcpld_hotplug_priv_data {
u8 fan_cache;
};

-static ssize_t mlxcpld_hotplug_attr_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t mlxreg_hotplug_attr_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
- struct mlxcpld_hotplug_priv_data *priv = platform_get_drvdata(pdev);
+ struct mlxreg_hotplug_priv_data *priv = platform_get_drvdata(pdev);
int index = to_sensor_dev_attr_2(attr)->index;
int nr = to_sensor_dev_attr_2(attr)->nr;
u8 reg_val = 0;

switch (nr) {
- case MLXCPLD_HOTPLUG_ATTR_TYPE_PSU:
+ case MLXREG_HOTPLUG_ATTR_TYPE_PSU:
/* Bit = 0 : PSU is present. */
reg_val = !!!(inb(priv->plat->psu_reg_offset) & BIT(index));
break;

- case MLXCPLD_HOTPLUG_ATTR_TYPE_PWR:
+ case MLXREG_HOTPLUG_ATTR_TYPE_PWR:
/* Bit = 1 : power cable is attached. */
reg_val = !!(inb(priv->plat->pwr_reg_offset) & BIT(index %
priv->plat->pwr_count));
break;

- case MLXCPLD_HOTPLUG_ATTR_TYPE_FAN:
+ case MLXREG_HOTPLUG_ATTR_TYPE_FAN:
/* Bit = 0 : FAN is present. */
reg_val = !!!(inb(priv->plat->fan_reg_offset) & BIT(index %
priv->plat->fan_count));
@@ -132,9 +131,9 @@ static ssize_t mlxcpld_hotplug_attr_show(struct device *dev,
return sprintf(buf, "%u\n", reg_val);
}

-#define PRIV_ATTR(i) priv->mlxcpld_hotplug_attr[i]
-#define PRIV_DEV_ATTR(i) priv->mlxcpld_hotplug_dev_attr[i]
-static int mlxcpld_hotplug_attr_init(struct mlxcpld_hotplug_priv_data *priv)
+#define PRIV_ATTR(i) priv->mlxreg_hotplug_attr[i]
+#define PRIV_DEV_ATTR(i) priv->mlxreg_hotplug_dev_attr[i]
+static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
{
int num_attrs = priv->plat->psu_count + priv->plat->pwr_count +
priv->plat->fan_count;
@@ -152,17 +151,17 @@ static int mlxcpld_hotplug_attr_init(struct mlxcpld_hotplug_priv_data *priv)
if (i < priv->plat->psu_count) {
PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
GFP_KERNEL, "psu%u", i + 1);
- PRIV_DEV_ATTR(i).nr = MLXCPLD_HOTPLUG_ATTR_TYPE_PSU;
+ PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_PSU;
} else if (i < priv->plat->psu_count + priv->plat->pwr_count) {
PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
GFP_KERNEL, "pwr%u", i %
priv->plat->pwr_count + 1);
- PRIV_DEV_ATTR(i).nr = MLXCPLD_HOTPLUG_ATTR_TYPE_PWR;
+ PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_PWR;
} else {
PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
GFP_KERNEL, "fan%u", i %
priv->plat->fan_count + 1);
- PRIV_DEV_ATTR(i).nr = MLXCPLD_HOTPLUG_ATTR_TYPE_FAN;
+ PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_FAN;
}

if (!PRIV_ATTR(i)->name) {
@@ -173,20 +172,20 @@ static int mlxcpld_hotplug_attr_init(struct mlxcpld_hotplug_priv_data *priv)

PRIV_DEV_ATTR(i).dev_attr.attr.name = PRIV_ATTR(i)->name;
PRIV_DEV_ATTR(i).dev_attr.attr.mode = S_IRUGO;
- PRIV_DEV_ATTR(i).dev_attr.show = mlxcpld_hotplug_attr_show;
+ PRIV_DEV_ATTR(i).dev_attr.show = mlxreg_hotplug_attr_show;
PRIV_DEV_ATTR(i).index = i;
sysfs_attr_init(&PRIV_DEV_ATTR(i).dev_attr.attr);
}

- priv->group.attrs = priv->mlxcpld_hotplug_attr;
+ priv->group.attrs = priv->mlxreg_hotplug_attr;
priv->groups[0] = &priv->group;
priv->groups[1] = NULL;

return 0;
}

-static int mlxcpld_hotplug_device_create(struct device *dev,
- struct mlxcpld_hotplug_device *item)
+static int mlxreg_hotplug_device_create(struct device *dev,
+ struct mlxreg_hotplug_device *item)
{
item->adapter = i2c_get_adapter(item->bus);
if (!item->adapter) {
@@ -207,7 +206,7 @@ static int mlxcpld_hotplug_device_create(struct device *dev,
return 0;
}

-static void mlxcpld_hotplug_device_destroy(struct mlxcpld_hotplug_device *item)
+static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *item)
{
if (item->client) {
i2c_unregister_device(item->client);
@@ -221,15 +220,15 @@ static void mlxcpld_hotplug_device_destroy(struct mlxcpld_hotplug_device *item)
}

static inline void
-mlxcpld_hotplug_work_helper(struct device *dev,
- struct mlxcpld_hotplug_device *item, u8 is_inverse,
- u16 offset, u8 mask, u8 *cache)
+mlxreg_hotplug_work_helper(struct device *dev,
+ struct mlxreg_hotplug_device *item, u8 is_inverse,
+ u16 offset, u8 mask, u8 *cache)
{
u8 val, asserted;
int bit;

/* Mask event. */
- outb(0, offset + MLXCPLD_HOTPLUG_MASK_OFF);
+ outb(0, offset + MLXREG_HOTPLUG_MASK_OFF);
/* Read status. */
val = inb(offset) & mask;
asserted = *cache ^ val;
@@ -251,25 +250,25 @@ mlxcpld_hotplug_work_helper(struct device *dev,
for_each_set_bit(bit, (unsigned long *)&asserted, 8) {
if (val & BIT(bit)) {
if (is_inverse)
- mlxcpld_hotplug_device_destroy(item + bit);
+ mlxreg_hotplug_device_destroy(item + bit);
else
- mlxcpld_hotplug_device_create(dev, item + bit);
+ mlxreg_hotplug_device_create(dev, item + bit);
} else {
if (is_inverse)
- mlxcpld_hotplug_device_create(dev, item + bit);
+ mlxreg_hotplug_device_create(dev, item + bit);
else
- mlxcpld_hotplug_device_destroy(item + bit);
+ mlxreg_hotplug_device_destroy(item + bit);
}
}

/* Acknowledge event. */
- outb(0, offset + MLXCPLD_HOTPLUG_EVENT_OFF);
+ outb(0, offset + MLXREG_HOTPLUG_EVENT_OFF);
/* Unmask event. */
- outb(mask, offset + MLXCPLD_HOTPLUG_MASK_OFF);
+ outb(mask, offset + MLXREG_HOTPLUG_MASK_OFF);
}

/*
- * mlxcpld_hotplug_work_handler - performs traversing of CPLD interrupt
+ * mlxreg_hotplug_work_handler - performs traversing of CPLD interrupt
* registers according to the below hierarchy schema:
*
* Aggregation registers (status/mask)
@@ -289,15 +288,15 @@ mlxcpld_hotplug_work_helper(struct device *dev,
* In case some system changed are detected: FAN in/out, PSU in/out, power
* cable attached/detached, relevant device is created or destroyed.
*/
-static void mlxcpld_hotplug_work_handler(struct work_struct *work)
+static void mlxreg_hotplug_work_handler(struct work_struct *work)
{
- struct mlxcpld_hotplug_priv_data *priv = container_of(work,
- struct mlxcpld_hotplug_priv_data, dwork.work);
+ struct mlxreg_hotplug_priv_data *priv = container_of(work,
+ struct mlxreg_hotplug_priv_data, dwork.work);
u8 val, aggr_asserted;
unsigned long flags;

/* Mask aggregation event. */
- outb(0, priv->plat->top_aggr_offset + MLXCPLD_HOTPLUG_AGGR_MASK_OFF);
+ outb(0, priv->plat->top_aggr_offset + MLXREG_HOTPLUG_AGGR_MASK_OFF);
/* Read aggregation status. */
val = inb(priv->plat->top_aggr_offset) & priv->plat->top_aggr_mask;
aggr_asserted = priv->aggr_cache ^ val;
@@ -305,31 +304,31 @@ static void mlxcpld_hotplug_work_handler(struct work_struct *work)

/* Handle PSU configuration changes. */
if (aggr_asserted & priv->plat->top_aggr_psu_mask)
- mlxcpld_hotplug_work_helper(&priv->pdev->dev, priv->plat->psu,
- 1, priv->plat->psu_reg_offset,
- priv->plat->psu_mask,
- &priv->psu_cache);
+ mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->psu,
+ 1, priv->plat->psu_reg_offset,
+ priv->plat->psu_mask,
+ &priv->psu_cache);

/* Handle power cable configuration changes. */
if (aggr_asserted & priv->plat->top_aggr_pwr_mask)
- mlxcpld_hotplug_work_helper(&priv->pdev->dev, priv->plat->pwr,
- 0, priv->plat->pwr_reg_offset,
- priv->plat->pwr_mask,
- &priv->pwr_cache);
+ mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->pwr,
+ 0, priv->plat->pwr_reg_offset,
+ priv->plat->pwr_mask,
+ &priv->pwr_cache);

/* Handle FAN configuration changes. */
if (aggr_asserted & priv->plat->top_aggr_fan_mask)
- mlxcpld_hotplug_work_helper(&priv->pdev->dev, priv->plat->fan,
- 1, priv->plat->fan_reg_offset,
- priv->plat->fan_mask,
- &priv->fan_cache);
+ mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->fan,
+ 1, priv->plat->fan_reg_offset,
+ priv->plat->fan_mask,
+ &priv->fan_cache);

if (aggr_asserted) {
spin_lock_irqsave(&priv->lock, flags);

/*
* It is possible, that some signals have been inserted, while
- * interrupt has been masked by mlxcpld_hotplug_work_handler.
+ * interrupt has been masked by mlxreg_hotplug_work_handler.
* In this case such signals will be missed. In order to handle
* these signals delayed work is canceled and work task
* re-scheduled for immediate execution. It allows to handle
@@ -347,42 +346,42 @@ static void mlxcpld_hotplug_work_handler(struct work_struct *work)

/* Unmask aggregation event (no need acknowledge). */
outb(priv->plat->top_aggr_mask, priv->plat->top_aggr_offset +
- MLXCPLD_HOTPLUG_AGGR_MASK_OFF);
+ MLXREG_HOTPLUG_AGGR_MASK_OFF);
}

-static void mlxcpld_hotplug_set_irq(struct mlxcpld_hotplug_priv_data *priv)
+static void mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
{
/* Clear psu presense event. */
- outb(0, priv->plat->psu_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF);
+ outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
/* Set psu initial status as mask and unmask psu event. */
priv->psu_cache = priv->plat->psu_mask;
outb(priv->plat->psu_mask, priv->plat->psu_reg_offset +
- MLXCPLD_HOTPLUG_MASK_OFF);
+ MLXREG_HOTPLUG_MASK_OFF);

/* Clear power cable event. */
- outb(0, priv->plat->pwr_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF);
+ outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
/* Keep power initial status as zero and unmask power event. */
outb(priv->plat->pwr_mask, priv->plat->pwr_reg_offset +
- MLXCPLD_HOTPLUG_MASK_OFF);
+ MLXREG_HOTPLUG_MASK_OFF);

/* Clear fan presense event. */
- outb(0, priv->plat->fan_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF);
+ outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
/* Set fan initial status as mask and unmask fan event. */
priv->fan_cache = priv->plat->fan_mask;
outb(priv->plat->fan_mask, priv->plat->fan_reg_offset +
- MLXCPLD_HOTPLUG_MASK_OFF);
+ MLXREG_HOTPLUG_MASK_OFF);

/* Keep aggregation initial status as zero and unmask events. */
outb(priv->plat->top_aggr_mask, priv->plat->top_aggr_offset +
- MLXCPLD_HOTPLUG_AGGR_MASK_OFF);
+ MLXREG_HOTPLUG_AGGR_MASK_OFF);

/* Invoke work handler for initializing hot plug devices setting. */
- mlxcpld_hotplug_work_handler(&priv->dwork.work);
+ mlxreg_hotplug_work_handler(&priv->dwork.work);

enable_irq(priv->irq);
}

-static void mlxcpld_hotplug_unset_irq(struct mlxcpld_hotplug_priv_data *priv)
+static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
{
int i;

@@ -390,38 +389,38 @@ static void mlxcpld_hotplug_unset_irq(struct mlxcpld_hotplug_priv_data *priv)
cancel_delayed_work_sync(&priv->dwork);

/* Mask aggregation event. */
- outb(0, priv->plat->top_aggr_offset + MLXCPLD_HOTPLUG_AGGR_MASK_OFF);
+ outb(0, priv->plat->top_aggr_offset + MLXREG_HOTPLUG_AGGR_MASK_OFF);

/* Mask psu presense event. */
- outb(0, priv->plat->psu_reg_offset + MLXCPLD_HOTPLUG_MASK_OFF);
+ outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
/* Clear psu presense event. */
- outb(0, priv->plat->psu_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF);
+ outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);

/* Mask power cable event. */
- outb(0, priv->plat->pwr_reg_offset + MLXCPLD_HOTPLUG_MASK_OFF);
+ outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
/* Clear power cable event. */
- outb(0, priv->plat->pwr_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF);
+ outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);

/* Mask fan presense event. */
- outb(0, priv->plat->fan_reg_offset + MLXCPLD_HOTPLUG_MASK_OFF);
+ outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
/* Clear fan presense event. */
- outb(0, priv->plat->fan_reg_offset + MLXCPLD_HOTPLUG_EVENT_OFF);
+ outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);

/* Remove all the attached devices. */
for (i = 0; i < priv->plat->psu_count; i++)
- mlxcpld_hotplug_device_destroy(priv->plat->psu + i);
+ mlxreg_hotplug_device_destroy(priv->plat->psu + i);

for (i = 0; i < priv->plat->pwr_count; i++)
- mlxcpld_hotplug_device_destroy(priv->plat->pwr + i);
+ mlxreg_hotplug_device_destroy(priv->plat->pwr + i);

for (i = 0; i < priv->plat->fan_count; i++)
- mlxcpld_hotplug_device_destroy(priv->plat->fan + i);
+ mlxreg_hotplug_device_destroy(priv->plat->fan + i);
}

-static irqreturn_t mlxcpld_hotplug_irq_handler(int irq, void *dev)
+static irqreturn_t mlxreg_hotplug_irq_handler(int irq, void *dev)
{
- struct mlxcpld_hotplug_priv_data *priv =
- (struct mlxcpld_hotplug_priv_data *)dev;
+ struct mlxreg_hotplug_priv_data *priv =
+ (struct mlxreg_hotplug_priv_data *)dev;

/* Schedule work task for immediate execution.*/
schedule_delayed_work(&priv->dwork, 0);
@@ -429,10 +428,10 @@ static irqreturn_t mlxcpld_hotplug_irq_handler(int irq, void *dev)
return IRQ_HANDLED;
}

-static int mlxcpld_hotplug_probe(struct platform_device *pdev)
+static int mlxreg_hotplug_probe(struct platform_device *pdev)
{
- struct mlxcpld_hotplug_platform_data *pdata;
- struct mlxcpld_hotplug_priv_data *priv;
+ struct mlxreg_hotplug_platform_data *pdata;
+ struct mlxreg_hotplug_priv_data *priv;
int err;

pdata = dev_get_platdata(&pdev->dev);
@@ -456,25 +455,25 @@ static int mlxcpld_hotplug_probe(struct platform_device *pdev)
}

err = devm_request_irq(&pdev->dev, priv->irq,
- mlxcpld_hotplug_irq_handler, 0, pdev->name,
- priv);
+ mlxreg_hotplug_irq_handler, 0, pdev->name,
+ priv);
if (err) {
dev_err(&pdev->dev, "Failed to request irq: %d\n", err);
return err;
}
disable_irq(priv->irq);

- INIT_DELAYED_WORK(&priv->dwork, mlxcpld_hotplug_work_handler);
+ INIT_DELAYED_WORK(&priv->dwork, mlxreg_hotplug_work_handler);
spin_lock_init(&priv->lock);

- err = mlxcpld_hotplug_attr_init(priv);
+ err = mlxreg_hotplug_attr_init(priv);
if (err) {
dev_err(&pdev->dev, "Failed to allocate attributes: %d\n", err);
return err;
}

priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
- "mlxcpld_hotplug", priv, priv->groups);
+ "mlxreg_hotplug", priv, priv->groups);
if (IS_ERR(priv->hwmon)) {
dev_err(&pdev->dev, "Failed to register hwmon device %ld\n",
PTR_ERR(priv->hwmon));
@@ -484,32 +483,32 @@ static int mlxcpld_hotplug_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);

/* Perform initial interrupts setup. */
- mlxcpld_hotplug_set_irq(priv);
+ mlxreg_hotplug_set_irq(priv);

return 0;
}

-static int mlxcpld_hotplug_remove(struct platform_device *pdev)
+static int mlxreg_hotplug_remove(struct platform_device *pdev)
{
- struct mlxcpld_hotplug_priv_data *priv = platform_get_drvdata(pdev);
+ struct mlxreg_hotplug_priv_data *priv = platform_get_drvdata(pdev);

/* Clean interrupts setup. */
- mlxcpld_hotplug_unset_irq(priv);
+ mlxreg_hotplug_unset_irq(priv);

return 0;
}

-static struct platform_driver mlxcpld_hotplug_driver = {
+static struct platform_driver mlxreg_hotplug_driver = {
.driver = {
- .name = "mlxcpld-hotplug",
+ .name = "mlxreg-hotplug",
},
- .probe = mlxcpld_hotplug_probe,
- .remove = mlxcpld_hotplug_remove,
+ .probe = mlxreg_hotplug_probe,
+ .remove = mlxreg_hotplug_remove,
};

-module_platform_driver(mlxcpld_hotplug_driver);
+module_platform_driver(mlxreg_hotplug_driver);

MODULE_AUTHOR("Vadim Pasternak <[email protected]>");
-MODULE_DESCRIPTION("Mellanox CPLD hotplug platform driver");
+MODULE_DESCRIPTION("Mellanox regmap hotplug platform driver");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("platform:mlxcpld-hotplug");
+MODULE_ALIAS("platform:mlxreg-hotplug");
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b9b40e3..c442d5c 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1166,14 +1166,6 @@ config MLX_PLATFORM

If you have a Mellanox system, say Y or M here.

-config MLX_CPLD_PLATFORM
- tristate "Mellanox platform hotplug driver support"
- select HWMON
- select I2C
- ---help---
- This driver handles hot-plug events for the power suppliers, power
- cables and fans on the wide range Mellanox IB and Ethernet systems.
-
config INTEL_TURBO_MAX_3
bool "Intel Turbo Boost Max Technology 3.0 enumeration driver"
depends on X86_64 && SCHED_MC_PRIO
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 57f37e5..c388608 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -88,6 +88,5 @@ obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o
obj-$(CONFIG_PMC_ATOM) += pmc_atom.o
obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o
-obj-$(CONFIG_MLX_CPLD_PLATFORM) += mlxcpld-hotplug.o
obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 504256c..0fbec1f 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -38,7 +38,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_data/i2c-mux-reg.h>
-#include <linux/platform_data/mlxcpld-hotplug.h>
+#include <linux/platform_data/mlxreg.h>

#define MLX_PLAT_DEVICE_NAME "mlxplat"

@@ -138,7 +138,7 @@ static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
};

/* Platform hotplug devices */
-static struct mlxcpld_hotplug_device mlxplat_mlxcpld_psu[] = {
+static struct mlxreg_hotplug_device mlxplat_mlxcpld_psu[] = {
{
.brdinfo = { I2C_BOARD_INFO("24c02", 0x51) },
.bus = 10,
@@ -149,7 +149,7 @@ static struct mlxcpld_hotplug_device mlxplat_mlxcpld_psu[] = {
},
};

-static struct mlxcpld_hotplug_device mlxplat_mlxcpld_pwr[] = {
+static struct mlxreg_hotplug_device mlxplat_mlxcpld_pwr[] = {
{
.brdinfo = { I2C_BOARD_INFO("dps460", 0x59) },
.bus = 10,
@@ -160,7 +160,7 @@ static struct mlxcpld_hotplug_device mlxplat_mlxcpld_pwr[] = {
},
};

-static struct mlxcpld_hotplug_device mlxplat_mlxcpld_fan[] = {
+static struct mlxreg_hotplug_device mlxplat_mlxcpld_fan[] = {
{
.brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
.bus = 11,
@@ -181,7 +181,7 @@ static struct mlxcpld_hotplug_device mlxplat_mlxcpld_fan[] = {

/* Platform hotplug default data */
static
-struct mlxcpld_hotplug_platform_data mlxplat_mlxcpld_default_data = {
+struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_default_data = {
.top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR,
.top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
.top_aggr_psu_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
@@ -203,7 +203,7 @@ struct mlxcpld_hotplug_platform_data mlxplat_mlxcpld_default_data = {

/* Platform hotplug MSN21xx system family data */
static
-struct mlxcpld_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
+struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
.top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR,
.top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX,
.top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX,
@@ -213,11 +213,11 @@ struct mlxcpld_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
};

static struct resource mlxplat_mlxcpld_resources[] = {
- [0] = DEFINE_RES_IRQ_NAMED(17, "mlxcpld-hotplug"),
+ [0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"),
};

static struct platform_device *mlxplat_dev;
-static struct mlxcpld_hotplug_platform_data *mlxplat_hotplug;
+static struct mlxreg_hotplug_platform_data *mlxplat_hotplug;

static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
{
@@ -329,7 +329,7 @@ static int __init mlxplat_init(void)
}

priv->pdev_hotplug = platform_device_register_resndata(
- &mlxplat_dev->dev, "mlxcpld-hotplug",
+ &mlxplat_dev->dev, "mlxreg-hotplug",
PLATFORM_DEVID_NONE,
mlxplat_mlxcpld_resources,
ARRAY_SIZE(mlxplat_mlxcpld_resources),
diff --git a/include/linux/platform_data/mlxcpld-hotplug.h b/include/linux/platform_data/mlxreg.h
similarity index 84%
rename from include/linux/platform_data/mlxcpld-hotplug.h
rename to include/linux/platform_data/mlxreg.h
index e4cfcff..8dcbb8e 100644
--- a/include/linux/platform_data/mlxcpld-hotplug.h
+++ b/include/linux/platform_data/mlxreg.h
@@ -1,7 +1,6 @@
/*
- * include/linux/platform_data/mlxcpld-hotplug.h
- * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2016 Vadim Pasternak <[email protected]>
+ * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2017 Vadim Pasternak <[email protected]>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,11 +31,11 @@
* POSSIBILITY OF SUCH DAMAGE.
*/

-#ifndef __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H
-#define __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H
+#ifndef __LINUX_PLATFORM_DATA_MLXREG_H
+#define __LINUX_PLATFORM_DATA_MLXREG_H

/**
- * struct mlxcpld_hotplug_device - I2C device data:
+ * struct mlxreg_hotplug_device - I2C device data:
* @adapter: I2C device adapter;
* @client: I2C device client;
* @brdinfo: device board information;
@@ -45,7 +44,7 @@
* Structure represents I2C hotplug device static data (board topology) and
* dynamic data (related kernel objects handles).
*/
-struct mlxcpld_hotplug_device {
+struct mlxreg_hotplug_device {
struct i2c_adapter *adapter;
struct i2c_client *client;
struct i2c_board_info brdinfo;
@@ -53,7 +52,7 @@ struct mlxcpld_hotplug_device {
};

/**
- * struct mlxcpld_hotplug_platform_data - device platform data:
+ * struct mlxreg_hotplug_platform_data - device platform data:
* @top_aggr_offset: offset of top aggregation interrupt register;
* @top_aggr_mask: top aggregation interrupt common mask;
* @top_aggr_psu_mask: top aggregation interrupt PSU mask;
@@ -76,24 +75,24 @@ struct mlxcpld_hotplug_device {
* like FAN, PSU, power cable insertion and removing. This data provides the
* number of hot-pluggable devices and hardware description for event handling.
*/
-struct mlxcpld_hotplug_platform_data {
+struct mlxreg_hotplug_platform_data {
u16 top_aggr_offset;
u8 top_aggr_mask;
u8 top_aggr_psu_mask;
u16 psu_reg_offset;
u8 psu_mask;
u8 psu_count;
- struct mlxcpld_hotplug_device *psu;
+ struct mlxreg_hotplug_device *psu;
u8 top_aggr_pwr_mask;
u16 pwr_reg_offset;
u8 pwr_mask;
u8 pwr_count;
- struct mlxcpld_hotplug_device *pwr;
+ struct mlxreg_hotplug_device *pwr;
u8 top_aggr_fan_mask;
u16 fan_reg_offset;
u8 fan_mask;
u8 fan_count;
- struct mlxcpld_hotplug_device *fan;
+ struct mlxreg_hotplug_device *fan;
};

-#endif /* __LINUX_PLATFORM_DATA_MLXCPLD_HOTPLUG_H */
+#endif /* __LINUX_PLATFORM_DATA_MLXREG_H */
--
2.1.4


2018-01-23 03:50:30

by Darren Hart

[permalink] [raw]
Subject: Re: [patch v9 4/4] platform/mellanox: mlxreg-hotplug: Modify to use a regmap interface

On Wed, Jan 17, 2018 at 06:21:56PM +0000, Vadim Pasternak wrote:
> Restructure mlxreg header for unification of hotplug item definitions.
>
> Unify hotplug items to allow any kind of item (power controller, fan
> eeprom, psu eeprom, asic health) in common way.
>
> Use a hardware independent regmap interface, enabling the support of
> hotplug events over programmable devices attached to different bus
> types, such as I2C, LPC, or SPI
>
> [dvhart: Simplify exit path]
> Simplify exit path: Several functions use a "goto access_error" pattern
> result in a duplicated exit path at the end of the function. Address this
> by using a single exit path, and checking for (ret) prior to printing the
> error message. This adds a conditional, but only in the failure case, and
> simplifies the exit path.
>
> [dvhart: Cleanup local variable declarations]
> Cleanup local variable declarations: Make the local variable declarations
> more consistent throughout the driver. Separate inline initial assignments
> when it cleans up the declaration block.
>
> Signed-off-by: Vadim Pasternak <[email protected]>
> Acked-by: Andy Shevchenko <[email protected]>
> ---
> v8->v9:
> Fixes provideded by Vadim:
> - Simplify exit path in mlxreg-hotplug
> - Cleanup local variable declarations
> driver. Separate inline initial assignments when it cleans up the
> declaration block.
> v7->v8
> v6->v7
> Fixes added by Vadim:
> - Remove include <linux/io.h> in mlxreg-hotplug.c in this patch.
> v5->v6:
> Fixes added by Vadim:
> - rename mlxreg_core_led_platform_data to common name
> mlxreg_core_platform_data;
> - add cell_low and mask_low fields to
> mlxreg_core_hotplug_platform_data for low aggregation interrupt
> registers and check for these fields in mlxreg_hotplug_set_irq and
> mlxreg_hotplug_unset_irq;
> v4->v5:
> Comments pointed out by Andy:
> - use suffix OFFSET instead of ADDR for aggregation registers;
> - return back MACROS;
> - rearrange mlxreg_hotplug_attr_init routine;
> ---
> drivers/platform/mellanox/Kconfig | 1 +
> drivers/platform/mellanox/mlxreg-hotplug.c | 608 +++++++++++++++++------------
> drivers/platform/x86/mlx-platform.c | 231 ++++++++---
> include/linux/platform_data/mlxreg.h | 126 ++++--
> 4 files changed, 630 insertions(+), 336 deletions(-)
>
> diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
> index 0267e1d..591bccd 100644
> --- a/drivers/platform/mellanox/Kconfig
> +++ b/drivers/platform/mellanox/Kconfig
> @@ -16,6 +16,7 @@ if MELLANOX_PLATFORM
>
> config MLXREG_HOTPLUG
> tristate "Mellanox platform hotplug driver support"
> + depends on REGMAP
> depends on HWMON
> depends on I2C
> ---help---
> diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
> index 556e612..18f3f3f 100644
> --- a/drivers/platform/mellanox/mlxreg-hotplug.c
> +++ b/drivers/platform/mellanox/mlxreg-hotplug.c
> @@ -37,92 +37,88 @@
> #include <linux/hwmon-sysfs.h>
> #include <linux/i2c.h>
> #include <linux/interrupt.h>
> -#include <linux/io.h>
> #include <linux/module.h>
> +#include <linux/of_device.h>
> #include <linux/platform_data/mlxreg.h>
> #include <linux/platform_device.h>
> +#include <linux/regmap.h>
> #include <linux/workqueue.h>
>
> -/* Offset of event and mask registers from status register */
> +/* Offset of event and mask registers from status register. */
> #define MLXREG_HOTPLUG_EVENT_OFF 1
> -#define MLXREG_HOTPLUG_MASK_OFF 2
> +#define MLXREG_HOTPLUG_MASK_OFF 2
> #define MLXREG_HOTPLUG_AGGR_MASK_OFF 1
>
> -#define MLXREG_HOTPLUG_ATTRS_NUM 8
> +/* ASIC health parameters. */
> +#define MLXREG_HOTPLUG_HEALTH_MASK 0x02
> +#define MLXREG_HOTPLUG_RST_CNTR 3
>
> -/**
> - * enum mlxreg_hotplug_attr_type - sysfs attributes for hotplug events:
> - * @MLXREG_HOTPLUG_ATTR_TYPE_PSU: power supply unit attribute;
> - * @MLXREG_HOTPLUG_ATTR_TYPE_PWR: power cable attribute;
> - * @MLXREG_HOTPLUG_ATTR_TYPE_FAN: FAN drawer attribute;
> - */
> -enum mlxreg_hotplug_attr_type {
> - MLXREG_HOTPLUG_ATTR_TYPE_PSU,
> - MLXREG_HOTPLUG_ATTR_TYPE_PWR,
> - MLXREG_HOTPLUG_ATTR_TYPE_FAN,
> -};
> +#define MLXREG_HOTPLUG_ATTRS_MAX 24
>
> /**
> * struct mlxreg_hotplug_priv_data - platform private data:
> - * @irq: platform interrupt number;
> + * @irq: platform device interrupt number;
> * @pdev: platform device;
> * @plat: platform data;
> + * @dwork: delayed work template;
> + * @lock: spin lock;
> * @hwmon: hwmon device;
> * @mlxreg_hotplug_attr: sysfs attributes array;
> * @mlxreg_hotplug_dev_attr: sysfs sensor device attribute array;
> * @group: sysfs attribute group;
> * @groups: list of sysfs attribute group for hwmon registration;
> - * @dwork: delayed work template;
> - * @lock: spin lock;
> + * @cell: location of top aggregation interrupt register;
> + * @mask: top aggregation interrupt common mask;
> * @aggr_cache: last value of aggregation register status;
> - * @psu_cache: last value of PSU register status;
> - * @pwr_cache: last value of power register status;
> - * @fan_cache: last value of FAN register status;
> */
> struct mlxreg_hotplug_priv_data {
> int irq;
> + struct device *dev;
> struct platform_device *pdev;
> struct mlxreg_hotplug_platform_data *plat;
> + struct regmap *regmap;
> + struct delayed_work dwork_irq;
> + struct delayed_work dwork;
> + spinlock_t lock; /* sync with interrupt */
> struct device *hwmon;
> - struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_NUM + 1];
> + struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1];
> struct sensor_device_attribute_2
> - mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_NUM];
> + mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_MAX];
> struct attribute_group group;
> const struct attribute_group *groups[2];
> - struct delayed_work dwork;
> - spinlock_t lock;
> - u8 aggr_cache;
> - u8 psu_cache;
> - u8 pwr_cache;
> - u8 fan_cache;
> + u32 cell;
> + u32 mask;
> + u32 aggr_cache;
> + bool after_probe;
> };
>
> -static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_device *data)
> +static int mlxreg_hotplug_device_create(struct mlxreg_core_data *data)
> {
> - data->adapter = i2c_get_adapter(data->nr);
> - if (!data->adapter)
> + data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
> + if (!data->hpdev.adapter)
> return -EFAULT;
>
> - data->client = i2c_new_device(data->adapter, &data->brdinfo);
> - if (!data->client) {
> - i2c_put_adapter(data->adapter);
> - data->adapter = NULL;
> + data->hpdev.client = i2c_new_device(data->hpdev.adapter,
> + data->hpdev.brdinfo);
> + if (!data->hpdev.client) {
> + i2c_put_adapter(data->hpdev.adapter);
> + data->hpdev.adapter = NULL;
> return -EFAULT;
> }
>
> return 0;
> }
>
> -static void mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_device *data)
> +static void mlxreg_hotplug_device_destroy(struct mlxreg_core_data *data)
> {
> - if (data->client) {
> - i2c_unregister_device(data->client);
> - data->client = NULL;
> + if (data->hpdev.client) {
> + i2c_unregister_device(data->hpdev.client);
> + data->hpdev.client = NULL;
> }
>
> - if (data->adapter) {
> - i2c_put_adapter(data->adapter);
> - data->adapter = NULL;
> + if (data->hpdev.adapter) {
> + i2c_put_adapter(data->hpdev.adapter);
> + data->hpdev.adapter = NULL;
> }
> }
>
> @@ -130,41 +126,76 @@ static ssize_t mlxreg_hotplug_attr_show(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct platform_device *pdev = to_platform_device(dev);
> - struct mlxreg_hotplug_priv_data *priv = platform_get_drvdata(pdev);
> + struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(dev);
> + struct mlxreg_core_hotplug_platform_data *pdata;
> int index = to_sensor_dev_attr_2(attr)->index;
> int nr = to_sensor_dev_attr_2(attr)->nr;
> - u8 reg_val = 0;
> -
> - switch (nr) {
> - case MLXREG_HOTPLUG_ATTR_TYPE_PSU:
> - /* Bit = 0 : PSU is present. */
> - reg_val = !!!(inb(priv->plat->psu_reg_offset) & BIT(index));
> - break;
> -
> - case MLXREG_HOTPLUG_ATTR_TYPE_PWR:
> - /* Bit = 1 : power cable is attached. */
> - reg_val = !!(inb(priv->plat->pwr_reg_offset) & BIT(index %
> - priv->plat->pwr_count));
> - break;
> -
> - case MLXREG_HOTPLUG_ATTR_TYPE_FAN:
> - /* Bit = 0 : FAN is present. */
> - reg_val = !!!(inb(priv->plat->fan_reg_offset) & BIT(index %
> - priv->plat->fan_count));
> - break;
> + struct mlxreg_core_item *item;
> + struct mlxreg_core_data *data;
> + u32 regval;
> + int ret;
> +
> + pdata = dev_get_platdata(&priv->pdev->dev);
> + item = pdata->items + nr;
> + data = item->data + index;
> +
> + ret = regmap_read(priv->regmap, data->reg, &regval);
> + if (ret)
> + return ret;
> +
> + if (item->health) {
> + regval &= data->mask;
> + } else {
> + /* Bit = 0 : functional if item->inversed is true. */
> + if (item->inversed)
> + regval = !(regval & data->mask);
> + else
> + regval = !!(regval & data->mask);
> }
>
> - return sprintf(buf, "%u\n", reg_val);
> + return sprintf(buf, "%u\n", regval);
> }
>
> #define PRIV_ATTR(i) priv->mlxreg_hotplug_attr[i]
> #define PRIV_DEV_ATTR(i) priv->mlxreg_hotplug_dev_attr[i]
> +
> static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
> {
> - int num_attrs = priv->plat->psu_count + priv->plat->pwr_count +
> - priv->plat->fan_count;
> - int i;
> + struct mlxreg_core_hotplug_platform_data *pdata;
> + struct mlxreg_core_item *item;
> + struct mlxreg_core_data *data;
> + int num_attrs = 0, id = 0, i, j;
> +
> + pdata = dev_get_platdata(&priv->pdev->dev);
> + item = pdata->items;
> +
> + /* Go over all kinds of items - psu, pwr, fan. */
> + for (i = 0; i < pdata->counter; i++, item++) {
> + num_attrs += item->count;
> + data = item->data;
> + /* Go over all units within the item. */
> + for (j = 0; j < item->count; j++, data++, id++) {
> + PRIV_ATTR(id) = &PRIV_DEV_ATTR(id).dev_attr.attr;
> + PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev,
> + GFP_KERNEL,
> + data->label);
> +
> + if (!PRIV_ATTR(id)->name) {
> + dev_err(priv->dev, "Memory allocation failed for attr %d.\n",
> + id);
> + return -ENOMEM;
> + }
> +
> + PRIV_DEV_ATTR(id).dev_attr.attr.name =
> + PRIV_ATTR(id)->name;
> + PRIV_DEV_ATTR(id).dev_attr.attr.mode = 0444;
> + PRIV_DEV_ATTR(id).dev_attr.show =
> + mlxreg_hotplug_attr_show;
> + PRIV_DEV_ATTR(id).nr = i;
> + PRIV_DEV_ATTR(id).index = j;
> + sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr);
> + }
> + }
>
> priv->group.attrs = devm_kzalloc(&priv->pdev->dev, num_attrs *
> sizeof(struct attribute *),
> @@ -172,38 +203,6 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
> if (!priv->group.attrs)
> return -ENOMEM;
>
> - for (i = 0; i < num_attrs; i++) {
> - PRIV_ATTR(i) = &PRIV_DEV_ATTR(i).dev_attr.attr;
> -
> - if (i < priv->plat->psu_count) {
> - PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
> - GFP_KERNEL, "psu%u", i + 1);
> - PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_PSU;
> - } else if (i < priv->plat->psu_count + priv->plat->pwr_count) {
> - PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
> - GFP_KERNEL, "pwr%u", i %
> - priv->plat->pwr_count + 1);
> - PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_PWR;
> - } else {
> - PRIV_ATTR(i)->name = devm_kasprintf(&priv->pdev->dev,
> - GFP_KERNEL, "fan%u", i %
> - priv->plat->fan_count + 1);
> - PRIV_DEV_ATTR(i).nr = MLXREG_HOTPLUG_ATTR_TYPE_FAN;
> - }
> -
> - if (!PRIV_ATTR(i)->name) {
> - dev_err(&priv->pdev->dev, "Memory allocation failed for sysfs attribute %d.\n",
> - i + 1);
> - return -ENOMEM;
> - }
> -
> - PRIV_DEV_ATTR(i).dev_attr.attr.name = PRIV_ATTR(i)->name;
> - PRIV_DEV_ATTR(i).dev_attr.attr.mode = S_IRUGO;
> - PRIV_DEV_ATTR(i).dev_attr.show = mlxreg_hotplug_attr_show;
> - PRIV_DEV_ATTR(i).index = i;
> - sysfs_attr_init(&PRIV_DEV_ATTR(i).dev_attr.attr);
> - }
> -
> priv->group.attrs = priv->mlxreg_hotplug_attr;
> priv->groups[0] = &priv->group;
> priv->groups[1] = NULL;
> @@ -211,20 +210,13 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
> return 0;
> }
>
> -static inline void
> -mlxreg_hotplug_work_helper(struct device *dev,
> - struct mlxreg_hotplug_device *item, u8 is_inverse,
> - u16 offset, u8 mask, u8 *cache)
> +static void
> +mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
> + struct mlxreg_core_item *item)
> {
> - u8 val, asserted;
> - int bit;
> -
> - /* Mask event. */
> - outb(0, offset + MLXREG_HOTPLUG_MASK_OFF);
> - /* Read status. */
> - val = inb(offset) & mask;
> - asserted = *cache ^ val;
> - *cache = val;
> + struct mlxreg_core_data *data;
> + u32 asserted, regval, bit;
> + int ret;
>
> /*
> * Validate if item related to received signal type is valid.
> @@ -234,86 +226,177 @@ mlxreg_hotplug_work_helper(struct device *dev,
> * signals from other devices if any.
> */
> if (unlikely(!item)) {
> - dev_err(dev, "False signal is received: register at offset 0x%02x, mask 0x%02x.\n",
> - offset, mask);
> + dev_err(priv->dev, "False signal: at offset:mask 0x%02x:0x%02x.\n",
> + item->reg, item->mask);
> +
> return;
> }
>
> + /* Mask event. */
> + ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
> + 0);
> + if (ret)
> + goto out;
> +
> + /* Read status. */
> + ret = regmap_read(priv->regmap, item->reg, &regval);
> + if (ret)
> + goto out;
> +
> + /* Set asserted bits and save last status. */
> + regval &= item->mask;
> + asserted = item->cache ^ regval;
> + item->cache = regval;
> +
> for_each_set_bit(bit, (unsigned long *)&asserted, 8) {
> - if (val & BIT(bit)) {
> - if (is_inverse)
> - mlxreg_hotplug_device_destroy(item + bit);
> + data = item->data + bit;
> + if (regval & BIT(bit)) {
> + if (item->inversed)
> + mlxreg_hotplug_device_destroy(data);
> else
> - mlxreg_hotplug_device_create(item + bit);
> + mlxreg_hotplug_device_create(data);
> } else {
> - if (is_inverse)
> - mlxreg_hotplug_device_create(item + bit);
> + if (item->inversed)
> + mlxreg_hotplug_device_create(data);
> else
> - mlxreg_hotplug_device_destroy(item + bit);
> + mlxreg_hotplug_device_destroy(data);
> }
> }
>
> /* Acknowledge event. */
> - outb(0, offset + MLXREG_HOTPLUG_EVENT_OFF);
> + ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_EVENT_OFF,
> + 0);
> + if (ret)
> + goto out;
> +
> /* Unmask event. */
> - outb(mask, offset + MLXREG_HOTPLUG_MASK_OFF);
> + ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
> + item->mask);
> +
> + out:
> + if (ret)
> + dev_err(priv->dev, "Failed to complete workqueue.\n");
> +}
> +
> +static void
> +mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
> + struct mlxreg_core_item *item)
> +{
> + struct mlxreg_core_data *data = item->data;
> + u32 regval;
> + int i, ret;
> +
> + for (i = 0; i < item->count; i++, data++) {
> + /* Mask event. */
> + ret = regmap_write(priv->regmap, data->reg +
> + MLXREG_HOTPLUG_MASK_OFF, 0);
> + if (ret)
> + goto out;
> +
> + /* Read status. */
> + ret = regmap_read(priv->regmap, data->reg, &regval);
> + if (ret)
> + goto out;
> +
> + regval &= data->mask;
> + item->cache = regval;
> + if (regval == MLXREG_HOTPLUG_HEALTH_MASK) {
> + if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) ||
> + !priv->after_probe) {
> + mlxreg_hotplug_device_create(data);
> + data->attached = true;
> + }
> + } else {
> + if (data->attached) {
> + mlxreg_hotplug_device_destroy(data);
> + data->attached = false;
> + data->health_cntr = 0;
> + }
> + }
> +
> + /* Acknowledge event. */
> + ret = regmap_write(priv->regmap, data->reg +
> + MLXREG_HOTPLUG_EVENT_OFF, 0);
> + if (ret)
> + goto out;
> +
> + /* Unmask event. */
> + ret = regmap_write(priv->regmap, data->reg +
> + MLXREG_HOTPLUG_MASK_OFF, data->mask);
> + if (ret)
> + goto out;
> + }
> +
> + out:
> + if (ret)
> + dev_err(priv->dev, "Failed to complete workqueue.\n");
> }
>
> /*
> - * mlxreg_hotplug_work_handler - performs traversing of CPLD interrupt
> + * mlxreg_hotplug_work_handler - performs traversing of device interrupt
> * registers according to the below hierarchy schema:
> *
> - * Aggregation registers (status/mask)
> - * PSU registers: *---*
> - * *-----------------* | |
> - * |status/event/mask|----->| * |
> - * *-----------------* | |
> - * Power registers: | |
> - * *-----------------* | |
> - * |status/event/mask|----->| * |---> CPU
> - * *-----------------* | |
> - * FAN registers:
> - * *-----------------* | |
> - * |status/event/mask|----->| * |
> - * *-----------------* | |
> - * *---*
> + * Aggregation registers (status/mask)
> + * PSU registers: *---*
> + * *-----------------* | |
> + * |status/event/mask|-----> | * |
> + * *-----------------* | |
> + * Power registers: | |
> + * *-----------------* | |
> + * |status/event/mask|-----> | * |
> + * *-----------------* | |
> + * FAN registers: | |--> CPU
> + * *-----------------* | |
> + * |status/event/mask|-----> | * |
> + * *-----------------* | |
> + * ASIC registers: | |
> + * *-----------------* | |
> + * |status/event/mask|-----> | * |
> + * *-----------------* | |
> + * *---*
> + *
> * In case some system changed are detected: FAN in/out, PSU in/out, power
> - * cable attached/detached, relevant device is created or destroyed.
> + * cable attached/detached, ASIC helath good/bad, relevant device is created
> + * or destroyed.
> */
> static void mlxreg_hotplug_work_handler(struct work_struct *work)
> {
> - struct mlxreg_hotplug_priv_data *priv = container_of(work,
> - struct mlxreg_hotplug_priv_data, dwork.work);
> - u8 val, aggr_asserted;
> + struct mlxreg_core_hotplug_platform_data *pdata;
> + struct mlxreg_hotplug_priv_data *priv;
> + struct mlxreg_core_item *item;
> + u32 regval, aggr_asserted;
> unsigned long flags;
> + int i, ret;
> +
> + priv = container_of(work, struct mlxreg_hotplug_priv_data,
> + dwork_irq.work);
> + pdata = dev_get_platdata(&priv->pdev->dev);
> + item = pdata->items;
>
> /* Mask aggregation event. */
> - outb(0, priv->plat->top_aggr_offset + MLXREG_HOTPLUG_AGGR_MASK_OFF);
> + ret = regmap_write(priv->regmap, pdata->cell +
> + MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
> + if (ret < 0)
> + goto out;
> +
> /* Read aggregation status. */
> - val = inb(priv->plat->top_aggr_offset) & priv->plat->top_aggr_mask;
> - aggr_asserted = priv->aggr_cache ^ val;
> - priv->aggr_cache = val;
> -
> - /* Handle PSU configuration changes. */
> - if (aggr_asserted & priv->plat->top_aggr_psu_mask)
> - mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->psu,
> - 1, priv->plat->psu_reg_offset,
> - priv->plat->psu_mask,
> - &priv->psu_cache);
> -
> - /* Handle power cable configuration changes. */
> - if (aggr_asserted & priv->plat->top_aggr_pwr_mask)
> - mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->pwr,
> - 0, priv->plat->pwr_reg_offset,
> - priv->plat->pwr_mask,
> - &priv->pwr_cache);
> -
> - /* Handle FAN configuration changes. */
> - if (aggr_asserted & priv->plat->top_aggr_fan_mask)
> - mlxreg_hotplug_work_helper(&priv->pdev->dev, priv->plat->fan,
> - 1, priv->plat->fan_reg_offset,
> - priv->plat->fan_mask,
> - &priv->fan_cache);
> + ret = regmap_read(priv->regmap, pdata->cell, &regval);
> + if (ret)
> + goto out;
> +
> + regval &= pdata->mask;
> + aggr_asserted = priv->aggr_cache ^ regval;
> + priv->aggr_cache = regval;
> +
> + /* Handle topology and health configuration changes. */
> + for (i = 0; i < pdata->counter; i++, item++) {
> + if (aggr_asserted & item->aggr_mask) {
> + if (item->health)
> + mlxreg_hotplug_health_work_helper(priv, item);
> + else
> + mlxreg_hotplug_work_helper(priv, item);
> + }
> + }
>
> if (aggr_asserted) {
> spin_lock_irqsave(&priv->lock, flags);
> @@ -328,8 +411,8 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
> * validates that no new signals have been received during
> * masking.
> */
> - cancel_delayed_work(&priv->dwork);
> - schedule_delayed_work(&priv->dwork, 0);
> + cancel_delayed_work(&priv->dwork_irq);
> + schedule_delayed_work(&priv->dwork_irq, 0);
>
> spin_unlock_irqrestore(&priv->lock, flags);
>
> @@ -337,92 +420,119 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
> }
>
> /* Unmask aggregation event (no need acknowledge). */
> - outb(priv->plat->top_aggr_mask, priv->plat->top_aggr_offset +
> - MLXREG_HOTPLUG_AGGR_MASK_OFF);
> + ret = regmap_write(priv->regmap, pdata->cell +
> + MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
> +
> + out:
> + if (ret)
> + dev_err(priv->dev, "Failed to complete workqueue.\n");
> }
>
> -static void mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
> +static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
> {
> - /* Clear psu presense event. */
> - outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
> - /* Set psu initial status as mask and unmask psu event. */
> - priv->psu_cache = priv->plat->psu_mask;
> - outb(priv->plat->psu_mask, priv->plat->psu_reg_offset +
> - MLXREG_HOTPLUG_MASK_OFF);
> -
> - /* Clear power cable event. */
> - outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
> - /* Keep power initial status as zero and unmask power event. */
> - outb(priv->plat->pwr_mask, priv->plat->pwr_reg_offset +
> - MLXREG_HOTPLUG_MASK_OFF);
> -
> - /* Clear fan presense event. */
> - outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
> - /* Set fan initial status as mask and unmask fan event. */
> - priv->fan_cache = priv->plat->fan_mask;
> - outb(priv->plat->fan_mask, priv->plat->fan_reg_offset +
> - MLXREG_HOTPLUG_MASK_OFF);
> + struct mlxreg_core_hotplug_platform_data *pdata;
> + struct mlxreg_core_item *item;
> + int i, ret;
> +
> + pdata = dev_get_platdata(&priv->pdev->dev);
> + item = pdata->items;
> +
> + for (i = 0; i < pdata->counter; i++, item++) {
> + /* Clear group presense event. */
> + ret = regmap_write(priv->regmap, item->reg +
> + MLXREG_HOTPLUG_EVENT_OFF, 0);
> + if (ret)
> + goto out;
> +
> + /* Set group initial status as mask and unmask group event. */
> + if (item->inversed) {
> + item->cache = item->mask;
> + ret = regmap_write(priv->regmap, item->reg +
> + MLXREG_HOTPLUG_MASK_OFF,
> + item->mask);
> + if (ret)
> + goto out;
> + }
> + }
>
> /* Keep aggregation initial status as zero and unmask events. */
> - outb(priv->plat->top_aggr_mask, priv->plat->top_aggr_offset +
> - MLXREG_HOTPLUG_AGGR_MASK_OFF);
> + ret = regmap_write(priv->regmap, pdata->cell +
> + MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
> + if (ret)
> + goto out;
> +
> + /* Keep low aggregation initial status as zero and unmask events. */
> + if (pdata->cell_low) {
> + ret = regmap_write(priv->regmap, pdata->cell_low +
> + MLXREG_HOTPLUG_AGGR_MASK_OFF,
> + pdata->mask_low);
> + if (ret)
> + goto out;
> + }
>
> /* Invoke work handler for initializing hot plug devices setting. */
> - mlxreg_hotplug_work_handler(&priv->dwork.work);
> + mlxreg_hotplug_work_handler(&priv->dwork_irq.work);
>
> + out:
> + if (ret)
> + dev_err(priv->dev, "Failed to set interrupts.\n");
> enable_irq(priv->irq);
> + return ret;
> }
>
> static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
> {
> - int i;
> + struct mlxreg_core_hotplug_platform_data *pdata;
> + struct mlxreg_core_item *item;
> + struct mlxreg_core_data *data;
> + int count, i, j;
>
> + pdata = dev_get_platdata(&priv->pdev->dev);
> + item = pdata->items;
> disable_irq(priv->irq);
> - cancel_delayed_work_sync(&priv->dwork);
> -
> - /* Mask aggregation event. */
> - outb(0, priv->plat->top_aggr_offset + MLXREG_HOTPLUG_AGGR_MASK_OFF);
> -
> - /* Mask psu presense event. */
> - outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
> - /* Clear psu presense event. */
> - outb(0, priv->plat->psu_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
> -
> - /* Mask power cable event. */
> - outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
> - /* Clear power cable event. */
> - outb(0, priv->plat->pwr_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
> -
> - /* Mask fan presense event. */
> - outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_MASK_OFF);
> - /* Clear fan presense event. */
> - outb(0, priv->plat->fan_reg_offset + MLXREG_HOTPLUG_EVENT_OFF);
> -
> - /* Remove all the attached devices. */
> - for (i = 0; i < priv->plat->psu_count; i++)
> - mlxreg_hotplug_device_destroy(priv->plat->psu + i);
> + cancel_delayed_work_sync(&priv->dwork_irq);
>
> - for (i = 0; i < priv->plat->pwr_count; i++)
> - mlxreg_hotplug_device_destroy(priv->plat->pwr + i);
> + /* Mask low aggregation event, if defined. */
> + if (pdata->cell_low)
> + regmap_write(priv->regmap, pdata->cell_low +
> + MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
>
> - for (i = 0; i < priv->plat->fan_count; i++)
> - mlxreg_hotplug_device_destroy(priv->plat->fan + i);
> + /* Mask aggregation event. */
> + regmap_write(priv->regmap, pdata->cell + MLXREG_HOTPLUG_AGGR_MASK_OFF,
> + 0);
> +
> + /* Clear topology configurations. */
> + for (i = 0; i < pdata->counter; i++, item++) {
> + data = item->data;
> + /* Mask group presense event. */
> + regmap_write(priv->regmap, data->reg + MLXREG_HOTPLUG_MASK_OFF,
> + 0);
> + /* Clear group presense event. */
> + regmap_write(priv->regmap, data->reg +
> + MLXREG_HOTPLUG_EVENT_OFF, 0);
> +
> + /* Remove all the attached devices in group. */
> + count = item->count;
> + for (j = 0; j < count; j++, data++)
> + mlxreg_hotplug_device_destroy(data);
> + }
> }
>
> static irqreturn_t mlxreg_hotplug_irq_handler(int irq, void *dev)
> {
> - struct mlxreg_hotplug_priv_data *priv =
> - (struct mlxreg_hotplug_priv_data *)dev;
> + struct mlxreg_hotplug_priv_data *priv;
> +
> + priv = (struct mlxreg_hotplug_priv_data *)dev;
>
> /* Schedule work task for immediate execution.*/
> - schedule_delayed_work(&priv->dwork, 0);
> + schedule_delayed_work(&priv->dwork_irq, 0);
>
> return IRQ_HANDLED;
> }
>
> static int mlxreg_hotplug_probe(struct platform_device *pdev)
> {
> - struct mlxreg_hotplug_platform_data *pdata;
> + struct mlxreg_core_hotplug_platform_data *pdata;
> struct mlxreg_hotplug_priv_data *priv;
> int err;
>
> @@ -436,31 +546,42 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
> if (!priv)
> return -ENOMEM;
>
> - priv->pdev = pdev;
> - priv->plat = pdata;
> -
> - priv->irq = platform_get_irq(pdev, 0);
> - if (priv->irq < 0) {
> - dev_err(&pdev->dev, "Failed to get platform irq: %d\n",
> - priv->irq);
> - return priv->irq;
> + if (pdata->irq) {
> + priv->irq = pdata->irq;
> + } else {
> + priv->irq = platform_get_irq(pdev, 0);
> + if (priv->irq < 0) {
> + dev_err(&pdev->dev, "Failed to get platform irq: %d\n",
> + priv->irq);
> + return priv->irq;
> + }
> }
>
> + priv->regmap = pdata->regmap;
> + priv->dev = pdev->dev.parent;
> + priv->pdev = pdev;
> +
> err = devm_request_irq(&pdev->dev, priv->irq,
> - mlxreg_hotplug_irq_handler, 0, pdev->name,
> - priv);
> + mlxreg_hotplug_irq_handler, IRQF_TRIGGER_FALLING
> + | IRQF_SHARED, "mlxreg-hotplug", priv);
> if (err) {
> dev_err(&pdev->dev, "Failed to request irq: %d\n", err);
> return err;
> }
> - disable_irq(priv->irq);
>
> - INIT_DELAYED_WORK(&priv->dwork, mlxreg_hotplug_work_handler);
> + disable_irq(priv->irq);
> spin_lock_init(&priv->lock);
> + INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler);
> + /* Perform initial interrupts setup. */
> + mlxreg_hotplug_set_irq(priv);
> +
> + priv->after_probe = true;
> + dev_set_drvdata(&pdev->dev, priv);
>
> err = mlxreg_hotplug_attr_init(priv);
> if (err) {
> - dev_err(&pdev->dev, "Failed to allocate attributes: %d\n", err);
> + dev_err(&pdev->dev, "Failed to allocate attributes: %d\n",
> + err);
> return err;
> }
>
> @@ -472,17 +593,12 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
> return PTR_ERR(priv->hwmon);
> }
>
> - platform_set_drvdata(pdev, priv);
> -
> - /* Perform initial interrupts setup. */
> - mlxreg_hotplug_set_irq(priv);
> -
> return 0;
> }
>
> static int mlxreg_hotplug_remove(struct platform_device *pdev)
> {
> - struct mlxreg_hotplug_priv_data *priv = platform_get_drvdata(pdev);
> + struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(&pdev->dev);
>
> /* Clean interrupts setup. */
> mlxreg_hotplug_unset_irq(priv);
> diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
> index 5601714..03c9e7a 100644
> --- a/drivers/platform/x86/mlx-platform.c
> +++ b/drivers/platform/x86/mlx-platform.c
> @@ -35,20 +35,22 @@
> #include <linux/dmi.h>
> #include <linux/i2c.h>
> #include <linux/i2c-mux.h>
> +#include <linux/io.h>
> #include <linux/module.h>
> #include <linux/platform_device.h>
> #include <linux/platform_data/i2c-mux-reg.h>
> #include <linux/platform_data/mlxreg.h>
> +#include <linux/regmap.h>
>
> #define MLX_PLAT_DEVICE_NAME "mlxplat"
>
> /* LPC bus IO offsets */
> #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
> #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
> -#define MLXPLAT_CPLD_LPC_REG_AGGR_ADRR 0x253a
> -#define MLXPLAT_CPLD_LPC_REG_PSU_ADRR 0x2558
> -#define MLXPLAT_CPLD_LPC_REG_PWR_ADRR 0x2564
> -#define MLXPLAT_CPLD_LPC_REG_FAN_ADRR 0x2588
> +#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
> +#define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58
> +#define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64
> +#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88
> #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
> #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
> #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
> @@ -138,78 +140,194 @@ static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
> };
>
> /* Platform hotplug devices */
> -static struct mlxreg_hotplug_device mlxplat_mlxcpld_psu[] = {
> +static struct i2c_board_info mlxplat_mlxcpld_psu[] = {
> {
> - .brdinfo = { I2C_BOARD_INFO("24c02", 0x51) },
> - .nr = 10,
> + I2C_BOARD_INFO("24c02", 0x51),
> },
> {
> - .brdinfo = { I2C_BOARD_INFO("24c02", 0x50) },
> - .nr = 10,
> + I2C_BOARD_INFO("24c02", 0x50),
> },
> };
>
> -static struct mlxreg_hotplug_device mlxplat_mlxcpld_pwr[] = {
> +static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
> {
> - .brdinfo = { I2C_BOARD_INFO("dps460", 0x59) },
> - .nr = 10,
> + I2C_BOARD_INFO("dps460", 0x59),
> },
> {
> - .brdinfo = { I2C_BOARD_INFO("dps460", 0x58) },
> - .nr = 10,
> + I2C_BOARD_INFO("dps460", 0x58),
> },
> };
>
> -static struct mlxreg_hotplug_device mlxplat_mlxcpld_fan[] = {
> +static struct i2c_board_info mlxplat_mlxcpld_fan[] = {
> {
> - .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
> - .nr = 11,
> + I2C_BOARD_INFO("24c32", 0x50),
> },
> {
> - .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
> - .nr = 12,
> + I2C_BOARD_INFO("24c32", 0x50),
> },
> {
> - .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
> - .nr = 13,
> + I2C_BOARD_INFO("24c32", 0x50),
> },
> {
> - .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) },
> - .nr = 14,
> + I2C_BOARD_INFO("24c32", 0x50),
> },
> };
>
> /* Platform hotplug default data */
> +static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = {
> + {
> + .label = "psu1",
> + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
> + .mask = BIT(0),
> + .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
> + .hpdev.nr = 10,
> + },
> + {
> + .label = "psu2",
> + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
> + .mask = BIT(1),
> + .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
> + .hpdev.nr = 10,
> + },
> +};
> +
> +static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = {
> + {
> + .label = "pwr1",
> + .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
> + .mask = BIT(0),
> + .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
> + .hpdev.nr = 10,
> + },
> + {
> + .label = "pwr2",
> + .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
> + .mask = BIT(1),
> + .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
> + .hpdev.nr = 10,
> + },
> +};
> +
> +static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = {
> + {
> + .label = "fan1",
> + .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
> + .mask = BIT(0),
> + .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0],
> + .hpdev.nr = 11,
> + },
> + {
> + .label = "fan2",
> + .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
> + .mask = BIT(1),
> + .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1],
> + .hpdev.nr = 12,
> + },
> + {
> + .label = "fan3",
> + .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
> + .mask = BIT(2),
> + .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2],
> + .hpdev.nr = 13,
> + },
> + {
> + .label = "fan4",
> + .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
> + .mask = BIT(3),
> + .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3],
> + .hpdev.nr = 14,
> + },
> +};
> +
> +static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
> + {
> + .data = mlxplat_mlxcpld_default_psu_items_data,
> + .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
> + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
> + .mask = MLXPLAT_CPLD_PSU_MASK,
> + .count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
> + .inversed = 1,
> + .health = false,
> + },
> + {
> + .data = mlxplat_mlxcpld_default_pwr_items_data,
> + .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
> + .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
> + .mask = MLXPLAT_CPLD_PWR_MASK,
> + .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
> + .inversed = 0,
> + .health = false,
> + },
> + {
> + .data = mlxplat_mlxcpld_default_fan_items_data,
> + .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
> + .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
> + .mask = MLXPLAT_CPLD_FAN_MASK,
> + .count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
> + .inversed = 1,
> + .health = false,
> + },
> +};
> +
> static
> -struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_default_data = {
> - .top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR,
> - .top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
> - .top_aggr_psu_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
> - .psu_reg_offset = MLXPLAT_CPLD_LPC_REG_PSU_ADRR,
> - .psu_mask = MLXPLAT_CPLD_PSU_MASK,
> - .psu_count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
> - .psu = mlxplat_mlxcpld_psu,
> - .top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
> - .pwr_reg_offset = MLXPLAT_CPLD_LPC_REG_PWR_ADRR,
> - .pwr_mask = MLXPLAT_CPLD_PWR_MASK,
> - .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
> - .pwr = mlxplat_mlxcpld_pwr,
> - .top_aggr_fan_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
> - .fan_reg_offset = MLXPLAT_CPLD_LPC_REG_FAN_ADRR,
> - .fan_mask = MLXPLAT_CPLD_FAN_MASK,
> - .fan_count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
> - .fan = mlxplat_mlxcpld_fan,
> +struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
> + .items = mlxplat_mlxcpld_default_items,
> + .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items),
> + .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
> + .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
> };
>
> /* Platform hotplug MSN21xx system family data */
> +static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = {
> + {
> + .data = mlxplat_mlxcpld_default_pwr_items_data,
> + .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
> + .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
> + .mask = MLXPLAT_CPLD_PWR_MASK,
> + .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
> + .inversed = 0,
> + .health = false,
> + },
> +};
> +
> static
> -struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
> - .top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR,
> - .top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX,
> - .top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX,
> - .pwr_reg_offset = MLXPLAT_CPLD_LPC_REG_PWR_ADRR,
> - .pwr_mask = MLXPLAT_CPLD_PWR_MASK,
> - .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
> +struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = {
> + .items = mlxplat_mlxcpld_msn21xx_items,
> + .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items),
> + .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
> + .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
> +};
> +
> +struct mlxplat_mlxcpld_regmap_context {
> + void __iomem *base;
> +};
> +
> +static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx;
> +
> +static int
> +mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val)
> +{
> + struct mlxplat_mlxcpld_regmap_context *ctx = context;
> +
> + *val = ioread8(ctx->base + reg);
> + return 0;
> +}
> +
> +static int
> +mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val)
> +{
> + struct mlxplat_mlxcpld_regmap_context *ctx = context;
> +
> + iowrite8(val, ctx->base + reg);
> + return 0;
> +}
> +
> +static const struct regmap_config mlxplat_mlxcpld_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .max_register = 255,
> + .reg_read = mlxplat_mlxcpld_reg_read,
> + .reg_write = mlxplat_mlxcpld_reg_write,
> };
>
> static struct resource mlxplat_mlxcpld_resources[] = {
> @@ -217,7 +335,7 @@ static struct resource mlxplat_mlxcpld_resources[] = {
> };
>
> static struct platform_device *mlxplat_dev;
> -static struct mlxreg_hotplug_platform_data *mlxplat_hotplug;
> +static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
>
> static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
> {
> @@ -328,6 +446,21 @@ static int __init mlxplat_init(void)
> }
> }
>
> + mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev,
> + mlxplat_lpc_resources[1].start, 1);
> + if (IS_ERR(mlxplat_mlxcpld_regmap_ctx.base)) {
> + err = PTR_ERR(mlxplat_mlxcpld_regmap_ctx.base);
> + goto fail_platform_mux_register;
> + }
> +
> + mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
> + &mlxplat_mlxcpld_regmap_ctx,
> + &mlxplat_mlxcpld_regmap_config);
> + if (IS_ERR(mlxplat_hotplug->regmap)) {
> + err = PTR_ERR(mlxplat_hotplug->regmap);
> + goto fail_platform_mux_register;
> + }
> +
> priv->pdev_hotplug = platform_device_register_resndata(
> &mlxplat_dev->dev, "mlxreg-hotplug",
> PLATFORM_DEVID_NONE,
> diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
> index 5c98ad1..c25623b 100644
> --- a/include/linux/platform_data/mlxreg.h
> +++ b/include/linux/platform_data/mlxreg.h
> @@ -34,13 +34,15 @@
> #ifndef __LINUX_PLATFORM_DATA_MLXREG_H
> #define __LINUX_PLATFORM_DATA_MLXREG_H
>
> +#define MLXREG_CORE_LABEL_MAX_SIZE 32
> +
> /**
> * struct mlxreg_hotplug_device - I2C device data:
> + *
> * @adapter: I2C device adapter;
> * @client: I2C device client;
> * @brdinfo: device board information;
> * @nr: I2C device adapter number, to which device is to be attached;
> - * @np - pointer to node platform associated with attribute;

We just added this in 3/4. This should have just been skipped and done as it is
here directly, and only enabling ARM support at the end.

> *
> * Structure represents I2C hotplug device static data (board topology) and
> * dynamic data (related kernel objects handles).
> @@ -48,53 +50,95 @@
> struct mlxreg_hotplug_device {
> struct i2c_adapter *adapter;
> struct i2c_client *client;
> - struct i2c_board_info brdinfo;
> + struct i2c_board_info *brdinfo;
> int nr;
> +};
> +
> +/**
> + * struct mlxreg_core_data - attributes control data:
> + *
> + * @label: attribute label;
> + * @label: attribute register offset;
> + * @reg: attribute register;
> + * @mask: attribute access mask;
> + * @mode: access mode;
> + * @bit: attribute effective bit;
> + * @np - pointer to node platform associated with attribute;
> + * @hpdev - hotplug device data;
> + * @health_cntr: dynamic device health indication counter;
> + * @attached: true if device has been attached after good helath indication;
> + */
> +struct mlxreg_core_data {
> + char label[MLXREG_CORE_LABEL_MAX_SIZE];
> + u32 reg;
> + u32 mask;
> + u32 bit;
> + umode_t mode;
> struct device_node *np;
> + struct mlxreg_hotplug_device hpdev;
> + u8 health_cntr;
> + bool attached;
> +};
> +
> +/**
> + * struct mlxreg_core_item - same type components controlled by the driver:
> + *
> + * @data: component data;
> + * @aggr_mask: group aggregation mask;
> + * @reg: group interrupt status register;
> + * @mask: group interrupt mask;
> + * @cache: last status value for elements fro the same group;
> + * @count: number of available elements in the group;
> + * @ind: element's index inside the group;
> + * @inversed: if 0: 0 for signal status is OK, if 1 - 1 is OK;
> + * @health: true if device has health indication, false in other case;
> + */
> +struct mlxreg_core_item {
> + struct mlxreg_core_data *data;
> + u32 aggr_mask;
> + u32 reg;
> + u32 mask;
> + u32 cache;
> + u8 count;
> + u8 ind;
> + u8 inversed;
> + u8 health;
> +};
> +
> +/**
> + * struct mlxreg_core_platform_data - platform data:
> + *
> + * @led_data: led private data;
> + * @regmap: register map of parent device;
> + * @counter: number of led instances;
> + */
> +struct mlxreg_core_platform_data {
> + struct mlxreg_core_data *data;
> + void *regmap;
> + int counter;
> };
>
> /**
> - * struct mlxreg_hotplug_platform_data - device platform data:
> - * @top_aggr_offset: offset of top aggregation interrupt register;
> - * @top_aggr_mask: top aggregation interrupt common mask;
> - * @top_aggr_psu_mask: top aggregation interrupt PSU mask;
> - * @psu_reg_offset: offset of PSU interrupt register;
> - * @psu_mask: PSU interrupt mask;
> - * @psu_count: number of equipped replaceable PSUs;
> - * @psu: pointer to PSU devices data array;
> - * @top_aggr_pwr_mask: top aggregation interrupt power mask;
> - * @pwr_reg_offset: offset of power interrupt register
> - * @pwr_mask: power interrupt mask;
> - * @pwr_count: number of power sources;
> - * @pwr: pointer to power devices data array;
> - * @top_aggr_fan_mask: top aggregation interrupt FAN mask;
> - * @fan_reg_offset: offset of FAN interrupt register;
> - * @fan_mask: FAN interrupt mask;
> - * @fan_count: number of equipped replaceable FANs;
> - * @fan: pointer to FAN devices data array;
> + * struct mlxreg_core_hotplug_platform_data - hotplug platform data:
> *
> - * Structure represents board platform data, related to system hotplug events,
> - * like FAN, PSU, power cable insertion and removing. This data provides the
> - * number of hot-pluggable devices and hardware description for event handling.
> + * @items: same type components with the hotplug capability;
> + * @irq: platform interrupt number;
> + * @regmap: register map of parent device;
> + * @counter: number of the components with the hotplug capability;
> + * @cell: location of top aggregation interrupt register;
> + * @mask: top aggregation interrupt common mask;
> + * @cell_low: location of low aggregation interrupt register;
> + * @mask_low: low aggregation interrupt common mask;
> */
> -struct mlxreg_hotplug_platform_data {
> - u16 top_aggr_offset;
> - u8 top_aggr_mask;
> - u8 top_aggr_psu_mask;
> - u16 psu_reg_offset;
> - u8 psu_mask;
> - u8 psu_count;
> - struct mlxreg_hotplug_device *psu;
> - u8 top_aggr_pwr_mask;
> - u16 pwr_reg_offset;
> - u8 pwr_mask;
> - u8 pwr_count;
> - struct mlxreg_hotplug_device *pwr;
> - u8 top_aggr_fan_mask;
> - u16 fan_reg_offset;
> - u8 fan_mask;
> - u8 fan_count;
> - struct mlxreg_hotplug_device *fan;
> +struct mlxreg_core_hotplug_platform_data {
> + struct mlxreg_core_item *items;
> + int irq;
> + void *regmap;
> + int counter;
> + u32 cell;
> + u32 mask;
> + u32 cell_low;
> + u32 mask_low;
> };
>
> #endif /* __LINUX_PLATFORM_DATA_MLXREG_H */
> --
> 2.1.4
>
>

--
Darren Hart
VMware Open Source Technology Center

2018-01-23 03:52:06

by Darren Hart

[permalink] [raw]
Subject: Re: [patch v9 4/4] platform/mellanox: mlxreg-hotplug: Modify to use a regmap interface

On Mon, Jan 22, 2018 at 07:49:46PM -0800, Darren Hart wrote:
> On Wed, Jan 17, 2018 at 06:21:56PM +0000, Vadim Pasternak wrote:
> > +#define MLXREG_CORE_LABEL_MAX_SIZE 32
> > +
> > /**
> > * struct mlxreg_hotplug_device - I2C device data:
> > + *
> > * @adapter: I2C device adapter;
> > * @client: I2C device client;
> > * @brdinfo: device board information;
> > * @nr: I2C device adapter number, to which device is to be attached;
> > - * @np - pointer to node platform associated with attribute;
>
> We just added this in 3/4. This should have just been skipped and done as it is
> here directly, and only enabling ARM support at the end.

Apologies, I was still working on this email when I accidentally sent it instead
of postponing it. The above is true, but I'm working on fixing it in my branch.

No need to resend at this point.

--
Darren Hart
VMware Open Source Technology Center

2018-01-23 03:52:31

by Darren Hart

[permalink] [raw]
Subject: Re: [patch v9 1/4] platform/x86: Move Mellanox hardware platform hotplug driver to platform/mellanox

On Wed, Jan 17, 2018 at 06:21:53PM +0000, Vadim Pasternak wrote:
> It moves drivers/platform/x86/mlxcpld-hotplug.c to
> drivers/platform/mellanox/mlxreg-hotplug.c and
> include/linux/platform_data/mlxcpld-hotplug.h to
> include/linux/platform_data/mlxreg.h for making hotplug driver usable for
> the different machine architectures.
>
> Signed-off-by: Vadim Pasternak <[email protected]>
> Acked-by: Andy Shevchenko <[email protected]>
> ---
> v9->v8:
> Comments pointed out by Darren:
> - make removing of X86_64 dependency of mlx-platform to a separate patch
> since it is not related to the moving hotplug driver to
> platform/mellanox;
> v7->v8:
> v6->v7:
> Fixes added by Vadim:
> - remove dependency on X86_64 to allow also X86 architecture;
> v5->v6:
> Fixes added by Vadim:
> - add SPD license record to Kconfig and Makefile;
> v4->v5:
> Comments pointed out by Andy:
> - arrange MAINTAINERS in correct alphabetic order;
> v3->v4:
> Comments pointed out by Darren:
> - Refactor the patches to provide the changes in patchset in incremental
> order;
> - Modify MAINTAINERS records;
> - Use git-mv for the replaced files;
> Commnets pointed out by Colin:
> - Make structures mlxplat_dev and mlxplat_hotplug static;
> ---
> MAINTAINERS | 7 +-
> drivers/platform/Kconfig | 2 +
> drivers/platform/Makefile | 1 +
> drivers/platform/mellanox/Kconfig | 25 +++
> drivers/platform/mellanox/Makefile | 6 +
> .../mlxreg-hotplug.c} | 223 ++++++++++-----------
> drivers/platform/x86/Kconfig | 8 -
> drivers/platform/x86/Makefile | 1 -
> drivers/platform/x86/mlx-platform.c | 18 +-
> .../platform_data/{mlxcpld-hotplug.h => mlxreg.h} | 25 ++-
> 10 files changed, 170 insertions(+), 146 deletions(-)
> create mode 100644 drivers/platform/mellanox/Kconfig
> create mode 100644 drivers/platform/mellanox/Makefile
> rename drivers/platform/{x86/mlxcpld-hotplug.c => mellanox/mlxreg-hotplug.c} (65%)
> rename include/linux/platform_data/{mlxcpld-hotplug.h => mlxreg.h} (84%)
>

...

> diff --git a/drivers/platform/x86/mlxcpld-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
> similarity index 65%
> rename from drivers/platform/x86/mlxcpld-hotplug.c
> rename to drivers/platform/mellanox/mlxreg-hotplug.c
> index aff3686..2866c76 100644
> --- a/drivers/platform/x86/mlxcpld-hotplug.c
> +++ b/drivers/platform/mellanox/mlxreg-hotplug.c
> @@ -1,7 +1,6 @@
> /*
> - * drivers/platform/x86/mlxcpld-hotplug.c
> - * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
> - * Copyright (c) 2016 Vadim Pasternak <[email protected]>
> + * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
> + * Copyright (c) 2017 Vadim Pasternak <[email protected]>

Copyright should persist across git rename. I've updated this to 2016-2018 on
both lines.

> /* Offset of event and mask registers from status register */
> -#define MLXCPLD_HOTPLUG_EVENT_OFF 1
> -#define MLXCPLD_HOTPLUG_MASK_OFF 2
> -#define MLXCPLD_HOTPLUG_AGGR_MASK_OFF 1
> +#define MLXREG_HOTPLUG_EVENT_OFF 1
> +#define MLXREG_HOTPLUG_MASK_OFF 2
> +#define MLXREG_HOTPLUG_AGGR_MASK_OFF 1

This, and much of what follows, is an additional change from the move, but it is
not called out in the changelog. I've added a note to the changelog about
renaming from MLXCPLD to MLXREG.

No need to resend.

--
Darren Hart
VMware Open Source Technology Center

2018-01-23 03:55:05

by Darren Hart

[permalink] [raw]
Subject: Re: [patch v9 3/4] platform/mellanox: mlxreg-hotplug: Code cleanup

On Wed, Jan 17, 2018 at 06:21:55PM +0000, Vadim Pasternak wrote:

As I continue to pick these patches apart into their individual functional
changes, I'm finding more issues...

> Renaming field bus in structure mlxreg_hotplug_device to nr to have a name
> consistent with Linux i2c naming.
>
> Removing unnecessary includes.
>
> Removing from mlxreg_hotplug_device_create dev_err to upper layer should
> produce error on EFAULT return.
>

But the only caller doesn't check the return code. Where did you expect for this
error to be detected?

> Relocation mlxreg_hotplug_device_create/destroy to the beginning of the
> mlxreg-hotplug.c in order to have attribute related code at the same
> location.
>
> Add to structure mlxreg_hotplug_device device node handle for devices
> defined in device table tree;
>

The above should *really* be several changes. Start with the non-functional
preparatory changes, followed by single functional change. Also, it seems to me
adding the device node prior to enabling building on ARM would make sense??

I've broken this up, verified incremental build, and rewritten the commit
messages. I have this sitting in a local branch currently.

I need you to respond to the question above re the create call, but I'll make
the change myself.

--
Darren Hart
VMware Open Source Technology Center

2018-01-23 04:03:53

by Darren Hart

[permalink] [raw]
Subject: Re: [patch v9 3/4] platform/mellanox: mlxreg-hotplug: Code cleanup

On Wed, Jan 17, 2018 at 06:21:55PM +0000, Vadim Pasternak wrote:
> Removing unnecessary includes.
...
> diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
> index 2866c76..556e612 100644
> --- a/drivers/platform/mellanox/mlxreg-hotplug.c
> +++ b/drivers/platform/mellanox/mlxreg-hotplug.c
> @@ -41,8 +41,6 @@
> #include <linux/module.h>
> #include <linux/platform_data/mlxreg.h>
> #include <linux/platform_device.h>
> -#include <linux/spinlock.h>

But spinlock IS required. Just because some other include eventually also
includes it doesn't meet we can drop it here. We use functions defined in
spinlock.h, so it needs to be included.

I've updated this in my branch...

--
Darren Hart
VMware Open Source Technology Center

2018-01-23 04:14:07

by Darren Hart

[permalink] [raw]
Subject: Re: [patch v9 0/4] drivers/platform: Replace module x86/mlxcpld-hotplug with mellanox/mlxreg-hotplug

On Wed, Jan 17, 2018 at 06:21:52PM +0000, Vadim Pasternak wrote:
> The patchset:
> - replaces modules include/linux/platform_data/mlxcpld-hotplug.h and
> drivers/platform/x86/mlxcpld-hotplug.c with the modules
> include/linux/platform_data/mlxreg.h and
> drivers/platform/mellanox/mlxreg-hotplug.c;
> relevant Makefile and Kconfig are updated;
> - modifies Mellanox hotplug driver for making it architecture
> independent. Drivers has been tested for x86 and ARM based systems.
> - includes code cleanup;
> - introduces regmap interface for mlxreg-hotplug driver to allow hotplug
> event functionality over programmable devices logic, when these devices
> can be attached to different interfaces types, like I2C, LPC, SPI;
> driver drivers/platform/x86/mlx-platform.c is updated according to new
> interface.

This series is still not dividing up changes into small functional chunks. It
"ping pongs" (adding then later removing code), and makes it difficult to review
functional changes by surrounding them with non-functional transformations. As
I've attempted to break this apart myself, I've discovered a few issues with the
code - see the responses to the individual patches.

You can find my broken up version here:
http://git.infradead.org/linux-platform-drivers-x86.git/shortlog/refs/heads/review-dvhart-mellanox-v10

In particular, please see:
http://git.infradead.org/linux-platform-drivers-x86.git/commit/4f0057fc3da29c04e2cefca9dc5b17577b3e4988

Vadim, please respond to my questions re the individual patches, and I'll
increment the patches in the above branch before pushing this up to testing.

--
Darren Hart
VMware Open Source Technology Center

2018-01-23 18:05:51

by Vadim Pasternak

[permalink] [raw]
Subject: RE: [patch v9 0/4] drivers/platform: Replace module x86/mlxcpld-hotplug with mellanox/mlxreg-hotplug



> -----Original Message-----
> From: Darren Hart [mailto:[email protected]]
> Sent: Tuesday, January 23, 2018 6:13 AM
> To: Vadim Pasternak <[email protected]>
> Cc: [email protected]; [email protected]; linux-
> [email protected]; [email protected]; [email protected]
> Subject: Re: [patch v9 0/4] drivers/platform: Replace module x86/mlxcpld-
> hotplug with mellanox/mlxreg-hotplug
>
> On Wed, Jan 17, 2018 at 06:21:52PM +0000, Vadim Pasternak wrote:
> > The patchset:
> > - replaces modules include/linux/platform_data/mlxcpld-hotplug.h and
> > drivers/platform/x86/mlxcpld-hotplug.c with the modules
> > include/linux/platform_data/mlxreg.h and
> > drivers/platform/mellanox/mlxreg-hotplug.c;
> > relevant Makefile and Kconfig are updated;
> > - modifies Mellanox hotplug driver for making it architecture
> > independent. Drivers has been tested for x86 and ARM based systems.
> > - includes code cleanup;
> > - introduces regmap interface for mlxreg-hotplug driver to allow hotplug
> > event functionality over programmable devices logic, when these devices
> > can be attached to different interfaces types, like I2C, LPC, SPI;
> > driver drivers/platform/x86/mlx-platform.c is updated according to new
> > interface.
>
> This series is still not dividing up changes into small functional chunks. It "ping
> pongs" (adding then later removing code), and makes it difficult to review
> functional changes by surrounding them with non-functional transformations. As
> I've attempted to break this apart myself, I've discovered a few issues with the
> code - see the responses to the individual patches.
>
> You can find my broken up version here:
> http://git.infradead.org/linux-platform-drivers-
> x86.git/shortlog/refs/heads/review-dvhart-mellanox-v10
>
> In particular, please see:
> http://git.infradead.org/linux-platform-drivers-
> x86.git/commit/4f0057fc3da29c04e2cefca9dc5b17577b3e4988
>
> Vadim, please respond to my questions re the individual patches, and I'll
> increment the patches in the above branch before pushing this up to testing.
>

Hi Darren,

Thank you for your reviews.

I wanted to take update from your update git, to align the patches with series
you pushed to review-dvhart-mellanox-v10.
But I have some issue with
cda61cd592ebc9534b9786c337b124a86a6e303f hash:
git remote update
Fetching origin
remote: error: inflate: data stream error (incorrect header check)
remote: error: unable to unpack cda61cd592ebc9534b9786c337b124a86a6e303f header
remote: fatal: loose object cda61cd592ebc9534b9786c337b124a86a6e303f (stored in ./objects/cd/a61cd592ebc9534b9786c337b124a86a6e303f) is corrupt
remote: aborting due to possible repository corruption on the remote side.
fatal: protocol error: bad pack header
error: Could not fetch origin

Same in case I just clone git anew.

I am about to re-send the series started from the patch 2.
I currently dropped the changes related to removing dev_err (from FIXME
platform/mellanox: Remove redundant dev_err messa).
I also added one extra patch between
platform/mellanox: mlxreg-hotplug: Modify to use a
and
platform/mellanox: mlxreg-hotplug: Enable building

And I'll not resend
platform/x86: mlx-platform: Allow compilation for 32
since it has been moved from the series as a separate patch.

> --
> Darren Hart
> VMware Open Source Technology Center

2018-01-23 21:55:27

by Darren Hart

[permalink] [raw]
Subject: Re: [patch v9 0/4] drivers/platform: Replace module x86/mlxcpld-hotplug with mellanox/mlxreg-hotplug

On Tue, Jan 23, 2018 at 06:04:37PM +0000, Vadim Pasternak wrote:
>
>
> > -----Original Message-----
> > From: Darren Hart [mailto:[email protected]]
> > Sent: Tuesday, January 23, 2018 6:13 AM
> > To: Vadim Pasternak <[email protected]>
> > Cc: [email protected]; [email protected]; linux-
> > [email protected]; [email protected]; [email protected]
> > Subject: Re: [patch v9 0/4] drivers/platform: Replace module x86/mlxcpld-
> > hotplug with mellanox/mlxreg-hotplug
> >
> > On Wed, Jan 17, 2018 at 06:21:52PM +0000, Vadim Pasternak wrote:
> > > The patchset:
> > > - replaces modules include/linux/platform_data/mlxcpld-hotplug.h and
> > > drivers/platform/x86/mlxcpld-hotplug.c with the modules
> > > include/linux/platform_data/mlxreg.h and
> > > drivers/platform/mellanox/mlxreg-hotplug.c;
> > > relevant Makefile and Kconfig are updated;
> > > - modifies Mellanox hotplug driver for making it architecture
> > > independent. Drivers has been tested for x86 and ARM based systems.
> > > - includes code cleanup;
> > > - introduces regmap interface for mlxreg-hotplug driver to allow hotplug
> > > event functionality over programmable devices logic, when these devices
> > > can be attached to different interfaces types, like I2C, LPC, SPI;
> > > driver drivers/platform/x86/mlx-platform.c is updated according to new
> > > interface.
> >
> > This series is still not dividing up changes into small functional chunks. It "ping
> > pongs" (adding then later removing code), and makes it difficult to review
> > functional changes by surrounding them with non-functional transformations. As
> > I've attempted to break this apart myself, I've discovered a few issues with the
> > code - see the responses to the individual patches.
> >
> > You can find my broken up version here:
> > http://git.infradead.org/linux-platform-drivers-
> > x86.git/shortlog/refs/heads/review-dvhart-mellanox-v10
> >
> > In particular, please see:
> > http://git.infradead.org/linux-platform-drivers-
> > x86.git/commit/4f0057fc3da29c04e2cefca9dc5b17577b3e4988
> >
> > Vadim, please respond to my questions re the individual patches, and I'll
> > increment the patches in the above branch before pushing this up to testing.
> >
>
> Hi Darren,
>
> Thank you for your reviews.
>
> I wanted to take update from your update git, to align the patches with series
> you pushed to review-dvhart-mellanox-v10.
> But I have some issue with
> cda61cd592ebc9534b9786c337b124a86a6e303f hash:
> git remote update
> Fetching origin
> remote: error: inflate: data stream error (incorrect header check)
> remote: error: unable to unpack cda61cd592ebc9534b9786c337b124a86a6e303f header
> remote: fatal: loose object cda61cd592ebc9534b9786c337b124a86a6e303f (stored in ./objects/cd/a61cd592ebc9534b9786c337b124a86a6e303f) is corrupt
> remote: aborting due to possible repository corruption on the remote side.
> fatal: protocol error: bad pack header
> error: Could not fetch origin
>
> Same in case I just clone git anew.

We're having some trouble with the repo on infradead. I have it temporarily
available on github:

https://github.com/dvhart/linux-pdx86/tree/review-dvhart-mellanox-v10

>
> I am about to re-send the series started from the patch 2.
> I currently dropped the changes related to removing dev_err (from FIXME
> platform/mellanox: Remove redundant dev_err messa).
> I also added one extra patch between
> platform/mellanox: mlxreg-hotplug: Modify to use a
> and
> platform/mellanox: mlxreg-hotplug: Enable building
>
> And I'll not resend
> platform/x86: mlx-platform: Allow compilation for 32
> since it has been moved from the series as a separate patch.

I'll follow up there.

--
Darren Hart
VMware Open Source Technology Center