aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/pciehp_ctrl.c')
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c173
1 files changed, 137 insertions, 36 deletions
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 50628487597d..c75e6a678dcc 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -150,6 +150,27 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
150 return 1; 150 return 1;
151} 151}
152 152
153void pciehp_handle_linkstate_change(struct slot *p_slot)
154{
155 u32 event_type;
156 struct controller *ctrl = p_slot->ctrl;
157
158 /* Link Status Change */
159 ctrl_dbg(ctrl, "Data Link Layer State change\n");
160
161 if (pciehp_check_link_active(ctrl)) {
162 ctrl_info(ctrl, "slot(%s): Link Up event\n",
163 slot_name(p_slot));
164 event_type = INT_LINK_UP;
165 } else {
166 ctrl_info(ctrl, "slot(%s): Link Down event\n",
167 slot_name(p_slot));
168 event_type = INT_LINK_DOWN;
169 }
170
171 queue_interrupt_event(p_slot, event_type);
172}
173
153/* The following routines constitute the bulk of the 174/* The following routines constitute the bulk of the
154 hotplug controller logic 175 hotplug controller logic
155 */ 176 */
@@ -212,7 +233,8 @@ static int board_added(struct slot *p_slot)
212 if (retval) { 233 if (retval) {
213 ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n", 234 ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
214 pci_domain_nr(parent), parent->number); 235 pci_domain_nr(parent), parent->number);
215 goto err_exit; 236 if (retval != -EEXIST)
237 goto err_exit;
216 } 238 }
217 239
218 pciehp_green_led_on(p_slot); 240 pciehp_green_led_on(p_slot);
@@ -255,6 +277,9 @@ static int remove_board(struct slot *p_slot)
255struct power_work_info { 277struct power_work_info {
256 struct slot *p_slot; 278 struct slot *p_slot;
257 struct work_struct work; 279 struct work_struct work;
280 unsigned int req;
281#define DISABLE_REQ 0
282#define ENABLE_REQ 1
258}; 283};
259 284
260/** 285/**
@@ -269,30 +294,38 @@ static void pciehp_power_thread(struct work_struct *work)
269 struct power_work_info *info = 294 struct power_work_info *info =
270 container_of(work, struct power_work_info, work); 295 container_of(work, struct power_work_info, work);
271 struct slot *p_slot = info->p_slot; 296 struct slot *p_slot = info->p_slot;
297 int ret;
272 298
273 mutex_lock(&p_slot->lock); 299 switch (info->req) {
274 switch (p_slot->state) { 300 case DISABLE_REQ:
275 case POWEROFF_STATE:
276 mutex_unlock(&p_slot->lock);
277 ctrl_dbg(p_slot->ctrl, 301 ctrl_dbg(p_slot->ctrl,
278 "Disabling domain:bus:device=%04x:%02x:00\n", 302 "Disabling domain:bus:device=%04x:%02x:00\n",
279 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate), 303 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
280 p_slot->ctrl->pcie->port->subordinate->number); 304 p_slot->ctrl->pcie->port->subordinate->number);
305 mutex_lock(&p_slot->hotplug_lock);
281 pciehp_disable_slot(p_slot); 306 pciehp_disable_slot(p_slot);
307 mutex_unlock(&p_slot->hotplug_lock);
282 mutex_lock(&p_slot->lock); 308 mutex_lock(&p_slot->lock);
283 p_slot->state = STATIC_STATE; 309 p_slot->state = STATIC_STATE;
284 break;
285 case POWERON_STATE:
286 mutex_unlock(&p_slot->lock); 310 mutex_unlock(&p_slot->lock);
287 if (pciehp_enable_slot(p_slot)) 311 break;
312 case ENABLE_REQ:
313 ctrl_dbg(p_slot->ctrl,
314 "Enabling domain:bus:device=%04x:%02x:00\n",
315 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
316 p_slot->ctrl->pcie->port->subordinate->number);
317 mutex_lock(&p_slot->hotplug_lock);
318 ret = pciehp_enable_slot(p_slot);
319 mutex_unlock(&p_slot->hotplug_lock);
320 if (ret)
288 pciehp_green_led_off(p_slot); 321 pciehp_green_led_off(p_slot);
289 mutex_lock(&p_slot->lock); 322 mutex_lock(&p_slot->lock);
290 p_slot->state = STATIC_STATE; 323 p_slot->state = STATIC_STATE;
324 mutex_unlock(&p_slot->lock);
291 break; 325 break;
292 default: 326 default:
293 break; 327 break;
294 } 328 }
295 mutex_unlock(&p_slot->lock);
296 329
297 kfree(info); 330 kfree(info);
298} 331}
@@ -315,9 +348,11 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
315 switch (p_slot->state) { 348 switch (p_slot->state) {
316 case BLINKINGOFF_STATE: 349 case BLINKINGOFF_STATE:
317 p_slot->state = POWEROFF_STATE; 350 p_slot->state = POWEROFF_STATE;
351 info->req = DISABLE_REQ;
318 break; 352 break;
319 case BLINKINGON_STATE: 353 case BLINKINGON_STATE:
320 p_slot->state = POWERON_STATE; 354 p_slot->state = POWERON_STATE;
355 info->req = ENABLE_REQ;
321 break; 356 break;
322 default: 357 default:
323 kfree(info); 358 kfree(info);
@@ -364,11 +399,10 @@ static void handle_button_press_event(struct slot *p_slot)
364 */ 399 */
365 ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); 400 ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
366 cancel_delayed_work(&p_slot->work); 401 cancel_delayed_work(&p_slot->work);
367 if (p_slot->state == BLINKINGOFF_STATE) { 402 if (p_slot->state == BLINKINGOFF_STATE)
368 pciehp_green_led_on(p_slot); 403 pciehp_green_led_on(p_slot);
369 } else { 404 else
370 pciehp_green_led_off(p_slot); 405 pciehp_green_led_off(p_slot);
371 }
372 pciehp_set_attention_status(p_slot, 0); 406 pciehp_set_attention_status(p_slot, 0);
373 ctrl_info(ctrl, "PCI slot #%s - action canceled " 407 ctrl_info(ctrl, "PCI slot #%s - action canceled "
374 "due to button press\n", slot_name(p_slot)); 408 "due to button press\n", slot_name(p_slot));
@@ -407,14 +441,81 @@ static void handle_surprise_event(struct slot *p_slot)
407 INIT_WORK(&info->work, pciehp_power_thread); 441 INIT_WORK(&info->work, pciehp_power_thread);
408 442
409 pciehp_get_adapter_status(p_slot, &getstatus); 443 pciehp_get_adapter_status(p_slot, &getstatus);
410 if (!getstatus) 444 if (!getstatus) {
411 p_slot->state = POWEROFF_STATE; 445 p_slot->state = POWEROFF_STATE;
412 else 446 info->req = DISABLE_REQ;
447 } else {
413 p_slot->state = POWERON_STATE; 448 p_slot->state = POWERON_STATE;
449 info->req = ENABLE_REQ;
450 }
414 451
415 queue_work(p_slot->wq, &info->work); 452 queue_work(p_slot->wq, &info->work);
416} 453}
417 454
455/*
456 * Note: This function must be called with slot->lock held
457 */
458static void handle_link_event(struct slot *p_slot, u32 event)
459{
460 struct controller *ctrl = p_slot->ctrl;
461 struct power_work_info *info;
462
463 info = kmalloc(sizeof(*info), GFP_KERNEL);
464 if (!info) {
465 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
466 __func__);
467 return;
468 }
469 info->p_slot = p_slot;
470 info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ;
471 INIT_WORK(&info->work, pciehp_power_thread);
472
473 switch (p_slot->state) {
474 case BLINKINGON_STATE:
475 case BLINKINGOFF_STATE:
476 cancel_delayed_work(&p_slot->work);
477 /* Fall through */
478 case STATIC_STATE:
479 p_slot->state = event == INT_LINK_UP ?
480 POWERON_STATE : POWEROFF_STATE;
481 queue_work(p_slot->wq, &info->work);
482 break;
483 case POWERON_STATE:
484 if (event == INT_LINK_UP) {
485 ctrl_info(ctrl,
486 "Link Up event ignored on slot(%s): already powering on\n",
487 slot_name(p_slot));
488 kfree(info);
489 } else {
490 ctrl_info(ctrl,
491 "Link Down event queued on slot(%s): currently getting powered on\n",
492 slot_name(p_slot));
493 p_slot->state = POWEROFF_STATE;
494 queue_work(p_slot->wq, &info->work);
495 }
496 break;
497 case POWEROFF_STATE:
498 if (event == INT_LINK_UP) {
499 ctrl_info(ctrl,
500 "Link Up event queued on slot(%s): currently getting powered off\n",
501 slot_name(p_slot));
502 p_slot->state = POWERON_STATE;
503 queue_work(p_slot->wq, &info->work);
504 } else {
505 ctrl_info(ctrl,
506 "Link Down event ignored on slot(%s): already powering off\n",
507 slot_name(p_slot));
508 kfree(info);
509 }
510 break;
511 default:
512 ctrl_err(ctrl, "Not a valid state on slot(%s)\n",
513 slot_name(p_slot));
514 kfree(info);
515 break;
516 }
517}
518
418static void interrupt_event_handler(struct work_struct *work) 519static void interrupt_event_handler(struct work_struct *work)
419{ 520{
420 struct event_info *info = container_of(work, struct event_info, work); 521 struct event_info *info = container_of(work, struct event_info, work);
@@ -433,12 +534,23 @@ static void interrupt_event_handler(struct work_struct *work)
433 pciehp_green_led_off(p_slot); 534 pciehp_green_led_off(p_slot);
434 break; 535 break;
435 case INT_PRESENCE_ON: 536 case INT_PRESENCE_ON:
436 case INT_PRESENCE_OFF:
437 if (!HP_SUPR_RM(ctrl)) 537 if (!HP_SUPR_RM(ctrl))
438 break; 538 break;
539 ctrl_dbg(ctrl, "Surprise Insertion\n");
540 handle_surprise_event(p_slot);
541 break;
542 case INT_PRESENCE_OFF:
543 /*
544 * Regardless of surprise capability, we need to
545 * definitely remove a card that has been pulled out!
546 */
439 ctrl_dbg(ctrl, "Surprise Removal\n"); 547 ctrl_dbg(ctrl, "Surprise Removal\n");
440 handle_surprise_event(p_slot); 548 handle_surprise_event(p_slot);
441 break; 549 break;
550 case INT_LINK_UP:
551 case INT_LINK_DOWN:
552 handle_link_event(p_slot, info->event_type);
553 break;
442 default: 554 default:
443 break; 555 break;
444 } 556 }
@@ -447,6 +559,9 @@ static void interrupt_event_handler(struct work_struct *work)
447 kfree(info); 559 kfree(info);
448} 560}
449 561
562/*
563 * Note: This function must be called with slot->hotplug_lock held
564 */
450int pciehp_enable_slot(struct slot *p_slot) 565int pciehp_enable_slot(struct slot *p_slot)
451{ 566{
452 u8 getstatus = 0; 567 u8 getstatus = 0;
@@ -479,13 +594,15 @@ int pciehp_enable_slot(struct slot *p_slot)
479 pciehp_get_latch_status(p_slot, &getstatus); 594 pciehp_get_latch_status(p_slot, &getstatus);
480 595
481 rc = board_added(p_slot); 596 rc = board_added(p_slot);
482 if (rc) { 597 if (rc)
483 pciehp_get_latch_status(p_slot, &getstatus); 598 pciehp_get_latch_status(p_slot, &getstatus);
484 } 599
485 return rc; 600 return rc;
486} 601}
487 602
488 603/*
604 * Note: This function must be called with slot->hotplug_lock held
605 */
489int pciehp_disable_slot(struct slot *p_slot) 606int pciehp_disable_slot(struct slot *p_slot)
490{ 607{
491 u8 getstatus = 0; 608 u8 getstatus = 0;
@@ -494,24 +611,6 @@ int pciehp_disable_slot(struct slot *p_slot)
494 if (!p_slot->ctrl) 611 if (!p_slot->ctrl)
495 return 1; 612 return 1;
496 613
497 if (!HP_SUPR_RM(p_slot->ctrl)) {
498 pciehp_get_adapter_status(p_slot, &getstatus);
499 if (!getstatus) {
500 ctrl_info(ctrl, "No adapter on slot(%s)\n",
501 slot_name(p_slot));
502 return -ENODEV;
503 }
504 }
505
506 if (MRL_SENS(p_slot->ctrl)) {
507 pciehp_get_latch_status(p_slot, &getstatus);
508 if (getstatus) {
509 ctrl_info(ctrl, "Latch open on slot(%s)\n",
510 slot_name(p_slot));
511 return -ENODEV;
512 }
513 }
514
515 if (POWER_CTRL(p_slot->ctrl)) { 614 if (POWER_CTRL(p_slot->ctrl)) {
516 pciehp_get_power_status(p_slot, &getstatus); 615 pciehp_get_power_status(p_slot, &getstatus);
517 if (!getstatus) { 616 if (!getstatus) {
@@ -536,7 +635,9 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
536 case STATIC_STATE: 635 case STATIC_STATE:
537 p_slot->state = POWERON_STATE; 636 p_slot->state = POWERON_STATE;
538 mutex_unlock(&p_slot->lock); 637 mutex_unlock(&p_slot->lock);
638 mutex_lock(&p_slot->hotplug_lock);
539 retval = pciehp_enable_slot(p_slot); 639 retval = pciehp_enable_slot(p_slot);
640 mutex_unlock(&p_slot->hotplug_lock);
540 mutex_lock(&p_slot->lock); 641 mutex_lock(&p_slot->lock);
541 p_slot->state = STATIC_STATE; 642 p_slot->state = STATIC_STATE;
542 break; 643 break;