diff options
author | Vadim Pasternak <vadimp@nvidia.com> | 2023-02-08 09:33:26 +0300 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2023-02-13 14:07:50 +0300 |
commit | 26e118ea98cf5ec0b53198e643d5fa8d99b73b49 (patch) | |
tree | 0032f53f2edcee55e08dc2923b7ee516a42220cc /drivers | |
parent | 233fd7e44cd7363ede8025619291b98475024c30 (diff) | |
download | linux-26e118ea98cf5ec0b53198e643d5fa8d99b73b49.tar.xz |
platform/mellanox: mlxreg-hotplug: Allow more flexible hotplug events configuration
Currently hotplug configuration in logic device assumes that all items
are provided with no holes.
Thus, any group of hotplug events, associated with the specific
status/event/mask registers is configured in those registers
successively from bit zero to bit #n (#n < 8).
This logic is changed int order to allow non-successive definition to
support configuration with the skipped bits – for example bits 3, 5, 7
in status/event/mask registers can be associated with hotplug events,
while others can be skipped.
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Reviewed-by: Michael Shych <michaelsh@nvidia.com>
Link: https://lore.kernel.org/r/20230208063331.15560-10-vadimp@nvidia.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/platform/mellanox/mlxreg-hotplug.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index 117bc3f395fd..b7dcc64cd238 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -239,6 +239,17 @@ static ssize_t mlxreg_hotplug_attr_show(struct device *dev, #define PRIV_ATTR(i) priv->mlxreg_hotplug_attr[i] #define PRIV_DEV_ATTR(i) priv->mlxreg_hotplug_dev_attr[i] +static int mlxreg_hotplug_item_label_index_get(u32 mask, u32 bit) +{ + int i, j; + + for (i = 0, j = -1; i <= bit; i++) { + if (mask & BIT(i)) + j++; + } + return j; +} + static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) { struct mlxreg_core_hotplug_platform_data *pdata; @@ -246,7 +257,7 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) struct mlxreg_core_data *data; unsigned long mask; u32 regval; - int num_attrs = 0, id = 0, i, j, k, ret; + int num_attrs = 0, id = 0, i, j, k, count, ret; pdata = dev_get_platdata(&priv->pdev->dev); item = pdata->items; @@ -272,7 +283,8 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) /* Go over all unmasked units within item. */ mask = item->mask; k = 0; - for_each_set_bit(j, &mask, item->count) { + count = item->ind ? item->ind : item->count; + for_each_set_bit(j, &mask, count) { if (data->capability) { /* * Read capability register and skip non @@ -282,16 +294,17 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) data->capability, ®val); if (ret) return ret; + if (!(regval & data->bit)) { data++; continue; } } + 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); @@ -365,9 +378,14 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv, regval &= item->mask; asserted = item->cache ^ regval; item->cache = regval; - for_each_set_bit(bit, &asserted, 8) { - data = item->data + bit; + int pos; + + pos = mlxreg_hotplug_item_label_index_get(item->mask, bit); + if (pos < 0) + goto out; + + data = item->data + pos; if (regval & BIT(bit)) { if (item->inversed) mlxreg_hotplug_device_destroy(priv, data, item->kind); |