History

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.

Vadim Pasternak committed 5 years ago

Commit bb1023b1 parent a5d8f572 files · +112 −35Browse files

Unified · Split

2 files
  1. drivers/platform/mellanox/mlxreg-hotplug.c +88 −35
  2. include/linux/platform_data/mlxreg.h +24 −0
drivers/platform/mellanox/mlxreg-hotplug.c+88−35
@@ -28,7 +28,7 @@ · 27 unmodified lines
28/* ASIC good health mask. */28/* ASIC good health mask. */
29#define MLXREG_HOTPLUG_GOOD_HEALTH_MASK 0x0229#define MLXREG_HOTPLUG_GOOD_HEALTH_MASK 0x02
30 30
31#define MLXREG_HOTPLUG_ATTRS_MAX 2431#define MLXREG_HOTPLUG_ATTRS_MAX 128
32#define MLXREG_HOTPLUG_NOT_ASSERT 332#define MLXREG_HOTPLUG_NOT_ASSERT 3
33 33
34/**34/**
@@ -89,9 +89,20 @@ mlxreg_hotplug_udev_event_send(struct kobject *kobj, · 54 unmodified lines
89 return kobject_uevent_env(kobj, KOBJ_CHANGE, mlxreg_hotplug_udev_envp);89 return kobject_uevent_env(kobj, KOBJ_CHANGE, mlxreg_hotplug_udev_envp);
90}90}
91 91
92static void
93mlxreg_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
92static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,101static 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)
94{104{
105 struct i2c_board_info *brdinfo = data->hpdev.brdinfo;
95 struct mlxreg_core_hotplug_platform_data *pdata;106 struct mlxreg_core_hotplug_platform_data *pdata;
96 struct i2c_client *client;107 struct i2c_client *client;
97 108
@@ -106,46 +117,88 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, · 8 unmodified lines
106 return 0;117 return 0;
107 118
108 pdata = dev_get_platdata(&priv->pdev->dev);119 pdata = dev_get_platdata(&priv->pdev->dev);
109 data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr +120 switch (data->hpdev.action) {
110 pdata->shift_nr);121 case MLXREG_HOTPLUG_DEVICE_DEFAULT_ACTION:
111 if (!data->hpdev.adapter) {122 data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr +
112 dev_err(priv->dev, "Failed to get adapter for bus %d\n",123 pdata->shift_nr);
113 data->hpdev.nr + pdata->shift_nr);124 if (!data->hpdev.adapter) {
114 return -EFAULT;125 dev_err(priv->dev, "Failed to get adapter for bus %d\n",
115 }126 data->hpdev.nr + pdata->shift_nr);
127 return -EFAULT;
128 }
116 129
117 client = i2c_new_client_device(data->hpdev.adapter,130 /* Export platform data to underlying device. */
118 data->hpdev.brdinfo);131 if (brdinfo->platform_data)
119 if (IS_ERR(client)) {132 mlxreg_hotplug_pdata_export(brdinfo->platform_data, pdata->regmap);
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);
123 133
124 i2c_put_adapter(data->hpdev.adapter);134 client = i2c_new_client_device(data->hpdev.adapter,
125 data->hpdev.adapter = NULL;135 brdinfo);
126 return PTR_ERR(client);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;
127 }166 }
128 167
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);
130 170
131 return 0;171 return 0;
132}172}
133 173
134static void174static void
135mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv,175mlxreg_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)
137{178{
138 /* Notify user by sending hwmon uevent. */179 /* Notify user by sending hwmon uevent. */
139 mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, false);180 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 }
140 190
141 if (data->hpdev.client) {191 if (data->hpdev.adapter) {
142 i2c_unregister_device(data->hpdev.client);192 i2c_put_adapter(data->hpdev.adapter);
143 data->hpdev.client = NULL;193 data->hpdev.adapter = NULL;
144 }194 }
145 195 break;
146 if (data->hpdev.adapter) {196 case MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION:
147 i2c_put_adapter(data->hpdev.adapter);197 if (data->hpdev.pdev)
148 data->hpdev.adapter = NULL;198 platform_device_unregister(data->hpdev.pdev);
199 break;
200 default:
201 break;
149 }202 }
150}203}
151 204
@@ -317,14 +370,14 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv, · 165 unmodified lines
317 data = item->data + bit;370 data = item->data + bit;
318 if (regval & BIT(bit)) {371 if (regval & BIT(bit)) {
319 if (item->inversed)372 if (item->inversed)
320 mlxreg_hotplug_device_destroy(priv, data);373 mlxreg_hotplug_device_destroy(priv, data, item->kind);
321 else374 else
322 mlxreg_hotplug_device_create(priv, data);375 mlxreg_hotplug_device_create(priv, data, item->kind);
323 } else {376 } else {
324 if (item->inversed)377 if (item->inversed)
325 mlxreg_hotplug_device_create(priv, data);378 mlxreg_hotplug_device_create(priv, data, item->kind);
326 else379 else
327 mlxreg_hotplug_device_destroy(priv, data);380 mlxreg_hotplug_device_destroy(priv, data, item->kind);
328 }381 }
329 }382 }
330 383
@@ -381,7 +434,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv, · 50 unmodified lines
381 * ASIC is in steady state. Connect associated434 * ASIC is in steady state. Connect associated
382 * device, if configured.435 * device, if configured.
383 */436 */
384 mlxreg_hotplug_device_create(priv, data);437 mlxreg_hotplug_device_create(priv, data, item->kind);
385 data->attached = true;438 data->attached = true;
386 }439 }
387 } else {440 } else {
@@ -391,7 +444,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv, · 3 unmodified lines
391 * in steady state. Disconnect associated444 * in steady state. Disconnect associated
392 * device, if it has been connected.445 * device, if it has been connected.
393 */446 */
394 mlxreg_hotplug_device_destroy(priv, data);447 mlxreg_hotplug_device_destroy(priv, data, item->kind);
395 data->attached = false;448 data->attached = false;
396 data->health_cntr = 0;449 data->health_cntr = 0;
397 }450 }
@@ -630,7 +683,7 @@ static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv) · 232 unmodified lines
630 /* Remove all the attached devices in group. */683 /* Remove all the attached devices in group. */
631 count = item->count;684 count = item->count;
632 for (j = 0; j < count; j++, data++)685 for (j = 0; j < count; j++, data++)
633 mlxreg_hotplug_device_destroy(priv, data);686 mlxreg_hotplug_device_destroy(priv, data, item->kind);
634 }687 }
635}688}
636 689
include/linux/platform_data/mlxreg.h+24−0
@@ -69,6 +69,19 @@ enum mlxreg_hotplug_device_action { · 68 unmodified lines
69 MLXREG_HOTPLUG_DEVICE_NO_ACTION = 2,69 MLXREG_HOTPLUG_DEVICE_NO_ACTION = 2,
70};70};
71 71
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 */
79struct 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
72/**85/**
73 * struct mlxreg_hotplug_device - I2C device data:86 * struct mlxreg_hotplug_device - I2C device data:
74 *87 *
@@ -76,7 +89,11 @@ enum mlxreg_hotplug_device_action { · 1 unmodified line
76 * @client: I2C device client;89 * @client: I2C device client;
77 * @brdinfo: device board information;90 * @brdinfo: device board information;
78 * @nr: I2C device adapter number, to which device is to be attached;91 * @nr: I2C device adapter number, to which device is to be attached;
92 * @pdev: platform device, if device is instantiated as a platform device;
79 * @action: action to be performed upon event receiving;93 * @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;
80 *97 *
81 * Structure represents I2C hotplug device static data (board topology) and98 * Structure represents I2C hotplug device static data (board topology) and
82 * dynamic data (related kernel objects handles).99 * dynamic data (related kernel objects handles).
@@ -86,7 +103,11 @@ struct mlxreg_hotplug_device { · 3 unmodified lines
86 struct i2c_client *client;103 struct i2c_client *client;
87 struct i2c_board_info *brdinfo;104 struct i2c_board_info *brdinfo;
88 int nr;105 int nr;
106 struct platform_device *pdev;
89 enum mlxreg_hotplug_device_action action;107 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;
90};111};
91 112
92/**113/**
@@ -104,10 +125,12 @@ struct mlxreg_hotplug_device { · 11 unmodified lines
104 * @mode: access mode;125 * @mode: access mode;
105 * @np - pointer to node platform associated with attribute;126 * @np - pointer to node platform associated with attribute;
106 * @hpdev - hotplug device data;127 * @hpdev - hotplug device data;
128 * @notifier: pointer to event notifier block;
107 * @health_cntr: dynamic device health indication counter;129 * @health_cntr: dynamic device health indication counter;
108 * @attached: true if device has been attached after good health indication;130 * @attached: true if device has been attached after good health indication;
109 * @regnum: number of registers occupied by multi-register attribute;131 * @regnum: number of registers occupied by multi-register attribute;
110 * @slot: slot number, at which device is located;132 * @slot: slot number, at which device is located;
133 * @secured: if set indicates that entry access is secured;
111 */134 */
112struct mlxreg_core_data {135struct mlxreg_core_data {
113 char label[MLXREG_CORE_LABEL_MAX_SIZE];136 char label[MLXREG_CORE_LABEL_MAX_SIZE];
@@ -122,6 +145,7 @@ struct mlxreg_core_data { · 8 unmodified lines
122 umode_t mode;145 umode_t mode;
123 struct device_node *np;146 struct device_node *np;
124 struct mlxreg_hotplug_device hpdev;147 struct mlxreg_hotplug_device hpdev;
148 struct mlxreg_core_hotplug_notifier *notifier;
125 u32 health_cntr;149 u32 health_cntr;
126 bool attached;150 bool attached;
127 u8 regnum;151 u8 regnum;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t