hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
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,195 @@
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
+ if (ctrl->state == BLINKINGON_STATE) {
260
+ ctrl->state = OFF_STATE;
261
+ cancel_delayed_work(&ctrl->button_work);
262
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
263
+ INDICATOR_NOOP);
264
+ ctrl_info(ctrl, "Slot(%s): Card not present\n",
265
+ slot_name(ctrl));
266
+ }
267
+ mutex_unlock(&ctrl->state_lock);
263268 return;
264269 }
265270
266
- switch (slot->state) {
271
+ switch (ctrl->state) {
267272 case BLINKINGON_STATE:
268
- cancel_delayed_work(&slot->work);
269
- /* fall through */
273
+ cancel_delayed_work(&ctrl->button_work);
274
+ fallthrough;
270275 case OFF_STATE:
271
- slot->state = POWERON_STATE;
272
- mutex_unlock(&slot->lock);
276
+ ctrl->state = POWERON_STATE;
277
+ mutex_unlock(&ctrl->state_lock);
273278 if (present)
274279 ctrl_info(ctrl, "Slot(%s): Card present\n",
275
- slot_name(slot));
280
+ slot_name(ctrl));
276281 if (link_active)
277282 ctrl_info(ctrl, "Slot(%s): Link Up\n",
278
- slot_name(slot));
279
- ctrl->request_result = pciehp_enable_slot(slot);
283
+ slot_name(ctrl));
284
+ ctrl->request_result = pciehp_enable_slot(ctrl);
280285 break;
281286 default:
282
- mutex_unlock(&slot->lock);
287
+ mutex_unlock(&ctrl->state_lock);
283288 break;
284289 }
285290 }
286291
287
-static int __pciehp_enable_slot(struct slot *p_slot)
292
+static int __pciehp_enable_slot(struct controller *ctrl)
288293 {
289294 u8 getstatus = 0;
290
- struct controller *ctrl = p_slot->ctrl;
291295
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);
296
+ if (MRL_SENS(ctrl)) {
297
+ pciehp_get_latch_status(ctrl, &getstatus);
299298 if (getstatus) {
300299 ctrl_info(ctrl, "Slot(%s): Latch open\n",
301
- slot_name(p_slot));
300
+ slot_name(ctrl));
302301 return -ENODEV;
303302 }
304303 }
305304
306
- if (POWER_CTRL(p_slot->ctrl)) {
307
- pciehp_get_power_status(p_slot, &getstatus);
305
+ if (POWER_CTRL(ctrl)) {
306
+ pciehp_get_power_status(ctrl, &getstatus);
308307 if (getstatus) {
309308 ctrl_info(ctrl, "Slot(%s): Already enabled\n",
310
- slot_name(p_slot));
309
+ slot_name(ctrl));
311310 return 0;
312311 }
313312 }
314313
315
- return board_added(p_slot);
314
+ return board_added(ctrl);
316315 }
317316
318
-static int pciehp_enable_slot(struct slot *slot)
317
+static int pciehp_enable_slot(struct controller *ctrl)
319318 {
320
- struct controller *ctrl = slot->ctrl;
321319 int ret;
322320
323321 pm_runtime_get_sync(&ctrl->pcie->port->dev);
324
- ret = __pciehp_enable_slot(slot);
322
+ ret = __pciehp_enable_slot(ctrl);
325323 if (ret && ATTN_BUTTN(ctrl))
326
- pciehp_green_led_off(slot); /* may be blinking */
324
+ /* may be blinking */
325
+ pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
326
+ INDICATOR_NOOP);
327327 pm_runtime_put(&ctrl->pcie->port->dev);
328328
329
- mutex_lock(&slot->lock);
330
- slot->state = ret ? OFF_STATE : ON_STATE;
331
- mutex_unlock(&slot->lock);
329
+ mutex_lock(&ctrl->state_lock);
330
+ ctrl->state = ret ? OFF_STATE : ON_STATE;
331
+ mutex_unlock(&ctrl->state_lock);
332332
333333 return ret;
334334 }
335335
336
-static int __pciehp_disable_slot(struct slot *p_slot)
336
+static int __pciehp_disable_slot(struct controller *ctrl, bool safe_removal)
337337 {
338338 u8 getstatus = 0;
339
- struct controller *ctrl = p_slot->ctrl;
340339
341
- if (POWER_CTRL(p_slot->ctrl)) {
342
- pciehp_get_power_status(p_slot, &getstatus);
340
+ if (POWER_CTRL(ctrl)) {
341
+ pciehp_get_power_status(ctrl, &getstatus);
343342 if (!getstatus) {
344343 ctrl_info(ctrl, "Slot(%s): Already disabled\n",
345
- slot_name(p_slot));
344
+ slot_name(ctrl));
346345 return -EINVAL;
347346 }
348347 }
349348
350
- remove_board(p_slot);
349
+ remove_board(ctrl, safe_removal);
351350 return 0;
352351 }
353352
354
-static int pciehp_disable_slot(struct slot *slot)
353
+static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal)
355354 {
356
- struct controller *ctrl = slot->ctrl;
357355 int ret;
358356
359357 pm_runtime_get_sync(&ctrl->pcie->port->dev);
360
- ret = __pciehp_disable_slot(slot);
358
+ ret = __pciehp_disable_slot(ctrl, safe_removal);
361359 pm_runtime_put(&ctrl->pcie->port->dev);
362360
363
- mutex_lock(&slot->lock);
364
- slot->state = OFF_STATE;
365
- mutex_unlock(&slot->lock);
361
+ mutex_lock(&ctrl->state_lock);
362
+ ctrl->state = OFF_STATE;
363
+ mutex_unlock(&ctrl->state_lock);
366364
367365 return ret;
368366 }
369367
370
-int pciehp_sysfs_enable_slot(struct slot *p_slot)
368
+int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot)
371369 {
372
- struct controller *ctrl = p_slot->ctrl;
370
+ struct controller *ctrl = to_ctrl(hotplug_slot);
373371
374
- mutex_lock(&p_slot->lock);
375
- switch (p_slot->state) {
372
+ mutex_lock(&ctrl->state_lock);
373
+ switch (ctrl->state) {
376374 case BLINKINGON_STATE:
377375 case OFF_STATE:
378
- mutex_unlock(&p_slot->lock);
376
+ mutex_unlock(&ctrl->state_lock);
379377 /*
380378 * The IRQ thread becomes a no-op if the user pulls out the
381379 * card before the thread wakes up, so initialize to -ENODEV.
....@@ -388,33 +386,33 @@
388386 return ctrl->request_result;
389387 case POWERON_STATE:
390388 ctrl_info(ctrl, "Slot(%s): Already in powering on state\n",
391
- slot_name(p_slot));
389
+ slot_name(ctrl));
392390 break;
393391 case BLINKINGOFF_STATE:
394392 case ON_STATE:
395393 case POWEROFF_STATE:
396394 ctrl_info(ctrl, "Slot(%s): Already enabled\n",
397
- slot_name(p_slot));
395
+ slot_name(ctrl));
398396 break;
399397 default:
400398 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
401
- slot_name(p_slot), p_slot->state);
399
+ slot_name(ctrl), ctrl->state);
402400 break;
403401 }
404
- mutex_unlock(&p_slot->lock);
402
+ mutex_unlock(&ctrl->state_lock);
405403
406404 return -ENODEV;
407405 }
408406
409
-int pciehp_sysfs_disable_slot(struct slot *p_slot)
407
+int pciehp_sysfs_disable_slot(struct hotplug_slot *hotplug_slot)
410408 {
411
- struct controller *ctrl = p_slot->ctrl;
409
+ struct controller *ctrl = to_ctrl(hotplug_slot);
412410
413
- mutex_lock(&p_slot->lock);
414
- switch (p_slot->state) {
411
+ mutex_lock(&ctrl->state_lock);
412
+ switch (ctrl->state) {
415413 case BLINKINGOFF_STATE:
416414 case ON_STATE:
417
- mutex_unlock(&p_slot->lock);
415
+ mutex_unlock(&ctrl->state_lock);
418416 pciehp_request(ctrl, DISABLE_SLOT);
419417 wait_event(ctrl->requester,
420418 !atomic_read(&ctrl->pending_events) &&
....@@ -422,20 +420,20 @@
422420 return ctrl->request_result;
423421 case POWEROFF_STATE:
424422 ctrl_info(ctrl, "Slot(%s): Already in powering off state\n",
425
- slot_name(p_slot));
423
+ slot_name(ctrl));
426424 break;
427425 case BLINKINGON_STATE:
428426 case OFF_STATE:
429427 case POWERON_STATE:
430428 ctrl_info(ctrl, "Slot(%s): Already disabled\n",
431
- slot_name(p_slot));
429
+ slot_name(ctrl));
432430 break;
433431 default:
434432 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
435
- slot_name(p_slot), p_slot->state);
433
+ slot_name(ctrl), ctrl->state);
436434 break;
437435 }
438
- mutex_unlock(&p_slot->lock);
436
+ mutex_unlock(&ctrl->state_lock);
439437
440438 return -ENODEV;
441439 }