aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2016-10-03 10:43:19 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-10-03 10:43:19 -0400
commit64ea3b99d665d0140cdf5047571e65d8ca28d0e6 (patch)
tree59bf503a1a14b88eae8ebe6793cd685eb187be6c
parentfb6b6cc41bed72cbafb0d01ab139a4a5ad673e01 (diff)
parent3161832d58c7f3bf8b190a2887086be0932d8dd3 (diff)
Merge branch 'pci/hotplug' into next
* pci/hotplug: x86/PCI: VMD: Request userspace control of PCIe hotplug indicators PCI: pciehp: Allow exclusive userspace control of indicators PCI: pciehp: Remove useless pciehp_get_latch_status() calls PCI: pciehp: Clean up dmesg "Slot(%s)" messages PCI: pciehp: Remove unnecessary guard PCI: pciehp: Don't re-read Slot Status when handling surprise event PCI: pciehp: Don't re-read Slot Status when queuing hotplug event PCI: pciehp: Process all hotplug events before looking for new ones PCI: pciehp: Return IRQ_NONE when we can't read interrupt status PCI: pciehp: Rename pcie_isr() locals for clarity PCI: pciehp: Clear attention LED on device add
-rw-r--r--arch/x86/include/asm/pci.h14
-rw-r--r--arch/x86/pci/common.c7
-rw-r--r--arch/x86/pci/vmd.c1
-rw-r--r--drivers/pci/hotplug/pciehp.h3
-rw-r--r--drivers/pci/hotplug/pciehp_core.c3
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c84
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c121
-rw-r--r--include/linux/pci.h3
8 files changed, 141 insertions, 95 deletions
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 9ab7507ca1c2..1411dbed5e5e 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -23,6 +23,9 @@ struct pci_sysdata {
23#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN 23#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
24 void *fwnode; /* IRQ domain for MSI assignment */ 24 void *fwnode; /* IRQ domain for MSI assignment */
25#endif 25#endif
26#if IS_ENABLED(CONFIG_VMD)
27 bool vmd_domain; /* True if in Intel VMD domain */
28#endif
26}; 29};
27 30
28extern int pci_routeirq; 31extern int pci_routeirq;
@@ -56,6 +59,17 @@ static inline void *_pci_root_bus_fwnode(struct pci_bus *bus)
56#define pci_root_bus_fwnode _pci_root_bus_fwnode 59#define pci_root_bus_fwnode _pci_root_bus_fwnode
57#endif 60#endif
58 61
62static inline bool is_vmd(struct pci_bus *bus)
63{
64#if IS_ENABLED(CONFIG_VMD)
65 struct pci_sysdata *sd = bus->sysdata;
66
67 return sd->vmd_domain;
68#else
69 return false;
70#endif
71}
72
59/* Can be used to override the logic in pci_scan_bus for skipping 73/* Can be used to override the logic in pci_scan_bus for skipping
60 already-configured bus numbers - to be used for buggy BIOSes 74 already-configured bus numbers - to be used for buggy BIOSes
61 or architectures with incomplete PCI setup by the loader */ 75 or architectures with incomplete PCI setup by the loader */
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 7b6a9d14c8c0..a4fdfa7dcc1b 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -677,6 +677,12 @@ static void set_dma_domain_ops(struct pci_dev *pdev)
677static void set_dma_domain_ops(struct pci_dev *pdev) {} 677static void set_dma_domain_ops(struct pci_dev *pdev) {}
678#endif 678#endif
679 679
680static void set_dev_domain_options(struct pci_dev *pdev)
681{
682 if (is_vmd(pdev->bus))
683 pdev->hotplug_user_indicators = 1;
684}
685
680int pcibios_add_device(struct pci_dev *dev) 686int pcibios_add_device(struct pci_dev *dev)
681{ 687{
682 struct setup_data *data; 688 struct setup_data *data;
@@ -707,6 +713,7 @@ int pcibios_add_device(struct pci_dev *dev)
707 iounmap(data); 713 iounmap(data);
708 } 714 }
709 set_dma_domain_ops(dev); 715 set_dma_domain_ops(dev);
716 set_dev_domain_options(dev);
710 return 0; 717 return 0;
711} 718}
712 719
diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c
index b814ca675131..a021b7b0eb69 100644
--- a/arch/x86/pci/vmd.c
+++ b/arch/x86/pci/vmd.c
@@ -596,6 +596,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
596 .parent = res, 596 .parent = res,
597 }; 597 };
598 598
599 sd->vmd_domain = true;
599 sd->domain = vmd_find_free_domain(); 600 sd->domain = vmd_find_free_domain();
600 if (sd->domain < 0) 601 if (sd->domain < 0)
601 return sd->domain; 602 return sd->domain;
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index e764918641ae..37d70b5ad22f 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -152,6 +152,9 @@ bool pciehp_check_link_active(struct controller *ctrl);
152void pciehp_release_ctrl(struct controller *ctrl); 152void pciehp_release_ctrl(struct controller *ctrl);
153int pciehp_reset_slot(struct slot *slot, int probe); 153int pciehp_reset_slot(struct slot *slot, int probe);
154 154
155int pciehp_set_raw_indicator_status(struct hotplug_slot *h_slot, u8 status);
156int pciehp_get_raw_indicator_status(struct hotplug_slot *h_slot, u8 *status);
157
155static inline const char *slot_name(struct slot *slot) 158static inline const char *slot_name(struct slot *slot)
156{ 159{
157 return hotplug_slot_name(slot->hotplug_slot); 160 return hotplug_slot_name(slot->hotplug_slot);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index fb0f86335158..7d32fa33dcef 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -113,6 +113,9 @@ static int init_slot(struct controller *ctrl)
113 if (ATTN_LED(ctrl)) { 113 if (ATTN_LED(ctrl)) {
114 ops->get_attention_status = get_attention_status; 114 ops->get_attention_status = get_attention_status;
115 ops->set_attention_status = set_attention_status; 115 ops->set_attention_status = set_attention_status;
116 } else if (ctrl->pcie->port->hotplug_user_indicators) {
117 ops->get_attention_status = pciehp_get_raw_indicator_status;
118 ops->set_attention_status = pciehp_set_raw_indicator_status;
116 } 119 }
117 120
118 /* register this slot with the hotplug pci core */ 121 /* register this slot with the hotplug pci core */
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 880978b6d534..efe69e879455 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -106,7 +106,7 @@ static int board_added(struct slot *p_slot)
106 106
107 /* Check for a power fault */ 107 /* Check for a power fault */
108 if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) { 108 if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
109 ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot)); 109 ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(p_slot));
110 retval = -EIO; 110 retval = -EIO;
111 goto err_exit; 111 goto err_exit;
112 } 112 }
@@ -120,6 +120,7 @@ static int board_added(struct slot *p_slot)
120 } 120 }
121 121
122 pciehp_green_led_on(p_slot); 122 pciehp_green_led_on(p_slot);
123 pciehp_set_attention_status(p_slot, 0);
123 return 0; 124 return 0;
124 125
125err_exit: 126err_exit:
@@ -253,11 +254,11 @@ static void handle_button_press_event(struct slot *p_slot)
253 pciehp_get_power_status(p_slot, &getstatus); 254 pciehp_get_power_status(p_slot, &getstatus);
254 if (getstatus) { 255 if (getstatus) {
255 p_slot->state = BLINKINGOFF_STATE; 256 p_slot->state = BLINKINGOFF_STATE;
256 ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n", 257 ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n",
257 slot_name(p_slot)); 258 slot_name(p_slot));
258 } else { 259 } else {
259 p_slot->state = BLINKINGON_STATE; 260 p_slot->state = BLINKINGON_STATE;
260 ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n", 261 ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n",
261 slot_name(p_slot)); 262 slot_name(p_slot));
262 } 263 }
263 /* blink green LED and turn off amber */ 264 /* blink green LED and turn off amber */
@@ -272,14 +273,14 @@ static void handle_button_press_event(struct slot *p_slot)
272 * press the attention again before the 5 sec. limit 273 * press the attention again before the 5 sec. limit
273 * expires to cancel hot-add or hot-remove 274 * expires to cancel hot-add or hot-remove
274 */ 275 */
275 ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); 276 ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(p_slot));
276 cancel_delayed_work(&p_slot->work); 277 cancel_delayed_work(&p_slot->work);
277 if (p_slot->state == BLINKINGOFF_STATE) 278 if (p_slot->state == BLINKINGOFF_STATE)
278 pciehp_green_led_on(p_slot); 279 pciehp_green_led_on(p_slot);
279 else 280 else
280 pciehp_green_led_off(p_slot); 281 pciehp_green_led_off(p_slot);
281 pciehp_set_attention_status(p_slot, 0); 282 pciehp_set_attention_status(p_slot, 0);
282 ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n", 283 ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n",
283 slot_name(p_slot)); 284 slot_name(p_slot));
284 p_slot->state = STATIC_STATE; 285 p_slot->state = STATIC_STATE;
285 break; 286 break;
@@ -290,10 +291,12 @@ static void handle_button_press_event(struct slot *p_slot)
290 * this means that the previous attention button action 291 * this means that the previous attention button action
291 * to hot-add or hot-remove is undergoing 292 * to hot-add or hot-remove is undergoing
292 */ 293 */
293 ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); 294 ctrl_info(ctrl, "Slot(%s): Button ignored\n",
295 slot_name(p_slot));
294 break; 296 break;
295 default: 297 default:
296 ctrl_warn(ctrl, "ignoring invalid state %#x\n", p_slot->state); 298 ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n",
299 slot_name(p_slot), p_slot->state);
297 break; 300 break;
298 } 301 }
299} 302}
@@ -301,20 +304,6 @@ static void handle_button_press_event(struct slot *p_slot)
301/* 304/*
302 * Note: This function must be called with slot->lock held 305 * Note: This function must be called with slot->lock held
303 */ 306 */
304static void handle_surprise_event(struct slot *p_slot)
305{
306 u8 getstatus;
307
308 pciehp_get_adapter_status(p_slot, &getstatus);
309 if (!getstatus)
310 pciehp_queue_power_work(p_slot, DISABLE_REQ);
311 else
312 pciehp_queue_power_work(p_slot, ENABLE_REQ);
313}
314
315/*
316 * Note: This function must be called with slot->lock held
317 */
318static void handle_link_event(struct slot *p_slot, u32 event) 307static void handle_link_event(struct slot *p_slot, u32 event)
319{ 308{
320 struct controller *ctrl = p_slot->ctrl; 309 struct controller *ctrl = p_slot->ctrl;
@@ -330,31 +319,27 @@ static void handle_link_event(struct slot *p_slot, u32 event)
330 break; 319 break;
331 case POWERON_STATE: 320 case POWERON_STATE:
332 if (event == INT_LINK_UP) { 321 if (event == INT_LINK_UP) {
333 ctrl_info(ctrl, 322 ctrl_info(ctrl, "Slot(%s): Link Up event ignored; already powering on\n",
334 "Link Up event ignored on slot(%s): already powering on\n",
335 slot_name(p_slot)); 323 slot_name(p_slot));
336 } else { 324 } else {
337 ctrl_info(ctrl, 325 ctrl_info(ctrl, "Slot(%s): Link Down event queued; currently getting powered on\n",
338 "Link Down event queued on slot(%s): currently getting powered on\n",
339 slot_name(p_slot)); 326 slot_name(p_slot));
340 pciehp_queue_power_work(p_slot, DISABLE_REQ); 327 pciehp_queue_power_work(p_slot, DISABLE_REQ);
341 } 328 }
342 break; 329 break;
343 case POWEROFF_STATE: 330 case POWEROFF_STATE:
344 if (event == INT_LINK_UP) { 331 if (event == INT_LINK_UP) {
345 ctrl_info(ctrl, 332 ctrl_info(ctrl, "Slot(%s): Link Up event queued; currently getting powered off\n",
346 "Link Up event queued on slot(%s): currently getting powered off\n",
347 slot_name(p_slot)); 333 slot_name(p_slot));
348 pciehp_queue_power_work(p_slot, ENABLE_REQ); 334 pciehp_queue_power_work(p_slot, ENABLE_REQ);
349 } else { 335 } else {
350 ctrl_info(ctrl, 336 ctrl_info(ctrl, "Slot(%s): Link Down event ignored; already powering off\n",
351 "Link Down event ignored on slot(%s): already powering off\n",
352 slot_name(p_slot)); 337 slot_name(p_slot));
353 } 338 }
354 break; 339 break;
355 default: 340 default:
356 ctrl_err(ctrl, "ignoring invalid state %#x on slot(%s)\n", 341 ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n",
357 p_slot->state, slot_name(p_slot)); 342 slot_name(p_slot), p_slot->state);
358 break; 343 break;
359 } 344 }
360} 345}
@@ -377,14 +362,14 @@ static void interrupt_event_handler(struct work_struct *work)
377 pciehp_green_led_off(p_slot); 362 pciehp_green_led_off(p_slot);
378 break; 363 break;
379 case INT_PRESENCE_ON: 364 case INT_PRESENCE_ON:
380 handle_surprise_event(p_slot); 365 pciehp_queue_power_work(p_slot, ENABLE_REQ);
381 break; 366 break;
382 case INT_PRESENCE_OFF: 367 case INT_PRESENCE_OFF:
383 /* 368 /*
384 * Regardless of surprise capability, we need to 369 * Regardless of surprise capability, we need to
385 * definitely remove a card that has been pulled out! 370 * definitely remove a card that has been pulled out!
386 */ 371 */
387 handle_surprise_event(p_slot); 372 pciehp_queue_power_work(p_slot, DISABLE_REQ);
388 break; 373 break;
389 case INT_LINK_UP: 374 case INT_LINK_UP:
390 case INT_LINK_DOWN: 375 case INT_LINK_DOWN:
@@ -404,18 +389,17 @@ static void interrupt_event_handler(struct work_struct *work)
404int pciehp_enable_slot(struct slot *p_slot) 389int pciehp_enable_slot(struct slot *p_slot)
405{ 390{
406 u8 getstatus = 0; 391 u8 getstatus = 0;
407 int rc;
408 struct controller *ctrl = p_slot->ctrl; 392 struct controller *ctrl = p_slot->ctrl;
409 393
410 pciehp_get_adapter_status(p_slot, &getstatus); 394 pciehp_get_adapter_status(p_slot, &getstatus);
411 if (!getstatus) { 395 if (!getstatus) {
412 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); 396 ctrl_info(ctrl, "Slot(%s): No adapter\n", slot_name(p_slot));
413 return -ENODEV; 397 return -ENODEV;
414 } 398 }
415 if (MRL_SENS(p_slot->ctrl)) { 399 if (MRL_SENS(p_slot->ctrl)) {
416 pciehp_get_latch_status(p_slot, &getstatus); 400 pciehp_get_latch_status(p_slot, &getstatus);
417 if (getstatus) { 401 if (getstatus) {
418 ctrl_info(ctrl, "Latch open on slot(%s)\n", 402 ctrl_info(ctrl, "Slot(%s): Latch open\n",
419 slot_name(p_slot)); 403 slot_name(p_slot));
420 return -ENODEV; 404 return -ENODEV;
421 } 405 }
@@ -424,19 +408,13 @@ int pciehp_enable_slot(struct slot *p_slot)
424 if (POWER_CTRL(p_slot->ctrl)) { 408 if (POWER_CTRL(p_slot->ctrl)) {
425 pciehp_get_power_status(p_slot, &getstatus); 409 pciehp_get_power_status(p_slot, &getstatus);
426 if (getstatus) { 410 if (getstatus) {
427 ctrl_info(ctrl, "Already enabled on slot(%s)\n", 411 ctrl_info(ctrl, "Slot(%s): Already enabled\n",
428 slot_name(p_slot)); 412 slot_name(p_slot));
429 return -EINVAL; 413 return -EINVAL;
430 } 414 }
431 } 415 }
432 416
433 pciehp_get_latch_status(p_slot, &getstatus); 417 return board_added(p_slot);
434
435 rc = board_added(p_slot);
436 if (rc)
437 pciehp_get_latch_status(p_slot, &getstatus);
438
439 return rc;
440} 418}
441 419
442/* 420/*
@@ -453,7 +431,7 @@ int pciehp_disable_slot(struct slot *p_slot)
453 if (POWER_CTRL(p_slot->ctrl)) { 431 if (POWER_CTRL(p_slot->ctrl)) {
454 pciehp_get_power_status(p_slot, &getstatus); 432 pciehp_get_power_status(p_slot, &getstatus);
455 if (!getstatus) { 433 if (!getstatus) {
456 ctrl_info(ctrl, "Already disabled on slot(%s)\n", 434 ctrl_info(ctrl, "Slot(%s): Already disabled\n",
457 slot_name(p_slot)); 435 slot_name(p_slot));
458 return -EINVAL; 436 return -EINVAL;
459 } 437 }
@@ -481,17 +459,17 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
481 p_slot->state = STATIC_STATE; 459 p_slot->state = STATIC_STATE;
482 break; 460 break;
483 case POWERON_STATE: 461 case POWERON_STATE:
484 ctrl_info(ctrl, "Slot %s is already in powering on state\n", 462 ctrl_info(ctrl, "Slot(%s): Already in powering on state\n",
485 slot_name(p_slot)); 463 slot_name(p_slot));
486 break; 464 break;
487 case BLINKINGOFF_STATE: 465 case BLINKINGOFF_STATE:
488 case POWEROFF_STATE: 466 case POWEROFF_STATE:
489 ctrl_info(ctrl, "Already enabled on slot %s\n", 467 ctrl_info(ctrl, "Slot(%s): Already enabled\n",
490 slot_name(p_slot)); 468 slot_name(p_slot));
491 break; 469 break;
492 default: 470 default:
493 ctrl_err(ctrl, "invalid state %#x on slot %s\n", 471 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
494 p_slot->state, slot_name(p_slot)); 472 slot_name(p_slot), p_slot->state);
495 break; 473 break;
496 } 474 }
497 mutex_unlock(&p_slot->lock); 475 mutex_unlock(&p_slot->lock);
@@ -518,17 +496,17 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot)
518 p_slot->state = STATIC_STATE; 496 p_slot->state = STATIC_STATE;
519 break; 497 break;
520 case POWEROFF_STATE: 498 case POWEROFF_STATE:
521 ctrl_info(ctrl, "Slot %s is already in powering off state\n", 499 ctrl_info(ctrl, "Slot(%s): Already in powering off state\n",
522 slot_name(p_slot)); 500 slot_name(p_slot));
523 break; 501 break;
524 case BLINKINGON_STATE: 502 case BLINKINGON_STATE:
525 case POWERON_STATE: 503 case POWERON_STATE:
526 ctrl_info(ctrl, "Already disabled on slot %s\n", 504 ctrl_info(ctrl, "Slot(%s): Already disabled\n",
527 slot_name(p_slot)); 505 slot_name(p_slot));
528 break; 506 break;
529 default: 507 default:
530 ctrl_err(ctrl, "invalid state %#x on slot %s\n", 508 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
531 p_slot->state, slot_name(p_slot)); 509 slot_name(p_slot), p_slot->state);
532 break; 510 break;
533 } 511 }
534 mutex_unlock(&p_slot->lock); 512 mutex_unlock(&p_slot->lock);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 08e84d61874e..b57fc6d6e28a 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -355,6 +355,18 @@ static int pciehp_link_enable(struct controller *ctrl)
355 return __pciehp_link_set(ctrl, true); 355 return __pciehp_link_set(ctrl, true);
356} 356}
357 357
358int pciehp_get_raw_indicator_status(struct hotplug_slot *hotplug_slot,
359 u8 *status)
360{
361 struct slot *slot = hotplug_slot->private;
362 struct pci_dev *pdev = ctrl_dev(slot->ctrl);
363 u16 slot_ctrl;
364
365 pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
366 *status = (slot_ctrl & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6;
367 return 0;
368}
369
358void pciehp_get_attention_status(struct slot *slot, u8 *status) 370void pciehp_get_attention_status(struct slot *slot, u8 *status)
359{ 371{
360 struct controller *ctrl = slot->ctrl; 372 struct controller *ctrl = slot->ctrl;
@@ -431,6 +443,17 @@ int pciehp_query_power_fault(struct slot *slot)
431 return !!(slot_status & PCI_EXP_SLTSTA_PFD); 443 return !!(slot_status & PCI_EXP_SLTSTA_PFD);
432} 444}
433 445
446int pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot,
447 u8 status)
448{
449 struct slot *slot = hotplug_slot->private;
450 struct controller *ctrl = slot->ctrl;
451
452 pcie_write_cmd_nowait(ctrl, status << 6,
453 PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC);
454 return 0;
455}
456
434void pciehp_set_attention_status(struct slot *slot, u8 value) 457void pciehp_set_attention_status(struct slot *slot, u8 value)
435{ 458{
436 struct controller *ctrl = slot->ctrl; 459 struct controller *ctrl = slot->ctrl;
@@ -535,14 +558,14 @@ void pciehp_power_off_slot(struct slot *slot)
535 PCI_EXP_SLTCTL_PWR_OFF); 558 PCI_EXP_SLTCTL_PWR_OFF);
536} 559}
537 560
538static irqreturn_t pcie_isr(int irq, void *dev_id) 561static irqreturn_t pciehp_isr(int irq, void *dev_id)
539{ 562{
540 struct controller *ctrl = (struct controller *)dev_id; 563 struct controller *ctrl = (struct controller *)dev_id;
541 struct pci_dev *pdev = ctrl_dev(ctrl); 564 struct pci_dev *pdev = ctrl_dev(ctrl);
542 struct pci_bus *subordinate = pdev->subordinate; 565 struct pci_bus *subordinate = pdev->subordinate;
543 struct pci_dev *dev; 566 struct pci_dev *dev;
544 struct slot *slot = ctrl->slot; 567 struct slot *slot = ctrl->slot;
545 u16 detected, intr_loc; 568 u16 status, events;
546 u8 present; 569 u8 present;
547 bool link; 570 bool link;
548 571
@@ -550,36 +573,31 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
550 if (pdev->current_state == PCI_D3cold) 573 if (pdev->current_state == PCI_D3cold)
551 return IRQ_NONE; 574 return IRQ_NONE;
552 575
576 pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &status);
577 if (status == (u16) ~0) {
578 ctrl_info(ctrl, "%s: no response from device\n", __func__);
579 return IRQ_NONE;
580 }
581
553 /* 582 /*
554 * In order to guarantee that all interrupt events are 583 * Slot Status contains plain status bits as well as event
555 * serviced, we need to re-inspect Slot Status register after 584 * notification bits; right now we only want the event bits.
556 * clearing what is presumed to be the last pending interrupt.
557 */ 585 */
558 intr_loc = 0; 586 events = status & (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
559 do { 587 PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC |
560 pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected); 588 PCI_EXP_SLTSTA_DLLSC);
561 if (detected == (u16) ~0) { 589 if (!events)
562 ctrl_info(ctrl, "%s: no response from device\n", 590 return IRQ_NONE;
563 __func__);
564 return IRQ_HANDLED;
565 }
566 591
567 detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | 592 /* Capture link status before clearing interrupts */
568 PCI_EXP_SLTSTA_PDC | 593 if (events & PCI_EXP_SLTSTA_DLLSC)
569 PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC); 594 link = pciehp_check_link_active(ctrl);
570 detected &= ~intr_loc;
571 intr_loc |= detected;
572 if (!intr_loc)
573 return IRQ_NONE;
574 if (detected)
575 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
576 intr_loc);
577 } while (detected);
578 595
579 ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", intr_loc); 596 pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events);
597 ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", events);
580 598
581 /* Check Command Complete Interrupt Pending */ 599 /* Check Command Complete Interrupt Pending */
582 if (intr_loc & PCI_EXP_SLTSTA_CC) { 600 if (events & PCI_EXP_SLTSTA_CC) {
583 ctrl->cmd_busy = 0; 601 ctrl->cmd_busy = 0;
584 smp_mb(); 602 smp_mb();
585 wake_up(&ctrl->queue); 603 wake_up(&ctrl->queue);
@@ -589,42 +607,38 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
589 list_for_each_entry(dev, &subordinate->devices, bus_list) { 607 list_for_each_entry(dev, &subordinate->devices, bus_list) {
590 if (dev->ignore_hotplug) { 608 if (dev->ignore_hotplug) {
591 ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n", 609 ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n",
592 intr_loc, pci_name(dev)); 610 events, pci_name(dev));
593 return IRQ_HANDLED; 611 return IRQ_HANDLED;
594 } 612 }
595 } 613 }
596 } 614 }
597 615
598 if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
599 return IRQ_HANDLED;
600
601 /* Check Attention Button Pressed */ 616 /* Check Attention Button Pressed */
602 if (intr_loc & PCI_EXP_SLTSTA_ABP) { 617 if (events & PCI_EXP_SLTSTA_ABP) {
603 ctrl_info(ctrl, "Button pressed on Slot(%s)\n", 618 ctrl_info(ctrl, "Slot(%s): Attention button pressed\n",
604 slot_name(slot)); 619 slot_name(slot));
605 pciehp_queue_interrupt_event(slot, INT_BUTTON_PRESS); 620 pciehp_queue_interrupt_event(slot, INT_BUTTON_PRESS);
606 } 621 }
607 622
608 /* Check Presence Detect Changed */ 623 /* Check Presence Detect Changed */
609 if (intr_loc & PCI_EXP_SLTSTA_PDC) { 624 if (events & PCI_EXP_SLTSTA_PDC) {
610 pciehp_get_adapter_status(slot, &present); 625 present = !!(status & PCI_EXP_SLTSTA_PDS);
611 ctrl_info(ctrl, "Card %spresent on Slot(%s)\n", 626 ctrl_info(ctrl, "Slot(%s): Card %spresent\n", slot_name(slot),
612 present ? "" : "not ", slot_name(slot)); 627 present ? "" : "not ");
613 pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON : 628 pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON :
614 INT_PRESENCE_OFF); 629 INT_PRESENCE_OFF);
615 } 630 }
616 631
617 /* Check Power Fault Detected */ 632 /* Check Power Fault Detected */
618 if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { 633 if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
619 ctrl->power_fault_detected = 1; 634 ctrl->power_fault_detected = 1;
620 ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(slot)); 635 ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(slot));
621 pciehp_queue_interrupt_event(slot, INT_POWER_FAULT); 636 pciehp_queue_interrupt_event(slot, INT_POWER_FAULT);
622 } 637 }
623 638
624 if (intr_loc & PCI_EXP_SLTSTA_DLLSC) { 639 if (events & PCI_EXP_SLTSTA_DLLSC) {
625 link = pciehp_check_link_active(ctrl); 640 ctrl_info(ctrl, "Slot(%s): Link %s\n", slot_name(slot),
626 ctrl_info(ctrl, "slot(%s): Link %s event\n", 641 link ? "Up" : "Down");
627 slot_name(slot), link ? "Up" : "Down");
628 pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP : 642 pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP :
629 INT_LINK_DOWN); 643 INT_LINK_DOWN);
630 } 644 }
@@ -632,6 +646,25 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
632 return IRQ_HANDLED; 646 return IRQ_HANDLED;
633} 647}
634 648
649static irqreturn_t pcie_isr(int irq, void *dev_id)
650{
651 irqreturn_t rc, handled = IRQ_NONE;
652
653 /*
654 * To guarantee that all interrupt events are serviced, we need to
655 * re-inspect Slot Status register after clearing what is presumed
656 * to be the last pending interrupt.
657 */
658 do {
659 rc = pciehp_isr(irq, dev_id);
660 if (rc == IRQ_HANDLED)
661 handled = IRQ_HANDLED;
662 } while (rc == IRQ_HANDLED);
663
664 /* Return IRQ_HANDLED if we handled one or more events */
665 return handled;
666}
667
635void pcie_enable_notification(struct controller *ctrl) 668void pcie_enable_notification(struct controller *ctrl)
636{ 669{
637 u16 cmd, mask; 670 u16 cmd, mask;
@@ -804,6 +837,10 @@ struct controller *pcie_init(struct pcie_device *dev)
804 } 837 }
805 ctrl->pcie = dev; 838 ctrl->pcie = dev;
806 pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); 839 pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);
840
841 if (pdev->hotplug_user_indicators)
842 slot_cap &= ~(PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_PIP);
843
807 ctrl->slot_cap = slot_cap; 844 ctrl->slot_cap = slot_cap;
808 mutex_init(&ctrl->ctrl_lock); 845 mutex_init(&ctrl->ctrl_lock);
809 init_waitqueue_head(&ctrl->queue); 846 init_waitqueue_head(&ctrl->queue);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 84d222ad3c08..b0e4ed19b315 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -312,6 +312,9 @@ struct pci_dev {
312 powered on/off by the 312 powered on/off by the
313 corresponding bridge */ 313 corresponding bridge */
314 unsigned int ignore_hotplug:1; /* Ignore hotplug events */ 314 unsigned int ignore_hotplug:1; /* Ignore hotplug events */
315 unsigned int hotplug_user_indicators:1; /* SlotCtl indicators
316 controlled exclusively by
317 user sysfs */
315 unsigned int d3_delay; /* D3->D0 transition time in ms */ 318 unsigned int d3_delay; /* D3->D0 transition time in ms */
316 unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */ 319 unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */
317 320