Skip to content

Commit bb1023b

Browse files
vadimp-nvidiajwrdegoede
authored andcommitted
platform/mellanox: mlxreg-hotplug: Extend logic for hotplug devices operations
Extend the structure 'mlxreg_hotplug_device" with platform device field to allow transition of the register map and system interrupt line number to underlying hotplug devices, sharing the same register map and same interrupt line with 'mlxreg-hotplug' driver. Extend logic for hotplug devices creation and removing according to the action associated with the hotplug device description. Previously hotplug driver was capable to attach / de-attach upon hotplug events only I2C devices handled by simple I2C drivers. Now it should be able to attach also devices handled by the platform drivers. The motivation is to allow transition of platform data like: - system interrupt line number, sharing with 'mlxreg-hotplug' to underlying hotplug devices. - shared register map of programmable devices on main board to underlying hotplug devices. Additioanlly the number of 'sysfs' attributes is increased, since modular system defines more 'sysfs' attributes. Signed-off-by: Vadim Pasternak <vadimp@nvidia.com> Reviewed-by: Michael Shych <michaelsh@nvidia.com> Link: https://lore.kernel.org/r/20211002093238.3771419-4-vadimp@nvidia.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 parent a5d8f57 commit bb1023b

File tree

2 files changed

+112
-35
lines changed

2 files changed

+112
-35
lines changed

drivers/platform/mellanox/mlxreg-hotplug.c

Lines changed: 88 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
/* ASIC good health mask. */
2929
#define MLXREG_HOTPLUG_GOOD_HEALTH_MASK 0x02
3030

31-
#define MLXREG_HOTPLUG_ATTRS_MAX 24
31+
#define MLXREG_HOTPLUG_ATTRS_MAX 128
3232
#define MLXREG_HOTPLUG_NOT_ASSERT 3
3333

3434
/**
@@ -89,9 +89,20 @@ mlxreg_hotplug_udev_event_send(struct kobject *kobj,
8989
return kobject_uevent_env(kobj, KOBJ_CHANGE, mlxreg_hotplug_udev_envp);
9090
}
9191

92+
static void
93+
mlxreg_hotplug_pdata_export(void *pdata, void *regmap)
94+
{
95+
struct mlxreg_core_hotplug_platform_data *dev_pdata = pdata;
96+
97+
/* Export regmap to underlying device. */
98+
dev_pdata->regmap = regmap;
99+
}
100+
92101
static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
93-
struct mlxreg_core_data *data)
102+
struct mlxreg_core_data *data,
103+
enum mlxreg_hotplug_kind kind)
94104
{
105+
struct i2c_board_info *brdinfo = data->hpdev.brdinfo;
95106
struct mlxreg_core_hotplug_platform_data *pdata;
96107
struct i2c_client *client;
97108

@@ -106,46 +117,88 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
106117
return 0;
107118

108119
pdata = dev_get_platdata(&priv->pdev->dev);
109-
data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr +
110-
pdata->shift_nr);
111-
if (!data->hpdev.adapter) {
112-
dev_err(priv->dev, "Failed to get adapter for bus %d\n",
113-
data->hpdev.nr + pdata->shift_nr);
114-
return -EFAULT;
115-
}
120+
switch (data->hpdev.action) {
121+
case MLXREG_HOTPLUG_DEVICE_DEFAULT_ACTION:
122+
data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr +
123+
pdata->shift_nr);
124+
if (!data->hpdev.adapter) {
125+
dev_err(priv->dev, "Failed to get adapter for bus %d\n",
126+
data->hpdev.nr + pdata->shift_nr);
127+
return -EFAULT;
128+
}
116129

117-
client = i2c_new_client_device(data->hpdev.adapter,
118-
data->hpdev.brdinfo);
119-
if (IS_ERR(client)) {
120-
dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
121-
data->hpdev.brdinfo->type, data->hpdev.nr +
122-
pdata->shift_nr, data->hpdev.brdinfo->addr);
130+
/* Export platform data to underlying device. */
131+
if (brdinfo->platform_data)
132+
mlxreg_hotplug_pdata_export(brdinfo->platform_data, pdata->regmap);
123133

124-
i2c_put_adapter(data->hpdev.adapter);
125-
data->hpdev.adapter = NULL;
126-
return PTR_ERR(client);
134+
client = i2c_new_client_device(data->hpdev.adapter,
135+
brdinfo);
136+
if (IS_ERR(client)) {
137+
dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
138+
brdinfo->type, data->hpdev.nr +
139+
pdata->shift_nr, brdinfo->addr);
140+
141+
i2c_put_adapter(data->hpdev.adapter);
142+
data->hpdev.adapter = NULL;
143+
return PTR_ERR(client);
144+
}
145+
146+
data->hpdev.client = client;
147+
break;
148+
case MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION:
149+
/* Export platform data to underlying device. */
150+
if (data->hpdev.brdinfo && data->hpdev.brdinfo->platform_data)
151+
mlxreg_hotplug_pdata_export(data->hpdev.brdinfo->platform_data,
152+
pdata->regmap);
153+
/* Pass parent hotplug device handle to underlying device. */
154+
data->notifier = data->hpdev.notifier;
155+
data->hpdev.pdev = platform_device_register_resndata(&priv->pdev->dev,
156+
brdinfo->type,
157+
data->hpdev.nr,
158+
NULL, 0, data,
159+
sizeof(*data));
160+
if (IS_ERR(data->hpdev.pdev))
161+
return PTR_ERR(data->hpdev.pdev);
162+
163+
break;
164+
default:
165+
break;
127166
}
128167

129-
data->hpdev.client = client;
168+
if (data->hpdev.notifier && data->hpdev.notifier->user_handler)
169+
return data->hpdev.notifier->user_handler(data->hpdev.notifier->handle, kind, 1);
130170

131171
return 0;
132172
}
133173

134174
static void
135175
mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv,
136-
struct mlxreg_core_data *data)
176+
struct mlxreg_core_data *data,
177+
enum mlxreg_hotplug_kind kind)
137178
{
138179
/* Notify user by sending hwmon uevent. */
139180
mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, false);
181+
if (data->hpdev.notifier && data->hpdev.notifier->user_handler)
182+
data->hpdev.notifier->user_handler(data->hpdev.notifier->handle, kind, 0);
183+
184+
switch (data->hpdev.action) {
185+
case MLXREG_HOTPLUG_DEVICE_DEFAULT_ACTION:
186+
if (data->hpdev.client) {
187+
i2c_unregister_device(data->hpdev.client);
188+
data->hpdev.client = NULL;
189+
}
140190

141-
if (data->hpdev.client) {
142-
i2c_unregister_device(data->hpdev.client);
143-
data->hpdev.client = NULL;
144-
}
145-
146-
if (data->hpdev.adapter) {
147-
i2c_put_adapter(data->hpdev.adapter);
148-
data->hpdev.adapter = NULL;
191+
if (data->hpdev.adapter) {
192+
i2c_put_adapter(data->hpdev.adapter);
193+
data->hpdev.adapter = NULL;
194+
}
195+
break;
196+
case MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION:
197+
if (data->hpdev.pdev)
198+
platform_device_unregister(data->hpdev.pdev);
199+
break;
200+
default:
201+
break;
149202
}
150203
}
151204

@@ -317,14 +370,14 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
317370
data = item->data + bit;
318371
if (regval & BIT(bit)) {
319372
if (item->inversed)
320-
mlxreg_hotplug_device_destroy(priv, data);
373+
mlxreg_hotplug_device_destroy(priv, data, item->kind);
321374
else
322-
mlxreg_hotplug_device_create(priv, data);
375+
mlxreg_hotplug_device_create(priv, data, item->kind);
323376
} else {
324377
if (item->inversed)
325-
mlxreg_hotplug_device_create(priv, data);
378+
mlxreg_hotplug_device_create(priv, data, item->kind);
326379
else
327-
mlxreg_hotplug_device_destroy(priv, data);
380+
mlxreg_hotplug_device_destroy(priv, data, item->kind);
328381
}
329382
}
330383

@@ -381,7 +434,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
381434
* ASIC is in steady state. Connect associated
382435
* device, if configured.
383436
*/
384-
mlxreg_hotplug_device_create(priv, data);
437+
mlxreg_hotplug_device_create(priv, data, item->kind);
385438
data->attached = true;
386439
}
387440
} else {
@@ -391,7 +444,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
391444
* in steady state. Disconnect associated
392445
* device, if it has been connected.
393446
*/
394-
mlxreg_hotplug_device_destroy(priv, data);
447+
mlxreg_hotplug_device_destroy(priv, data, item->kind);
395448
data->attached = false;
396449
data->health_cntr = 0;
397450
}
@@ -630,7 +683,7 @@ static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
630683
/* Remove all the attached devices in group. */
631684
count = item->count;
632685
for (j = 0; j < count; j++, data++)
633-
mlxreg_hotplug_device_destroy(priv, data);
686+
mlxreg_hotplug_device_destroy(priv, data, item->kind);
634687
}
635688
}
636689

include/linux/platform_data/mlxreg.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,31 @@ enum mlxreg_hotplug_device_action {
6969
MLXREG_HOTPLUG_DEVICE_NO_ACTION = 2,
7070
};
7171

72+
/**
73+
* struct mlxreg_core_hotplug_notifier - hotplug notifier block:
74+
*
75+
* @identity: notifier identity name;
76+
* @handle: user handle to be passed by user handler function;
77+
* @user_handler: user handler function associated with the event;
78+
*/
79+
struct mlxreg_core_hotplug_notifier {
80+
char identity[MLXREG_CORE_LABEL_MAX_SIZE];
81+
void *handle;
82+
int (*user_handler)(void *handle, enum mlxreg_hotplug_kind kind, u8 action);
83+
};
84+
7285
/**
7386
* struct mlxreg_hotplug_device - I2C device data:
7487
*
7588
* @adapter: I2C device adapter;
7689
* @client: I2C device client;
7790
* @brdinfo: device board information;
7891
* @nr: I2C device adapter number, to which device is to be attached;
92+
* @pdev: platform device, if device is instantiated as a platform device;
7993
* @action: action to be performed upon event receiving;
94+
* @handle: user handle to be passed by user handler function;
95+
* @user_handler: user handler function associated with the event;
96+
* @notifier: pointer to event notifier block;
8097
*
8198
* Structure represents I2C hotplug device static data (board topology) and
8299
* dynamic data (related kernel objects handles).
@@ -86,7 +103,11 @@ struct mlxreg_hotplug_device {
86103
struct i2c_client *client;
87104
struct i2c_board_info *brdinfo;
88105
int nr;
106+
struct platform_device *pdev;
89107
enum mlxreg_hotplug_device_action action;
108+
void *handle;
109+
int (*user_handler)(void *handle, enum mlxreg_hotplug_kind kind, u8 action);
110+
struct mlxreg_core_hotplug_notifier *notifier;
90111
};
91112

92113
/**
@@ -104,10 +125,12 @@ struct mlxreg_hotplug_device {
104125
* @mode: access mode;
105126
* @np - pointer to node platform associated with attribute;
106127
* @hpdev - hotplug device data;
128+
* @notifier: pointer to event notifier block;
107129
* @health_cntr: dynamic device health indication counter;
108130
* @attached: true if device has been attached after good health indication;
109131
* @regnum: number of registers occupied by multi-register attribute;
110132
* @slot: slot number, at which device is located;
133+
* @secured: if set indicates that entry access is secured;
111134
*/
112135
struct mlxreg_core_data {
113136
char label[MLXREG_CORE_LABEL_MAX_SIZE];
@@ -122,6 +145,7 @@ struct mlxreg_core_data {
122145
umode_t mode;
123146
struct device_node *np;
124147
struct mlxreg_hotplug_device hpdev;
148+
struct mlxreg_core_hotplug_notifier *notifier;
125149
u32 health_cntr;
126150
bool attached;
127151
u8 regnum;

0 commit comments

Comments
 (0)