hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/pci/hotplug/pciehp_ctrl.c
....@@ -13,24 +13,29 @@
1313 *
1414 */
1515
16
-#include <linux/module.h>
16
+#define dev_fmt(fmt) "pciehp: " fmt
17
+
1718 #include <linux/kernel.h>
1819 #include <linux/types.h>
19
-#include <linux/slab.h>
2020 #include <linux/pm_runtime.h>
2121 #include <linux/pci.h>
22
-#include "../pci.h"
2322 #include "pciehp.h"
2423
2524 /* The following routines constitute the bulk of the
2625 hotplug controller logic
2726 */
2827
29
-static void set_slot_off(struct controller *ctrl, struct slot *pslot)
28
+#define SAFE_REMOVAL true
29
+#define SURPRISE_REMOVAL false
30
+
31
+static void set_slot_off(struct controller *ctrl)
3032 {
31
- /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
33
+ /*
34
+ * Turn off slot, turn on attention indicator, turn off power
35
+ * indicator
36
+ */
3237 if (POWER_CTRL(ctrl)) {
33
- pciehp_power_off_slot(pslot);
38
+ pciehp_power_off_slot(ctrl);
3439
3540 /*
3641 * After turning power off, we must wait for at least 1 second
....@@ -40,47 +45,45 @@
4045 msleep(1000);
4146 }
4247
43
- pciehp_green_led_off(pslot);
44
- pciehp_set_attention_status(pslot, 1);
48
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
49
+ PCI_EXP_SLTCTL_ATTN_IND_ON);
4550 }
4651
4752 /**
4853 * board_added - Called after a board has been added to the system.
49
- * @p_slot: &slot where board is added
54
+ * @ctrl: PCIe hotplug controller where board is added
5055 *
5156 * Turns power on for the board.
5257 * Configures board.
5358 */
54
-static int board_added(struct slot *p_slot)
59
+static int board_added(struct controller *ctrl)
5560 {
5661 int retval = 0;
57
- struct controller *ctrl = p_slot->ctrl;
5862 struct pci_bus *parent = ctrl->pcie->port->subordinate;
5963
6064 if (POWER_CTRL(ctrl)) {
6165 /* Power on slot */
62
- retval = pciehp_power_on_slot(p_slot);
66
+ retval = pciehp_power_on_slot(ctrl);
6367 if (retval)
6468 return retval;
6569 }
6670
67
- pciehp_green_led_blink(p_slot);
71
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK,
72
+ INDICATOR_NOOP);
6873
6974 /* Check link training status */
7075 retval = pciehp_check_link_status(ctrl);
71
- if (retval) {
72
- ctrl_err(ctrl, "Failed to check link status\n");
76
+ if (retval)
7377 goto err_exit;
74
- }
7578
7679 /* Check for a power fault */
77
- if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
78
- ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(p_slot));
80
+ if (ctrl->power_fault_detected || pciehp_query_power_fault(ctrl)) {
81
+ ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl));
7982 retval = -EIO;
8083 goto err_exit;
8184 }
8285
83
- retval = pciehp_configure_device(p_slot);
86
+ retval = pciehp_configure_device(ctrl);
8487 if (retval) {
8588 if (retval != -EEXIST) {
8689 ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
....@@ -89,27 +92,26 @@
8992 }
9093 }
9194
92
- pciehp_green_led_on(p_slot);
93
- pciehp_set_attention_status(p_slot, 0);
95
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON,
96
+ PCI_EXP_SLTCTL_ATTN_IND_OFF);
9497 return 0;
9598
9699 err_exit:
97
- set_slot_off(ctrl, p_slot);
100
+ set_slot_off(ctrl);
98101 return retval;
99102 }
100103
101104 /**
102
- * remove_board - Turns off slot and LEDs
103
- * @p_slot: slot where board is being removed
105
+ * remove_board - Turn off slot and Power Indicator
106
+ * @ctrl: PCIe hotplug controller where board is being removed
107
+ * @safe_removal: whether the board is safely removed (versus surprise removed)
104108 */
105
-static void remove_board(struct slot *p_slot)
109
+static void remove_board(struct controller *ctrl, bool safe_removal)
106110 {
107
- struct controller *ctrl = p_slot->ctrl;
108
-
109
- pciehp_unconfigure_device(p_slot);
111
+ pciehp_unconfigure_device(ctrl, safe_removal);
110112
111113 if (POWER_CTRL(ctrl)) {
112
- pciehp_power_off_slot(p_slot);
114
+ pciehp_power_off_slot(ctrl);
113115
114116 /*
115117 * After turning power off, we must wait for at least 1 second
....@@ -123,12 +125,12 @@
123125 &ctrl->pending_events);
124126 }
125127
126
- /* turn off Green LED */
127
- pciehp_green_led_off(p_slot);
128
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
129
+ INDICATOR_NOOP);
128130 }
129131
130
-static int pciehp_enable_slot(struct slot *slot);
131
-static int pciehp_disable_slot(struct slot *slot);
132
+static int pciehp_enable_slot(struct controller *ctrl);
133
+static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal);
132134
133135 void pciehp_request(struct controller *ctrl, int action)
134136 {
....@@ -139,11 +141,11 @@
139141
140142 void pciehp_queue_pushbutton_work(struct work_struct *work)
141143 {
142
- struct slot *p_slot = container_of(work, struct slot, work.work);
143
- struct controller *ctrl = p_slot->ctrl;
144
+ struct controller *ctrl = container_of(work, struct controller,
145
+ button_work.work);
144146
145
- mutex_lock(&p_slot->lock);
146
- switch (p_slot->state) {
147
+ mutex_lock(&ctrl->state_lock);
148
+ switch (ctrl->state) {
147149 case BLINKINGOFF_STATE:
148150 pciehp_request(ctrl, DISABLE_SLOT);
149151 break;
....@@ -153,30 +155,28 @@
153155 default:
154156 break;
155157 }
156
- mutex_unlock(&p_slot->lock);
158
+ mutex_unlock(&ctrl->state_lock);
157159 }
158160
159
-void pciehp_handle_button_press(struct slot *p_slot)
161
+void pciehp_handle_button_press(struct controller *ctrl)
160162 {
161
- struct controller *ctrl = p_slot->ctrl;
162
-
163
- mutex_lock(&p_slot->lock);
164
- switch (p_slot->state) {
163
+ mutex_lock(&ctrl->state_lock);
164
+ switch (ctrl->state) {
165165 case OFF_STATE:
166166 case ON_STATE:
167
- if (p_slot->state == ON_STATE) {
168
- p_slot->state = BLINKINGOFF_STATE;
167
+ if (ctrl->state == ON_STATE) {
168
+ ctrl->state = BLINKINGOFF_STATE;
169169 ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n",
170
- slot_name(p_slot));
170
+ slot_name(ctrl));
171171 } else {
172
- p_slot->state = BLINKINGON_STATE;
172
+ ctrl->state = BLINKINGON_STATE;
173173 ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n",
174
- slot_name(p_slot));
174
+ slot_name(ctrl));
175175 }
176
- /* blink green LED and turn off amber */
177
- pciehp_green_led_blink(p_slot);
178
- pciehp_set_attention_status(p_slot, 0);
179
- schedule_delayed_work(&p_slot->work, 5 * HZ);
176
+ /* blink power indicator and turn off attention */
177
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK,
178
+ PCI_EXP_SLTCTL_ATTN_IND_OFF);
179
+ schedule_delayed_work(&ctrl->button_work, 5 * HZ);
180180 break;
181181 case BLINKINGOFF_STATE:
182182 case BLINKINGON_STATE:
....@@ -185,197 +185,187 @@
185185 * press the attention again before the 5 sec. limit
186186 * expires to cancel hot-add or hot-remove
187187 */
188
- ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(p_slot));
189
- cancel_delayed_work(&p_slot->work);
190
- if (p_slot->state == BLINKINGOFF_STATE) {
191
- p_slot->state = ON_STATE;
192
- pciehp_green_led_on(p_slot);
188
+ ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(ctrl));
189
+ cancel_delayed_work(&ctrl->button_work);
190
+ if (ctrl->state == BLINKINGOFF_STATE) {
191
+ ctrl->state = ON_STATE;
192
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON,
193
+ PCI_EXP_SLTCTL_ATTN_IND_OFF);
193194 } else {
194
- p_slot->state = OFF_STATE;
195
- pciehp_green_led_off(p_slot);
195
+ ctrl->state = OFF_STATE;
196
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
197
+ PCI_EXP_SLTCTL_ATTN_IND_OFF);
196198 }
197
- pciehp_set_attention_status(p_slot, 0);
198199 ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n",
199
- slot_name(p_slot));
200
+ slot_name(ctrl));
200201 break;
201202 default:
202203 ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n",
203
- slot_name(p_slot), p_slot->state);
204
+ slot_name(ctrl), ctrl->state);
204205 break;
205206 }
206
- mutex_unlock(&p_slot->lock);
207
+ mutex_unlock(&ctrl->state_lock);
207208 }
208209
209
-void pciehp_handle_disable_request(struct slot *slot)
210
+void pciehp_handle_disable_request(struct controller *ctrl)
210211 {
211
- struct controller *ctrl = slot->ctrl;
212
-
213
- mutex_lock(&slot->lock);
214
- switch (slot->state) {
212
+ mutex_lock(&ctrl->state_lock);
213
+ switch (ctrl->state) {
215214 case BLINKINGON_STATE:
216215 case BLINKINGOFF_STATE:
217
- cancel_delayed_work(&slot->work);
216
+ cancel_delayed_work(&ctrl->button_work);
218217 break;
219218 }
220
- slot->state = POWEROFF_STATE;
221
- mutex_unlock(&slot->lock);
219
+ ctrl->state = POWEROFF_STATE;
220
+ mutex_unlock(&ctrl->state_lock);
222221
223
- ctrl->request_result = pciehp_disable_slot(slot);
222
+ ctrl->request_result = pciehp_disable_slot(ctrl, SAFE_REMOVAL);
224223 }
225224
226
-void pciehp_handle_presence_or_link_change(struct slot *slot, u32 events)
225
+void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
227226 {
228
- struct controller *ctrl = slot->ctrl;
229
- bool link_active;
230
- u8 present;
227
+ int present, link_active;
231228
232229 /*
233230 * If the slot is on and presence or link has changed, turn it off.
234231 * Even if it's occupied again, we cannot assume the card is the same.
235232 */
236
- mutex_lock(&slot->lock);
237
- switch (slot->state) {
233
+ mutex_lock(&ctrl->state_lock);
234
+ switch (ctrl->state) {
238235 case BLINKINGOFF_STATE:
239
- cancel_delayed_work(&slot->work);
240
- /* fall through */
236
+ cancel_delayed_work(&ctrl->button_work);
237
+ fallthrough;
241238 case ON_STATE:
242
- slot->state = POWEROFF_STATE;
243
- mutex_unlock(&slot->lock);
239
+ ctrl->state = POWEROFF_STATE;
240
+ mutex_unlock(&ctrl->state_lock);
244241 if (events & PCI_EXP_SLTSTA_DLLSC)
245242 ctrl_info(ctrl, "Slot(%s): Link Down\n",
246
- slot_name(slot));
243
+ slot_name(ctrl));
247244 if (events & PCI_EXP_SLTSTA_PDC)
248245 ctrl_info(ctrl, "Slot(%s): Card not present\n",
249
- slot_name(slot));
250
- pciehp_disable_slot(slot);
246
+ slot_name(ctrl));
247
+ pciehp_disable_slot(ctrl, SURPRISE_REMOVAL);
251248 break;
252249 default:
253
- mutex_unlock(&slot->lock);
250
+ mutex_unlock(&ctrl->state_lock);
254251 break;
255252 }
256253
257254 /* Turn the slot on if it's occupied or link is up */
258
- mutex_lock(&slot->lock);
259
- pciehp_get_adapter_status(slot, &present);
255
+ mutex_lock(&ctrl->state_lock);
256
+ present = pciehp_card_present(ctrl);
260257 link_active = pciehp_check_link_active(ctrl);
261
- if (!present && !link_active) {
262
- mutex_unlock(&slot->lock);
258
+ if (present <= 0 && link_active <= 0) {
259
+ mutex_unlock(&ctrl->state_lock);
263260 return;
264261 }
265262
266
- switch (slot->state) {
263
+ switch (ctrl->state) {
267264 case BLINKINGON_STATE:
268
- cancel_delayed_work(&slot->work);
269
- /* fall through */
265
+ cancel_delayed_work(&ctrl->button_work);
266
+ fallthrough;
270267 case OFF_STATE:
271
- slot->state = POWERON_STATE;
272
- mutex_unlock(&slot->lock);
268
+ ctrl->state = POWERON_STATE;
269
+ mutex_unlock(&ctrl->state_lock);
273270 if (present)
274271 ctrl_info(ctrl, "Slot(%s): Card present\n",
275
- slot_name(slot));
272
+ slot_name(ctrl));
276273 if (link_active)
277274 ctrl_info(ctrl, "Slot(%s): Link Up\n",
278
- slot_name(slot));
279
- ctrl->request_result = pciehp_enable_slot(slot);
275
+ slot_name(ctrl));
276
+ ctrl->request_result = pciehp_enable_slot(ctrl);
280277 break;
281278 default:
282
- mutex_unlock(&slot->lock);
279
+ mutex_unlock(&ctrl->state_lock);
283280 break;
284281 }
285282 }
286283
287
-static int __pciehp_enable_slot(struct slot *p_slot)
284
+static int __pciehp_enable_slot(struct controller *ctrl)
288285 {
289286 u8 getstatus = 0;
290
- struct controller *ctrl = p_slot->ctrl;
291287
292
- pciehp_get_adapter_status(p_slot, &getstatus);
293
- if (!getstatus) {
294
- ctrl_info(ctrl, "Slot(%s): No adapter\n", slot_name(p_slot));
295
- return -ENODEV;
296
- }
297
- if (MRL_SENS(p_slot->ctrl)) {
298
- pciehp_get_latch_status(p_slot, &getstatus);
288
+ if (MRL_SENS(ctrl)) {
289
+ pciehp_get_latch_status(ctrl, &getstatus);
299290 if (getstatus) {
300291 ctrl_info(ctrl, "Slot(%s): Latch open\n",
301
- slot_name(p_slot));
292
+ slot_name(ctrl));
302293 return -ENODEV;
303294 }
304295 }
305296
306
- if (POWER_CTRL(p_slot->ctrl)) {
307
- pciehp_get_power_status(p_slot, &getstatus);
297
+ if (POWER_CTRL(ctrl)) {
298
+ pciehp_get_power_status(ctrl, &getstatus);
308299 if (getstatus) {
309300 ctrl_info(ctrl, "Slot(%s): Already enabled\n",
310
- slot_name(p_slot));
301
+ slot_name(ctrl));
311302 return 0;
312303 }
313304 }
314305
315
- return board_added(p_slot);
306
+ return board_added(ctrl);
316307 }
317308
318
-static int pciehp_enable_slot(struct slot *slot)
309
+static int pciehp_enable_slot(struct controller *ctrl)
319310 {
320
- struct controller *ctrl = slot->ctrl;
321311 int ret;
322312
323313 pm_runtime_get_sync(&ctrl->pcie->port->dev);
324
- ret = __pciehp_enable_slot(slot);
314
+ ret = __pciehp_enable_slot(ctrl);
325315 if (ret && ATTN_BUTTN(ctrl))
326
- pciehp_green_led_off(slot); /* may be blinking */
316
+ /* may be blinking */
317
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
318
+ INDICATOR_NOOP);
327319 pm_runtime_put(&ctrl->pcie->port->dev);
328320
329
- mutex_lock(&slot->lock);
330
- slot->state = ret ? OFF_STATE : ON_STATE;
331
- mutex_unlock(&slot->lock);
321
+ mutex_lock(&ctrl->state_lock);
322
+ ctrl->state = ret ? OFF_STATE : ON_STATE;
323
+ mutex_unlock(&ctrl->state_lock);
332324
333325 return ret;
334326 }
335327
336
-static int __pciehp_disable_slot(struct slot *p_slot)
328
+static int __pciehp_disable_slot(struct controller *ctrl, bool safe_removal)
337329 {
338330 u8 getstatus = 0;
339
- struct controller *ctrl = p_slot->ctrl;
340331
341
- if (POWER_CTRL(p_slot->ctrl)) {
342
- pciehp_get_power_status(p_slot, &getstatus);
332
+ if (POWER_CTRL(ctrl)) {
333
+ pciehp_get_power_status(ctrl, &getstatus);
343334 if (!getstatus) {
344335 ctrl_info(ctrl, "Slot(%s): Already disabled\n",
345
- slot_name(p_slot));
336
+ slot_name(ctrl));
346337 return -EINVAL;
347338 }
348339 }
349340
350
- remove_board(p_slot);
341
+ remove_board(ctrl, safe_removal);
351342 return 0;
352343 }
353344
354
-static int pciehp_disable_slot(struct slot *slot)
345
+static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal)
355346 {
356
- struct controller *ctrl = slot->ctrl;
357347 int ret;
358348
359349 pm_runtime_get_sync(&ctrl->pcie->port->dev);
360
- ret = __pciehp_disable_slot(slot);
350
+ ret = __pciehp_disable_slot(ctrl, safe_removal);
361351 pm_runtime_put(&ctrl->pcie->port->dev);
362352
363
- mutex_lock(&slot->lock);
364
- slot->state = OFF_STATE;
365
- mutex_unlock(&slot->lock);
353
+ mutex_lock(&ctrl->state_lock);
354
+ ctrl->state = OFF_STATE;
355
+ mutex_unlock(&ctrl->state_lock);
366356
367357 return ret;
368358 }
369359
370
-int pciehp_sysfs_enable_slot(struct slot *p_slot)
360
+int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot)
371361 {
372
- struct controller *ctrl = p_slot->ctrl;
362
+ struct controller *ctrl = to_ctrl(hotplug_slot);
373363
374
- mutex_lock(&p_slot->lock);
375
- switch (p_slot->state) {
364
+ mutex_lock(&ctrl->state_lock);
365
+ switch (ctrl->state) {
376366 case BLINKINGON_STATE:
377367 case OFF_STATE:
378
- mutex_unlock(&p_slot->lock);
368
+ mutex_unlock(&ctrl->state_lock);
379369 /*
380370 * The IRQ thread becomes a no-op if the user pulls out the
381371 * card before the thread wakes up, so initialize to -ENODEV.
....@@ -388,33 +378,33 @@
388378 return ctrl->request_result;
389379 case POWERON_STATE:
390380 ctrl_info(ctrl, "Slot(%s): Already in powering on state\n",
391
- slot_name(p_slot));
381
+ slot_name(ctrl));
392382 break;
393383 case BLINKINGOFF_STATE:
394384 case ON_STATE:
395385 case POWEROFF_STATE:
396386 ctrl_info(ctrl, "Slot(%s): Already enabled\n",
397
- slot_name(p_slot));
387
+ slot_name(ctrl));
398388 break;
399389 default:
400390 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
401
- slot_name(p_slot), p_slot->state);
391
+ slot_name(ctrl), ctrl->state);
402392 break;
403393 }
404
- mutex_unlock(&p_slot->lock);
394
+ mutex_unlock(&ctrl->state_lock);
405395
406396 return -ENODEV;
407397 }
408398
409
-int pciehp_sysfs_disable_slot(struct slot *p_slot)
399
+int pciehp_sysfs_disable_slot(struct hotplug_slot *hotplug_slot)
410400 {
411
- struct controller *ctrl = p_slot->ctrl;
401
+ struct controller *ctrl = to_ctrl(hotplug_slot);
412402
413
- mutex_lock(&p_slot->lock);
414
- switch (p_slot->state) {
403
+ mutex_lock(&ctrl->state_lock);
404
+ switch (ctrl->state) {
415405 case BLINKINGOFF_STATE:
416406 case ON_STATE:
417
- mutex_unlock(&p_slot->lock);
407
+ mutex_unlock(&ctrl->state_lock);
418408 pciehp_request(ctrl, DISABLE_SLOT);
419409 wait_event(ctrl->requester,
420410 !atomic_read(&ctrl->pending_events) &&
....@@ -422,20 +412,20 @@
422412 return ctrl->request_result;
423413 case POWEROFF_STATE:
424414 ctrl_info(ctrl, "Slot(%s): Already in powering off state\n",
425
- slot_name(p_slot));
415
+ slot_name(ctrl));
426416 break;
427417 case BLINKINGON_STATE:
428418 case OFF_STATE:
429419 case POWERON_STATE:
430420 ctrl_info(ctrl, "Slot(%s): Already disabled\n",
431
- slot_name(p_slot));
421
+ slot_name(ctrl));
432422 break;
433423 default:
434424 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
435
- slot_name(p_slot), p_slot->state);
425
+ slot_name(ctrl), ctrl->state);
436426 break;
437427 }
438
- mutex_unlock(&p_slot->lock);
428
+ mutex_unlock(&ctrl->state_lock);
439429
440430 return -ENODEV;
441431 }