diff options
Diffstat (limited to 'drivers/platform/mellanox/mlxreg-hotplug.c')
-rw-r--r-- | drivers/platform/mellanox/mlxreg-hotplug.c | 114 |
1 files changed, 64 insertions, 50 deletions
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index ed48917af162..b013445147dd 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -1,34 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved. - * Copyright (c) 2016-2018 Vadim Pasternak <vadimp@mellanox.com> + * Mellanox hotplug driver * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * Copyright (C) 2016-2020 Mellanox Technologies */ #include <linux/bitops.h> @@ -42,6 +16,7 @@ #include <linux/platform_data/mlxreg.h> #include <linux/platform_device.h> #include <linux/spinlock.h> +#include <linux/string_helpers.h> #include <linux/regmap.h> #include <linux/workqueue.h> @@ -97,6 +72,23 @@ struct mlxreg_hotplug_priv_data { u8 not_asserted; }; +/* Environment variables array for udev. */ +static char *mlxreg_hotplug_udev_envp[] = { NULL, NULL }; + +static int +mlxreg_hotplug_udev_event_send(struct kobject *kobj, + struct mlxreg_core_data *data, bool action) +{ + char event_str[MLXREG_CORE_LABEL_MAX_SIZE + 2]; + char label[MLXREG_CORE_LABEL_MAX_SIZE] = { 0 }; + + mlxreg_hotplug_udev_envp[0] = event_str; + string_upper(label, data->label); + snprintf(event_str, MLXREG_CORE_LABEL_MAX_SIZE, "%s=%d", label, !!action); + + return kobject_uevent_env(kobj, KOBJ_CHANGE, mlxreg_hotplug_udev_envp); +} + static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, struct mlxreg_core_data *data) { @@ -104,7 +96,7 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, struct i2c_client *client; /* Notify user by sending hwmon uevent. */ - kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); + mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, true); /* * Return if adapter number is negative. It could be in case hotplug @@ -144,7 +136,7 @@ mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv, struct mlxreg_core_data *data) { /* Notify user by sending hwmon uevent. */ - kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); + mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, false); if (data->hpdev.client) { i2c_unregister_device(data->hpdev.client); @@ -199,17 +191,49 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) 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; + unsigned long mask; + u32 regval; + int num_attrs = 0, id = 0, i, j, k, ret; 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; + if (item->capability) { + /* + * Read group capability register to get actual number + * of interrupt capable components and set group mask + * accordingly. + */ + ret = regmap_read(priv->regmap, item->capability, + ®val); + if (ret) + return ret; + + item->mask = GENMASK((regval & item->mask) - 1, 0); + } + data = item->data; - /* Go over all units within the item. */ - for (j = 0; j < item->count; j++, data++, id++) { + + /* Go over all unmasked units within item. */ + mask = item->mask; + k = 0; + for_each_set_bit(j, &mask, item->count) { + if (data->capability) { + /* + * Read capability register and skip non + * relevant attributes. + */ + ret = regmap_read(priv->regmap, + 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, @@ -227,9 +251,13 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) PRIV_DEV_ATTR(id).dev_attr.show = mlxreg_hotplug_attr_show; PRIV_DEV_ATTR(id).nr = i; - PRIV_DEV_ATTR(id).index = j; + PRIV_DEV_ATTR(id).index = k; sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr); + data++; + id++; + k++; } + num_attrs += k; } priv->group.attrs = devm_kcalloc(&priv->pdev->dev, @@ -507,20 +535,6 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) item = pdata->items; for (i = 0; i < pdata->counter; i++, item++) { - if (item->capability) { - /* - * Read group capability register to get actual number - * of interrupt capable components and set group mask - * accordingly. - */ - ret = regmap_read(priv->regmap, item->capability, - ®val); - if (ret) - goto out; - - item->mask = GENMASK((regval & item->mask) - 1, 0); - } - /* Clear group presense event. */ ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_EVENT_OFF, 0); |