0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/module.h>
0017 #include <linux/kernel.h>
0018 #include <linux/types.h>
0019 #include <linux/slab.h>
0020 #include <linux/pci.h>
0021 #include "../pci.h"
0022 #include "shpchp.h"
0023
0024 static void interrupt_event_handler(struct work_struct *work);
0025 static int shpchp_enable_slot(struct slot *p_slot);
0026 static int shpchp_disable_slot(struct slot *p_slot);
0027
0028 static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
0029 {
0030 struct event_info *info;
0031
0032 info = kmalloc(sizeof(*info), GFP_ATOMIC);
0033 if (!info)
0034 return -ENOMEM;
0035
0036 info->event_type = event_type;
0037 info->p_slot = p_slot;
0038 INIT_WORK(&info->work, interrupt_event_handler);
0039
0040 queue_work(p_slot->wq, &info->work);
0041
0042 return 0;
0043 }
0044
0045 u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
0046 {
0047 struct slot *p_slot;
0048 u32 event_type;
0049
0050
0051 ctrl_dbg(ctrl, "Attention button interrupt received\n");
0052
0053 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
0054 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
0055
0056
0057
0058
0059 ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
0060 event_type = INT_BUTTON_PRESS;
0061
0062 queue_interrupt_event(p_slot, event_type);
0063
0064 return 0;
0065
0066 }
0067
0068 u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
0069 {
0070 struct slot *p_slot;
0071 u8 getstatus;
0072 u32 event_type;
0073
0074
0075 ctrl_dbg(ctrl, "Switch interrupt received\n");
0076
0077 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
0078 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
0079 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
0080 ctrl_dbg(ctrl, "Card present %x Power status %x\n",
0081 p_slot->presence_save, p_slot->pwr_save);
0082
0083 if (getstatus) {
0084
0085
0086
0087 ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot));
0088 event_type = INT_SWITCH_OPEN;
0089 if (p_slot->pwr_save && p_slot->presence_save) {
0090 event_type = INT_POWER_FAULT;
0091 ctrl_err(ctrl, "Surprise Removal of card\n");
0092 }
0093 } else {
0094
0095
0096
0097 ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot));
0098 event_type = INT_SWITCH_CLOSE;
0099 }
0100
0101 queue_interrupt_event(p_slot, event_type);
0102
0103 return 1;
0104 }
0105
0106 u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
0107 {
0108 struct slot *p_slot;
0109 u32 event_type;
0110
0111
0112 ctrl_dbg(ctrl, "Presence/Notify input change\n");
0113
0114 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
0115
0116
0117
0118
0119 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
0120 if (p_slot->presence_save) {
0121
0122
0123
0124 ctrl_info(ctrl, "Card present on Slot(%s)\n",
0125 slot_name(p_slot));
0126 event_type = INT_PRESENCE_ON;
0127 } else {
0128
0129
0130
0131 ctrl_info(ctrl, "Card not present on Slot(%s)\n",
0132 slot_name(p_slot));
0133 event_type = INT_PRESENCE_OFF;
0134 }
0135
0136 queue_interrupt_event(p_slot, event_type);
0137
0138 return 1;
0139 }
0140
0141 u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
0142 {
0143 struct slot *p_slot;
0144 u32 event_type;
0145
0146
0147 ctrl_dbg(ctrl, "Power fault interrupt received\n");
0148
0149 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
0150
0151 if (!(p_slot->hpc_ops->query_power_fault(p_slot))) {
0152
0153
0154
0155 ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
0156 slot_name(p_slot));
0157 p_slot->status = 0x00;
0158 event_type = INT_POWER_FAULT_CLEAR;
0159 } else {
0160
0161
0162
0163 ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
0164 event_type = INT_POWER_FAULT;
0165
0166 p_slot->status = 0xFF;
0167 ctrl_info(ctrl, "Power fault bit %x set\n", hp_slot);
0168 }
0169
0170 queue_interrupt_event(p_slot, event_type);
0171
0172 return 1;
0173 }
0174
0175
0176
0177
0178 static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
0179 enum pci_bus_speed speed)
0180 {
0181 int rc = 0;
0182
0183 ctrl_dbg(ctrl, "Change speed to %d\n", speed);
0184 rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed);
0185 if (rc) {
0186 ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n",
0187 __func__);
0188 return WRONG_BUS_FREQUENCY;
0189 }
0190 return rc;
0191 }
0192
0193 static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
0194 u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,
0195 enum pci_bus_speed msp)
0196 {
0197 int rc = 0;
0198
0199
0200
0201
0202
0203 if (flag) {
0204 if (asp < bsp) {
0205 ctrl_err(ctrl, "Speed of bus %x and adapter %x mismatch\n",
0206 bsp, asp);
0207 rc = WRONG_BUS_FREQUENCY;
0208 }
0209 return rc;
0210 }
0211
0212 if (asp < msp) {
0213 if (bsp != asp)
0214 rc = change_bus_speed(ctrl, pslot, asp);
0215 } else {
0216 if (bsp != msp)
0217 rc = change_bus_speed(ctrl, pslot, msp);
0218 }
0219 return rc;
0220 }
0221
0222
0223
0224
0225
0226
0227
0228
0229 static int board_added(struct slot *p_slot)
0230 {
0231 u8 hp_slot;
0232 u8 slots_not_empty = 0;
0233 int rc = 0;
0234 enum pci_bus_speed asp, bsp, msp;
0235 struct controller *ctrl = p_slot->ctrl;
0236 struct pci_bus *parent = ctrl->pci_dev->subordinate;
0237
0238 hp_slot = p_slot->device - ctrl->slot_device_offset;
0239
0240 ctrl_dbg(ctrl, "%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
0241 __func__, p_slot->device, ctrl->slot_device_offset, hp_slot);
0242
0243
0244 rc = p_slot->hpc_ops->power_on_slot(p_slot);
0245 if (rc) {
0246 ctrl_err(ctrl, "Failed to power on slot\n");
0247 return -1;
0248 }
0249
0250 if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
0251 rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz);
0252 if (rc) {
0253 ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n",
0254 __func__);
0255 return WRONG_BUS_FREQUENCY;
0256 }
0257
0258
0259 rc = p_slot->hpc_ops->slot_enable(p_slot);
0260 if (rc) {
0261 ctrl_err(ctrl, "Issue of Slot Enable command failed\n");
0262 return rc;
0263 }
0264 }
0265
0266 rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);
0267 if (rc) {
0268 ctrl_err(ctrl, "Can't get adapter speed or bus mode mismatch\n");
0269 return WRONG_BUS_FREQUENCY;
0270 }
0271
0272 bsp = ctrl->pci_dev->subordinate->cur_bus_speed;
0273 msp = ctrl->pci_dev->subordinate->max_bus_speed;
0274
0275
0276 if (!list_empty(&ctrl->pci_dev->subordinate->devices))
0277 slots_not_empty = 1;
0278
0279 ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, max_bus_speed %d\n",
0280 __func__, slots_not_empty, asp,
0281 bsp, msp);
0282
0283 rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp);
0284 if (rc)
0285 return rc;
0286
0287
0288 rc = p_slot->hpc_ops->slot_enable(p_slot);
0289 if (rc) {
0290 ctrl_err(ctrl, "Issue of Slot Enable command failed\n");
0291 return rc;
0292 }
0293
0294
0295 msleep(1000);
0296
0297 ctrl_dbg(ctrl, "%s: slot status = %x\n", __func__, p_slot->status);
0298
0299 if (p_slot->status == 0xFF) {
0300
0301 ctrl_dbg(ctrl, "%s: Power fault\n", __func__);
0302 p_slot->status = 0;
0303 goto err_exit;
0304 }
0305
0306 if (shpchp_configure_device(p_slot)) {
0307 ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n",
0308 pci_domain_nr(parent), p_slot->bus, p_slot->device);
0309 goto err_exit;
0310 }
0311
0312 p_slot->status = 0;
0313 p_slot->is_a_board = 0x01;
0314 p_slot->pwr_save = 1;
0315
0316 p_slot->hpc_ops->green_led_on(p_slot);
0317
0318 return 0;
0319
0320 err_exit:
0321
0322 rc = p_slot->hpc_ops->slot_disable(p_slot);
0323 if (rc) {
0324 ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
0325 __func__);
0326 return rc;
0327 }
0328
0329 return(rc);
0330 }
0331
0332
0333
0334
0335
0336
0337 static int remove_board(struct slot *p_slot)
0338 {
0339 struct controller *ctrl = p_slot->ctrl;
0340 u8 hp_slot;
0341 int rc;
0342
0343 shpchp_unconfigure_device(p_slot);
0344
0345 hp_slot = p_slot->device - ctrl->slot_device_offset;
0346 p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
0347
0348 ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, hp_slot);
0349
0350
0351 if (p_slot->is_a_board)
0352 p_slot->status = 0x01;
0353
0354
0355 rc = p_slot->hpc_ops->slot_disable(p_slot);
0356 if (rc) {
0357 ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
0358 __func__);
0359 return rc;
0360 }
0361
0362 rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
0363 if (rc) {
0364 ctrl_err(ctrl, "Issue of Set Attention command failed\n");
0365 return rc;
0366 }
0367
0368 p_slot->pwr_save = 0;
0369 p_slot->is_a_board = 0;
0370
0371 return 0;
0372 }
0373
0374
0375 struct pushbutton_work_info {
0376 struct slot *p_slot;
0377 struct work_struct work;
0378 };
0379
0380
0381
0382
0383
0384
0385
0386
0387 static void shpchp_pushbutton_thread(struct work_struct *work)
0388 {
0389 struct pushbutton_work_info *info =
0390 container_of(work, struct pushbutton_work_info, work);
0391 struct slot *p_slot = info->p_slot;
0392
0393 mutex_lock(&p_slot->lock);
0394 switch (p_slot->state) {
0395 case POWEROFF_STATE:
0396 mutex_unlock(&p_slot->lock);
0397 shpchp_disable_slot(p_slot);
0398 mutex_lock(&p_slot->lock);
0399 p_slot->state = STATIC_STATE;
0400 break;
0401 case POWERON_STATE:
0402 mutex_unlock(&p_slot->lock);
0403 if (shpchp_enable_slot(p_slot))
0404 p_slot->hpc_ops->green_led_off(p_slot);
0405 mutex_lock(&p_slot->lock);
0406 p_slot->state = STATIC_STATE;
0407 break;
0408 default:
0409 break;
0410 }
0411 mutex_unlock(&p_slot->lock);
0412
0413 kfree(info);
0414 }
0415
0416 void shpchp_queue_pushbutton_work(struct work_struct *work)
0417 {
0418 struct slot *p_slot = container_of(work, struct slot, work.work);
0419 struct pushbutton_work_info *info;
0420
0421 info = kmalloc(sizeof(*info), GFP_KERNEL);
0422 if (!info) {
0423 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
0424 __func__);
0425 return;
0426 }
0427 info->p_slot = p_slot;
0428 INIT_WORK(&info->work, shpchp_pushbutton_thread);
0429
0430 mutex_lock(&p_slot->lock);
0431 switch (p_slot->state) {
0432 case BLINKINGOFF_STATE:
0433 p_slot->state = POWEROFF_STATE;
0434 break;
0435 case BLINKINGON_STATE:
0436 p_slot->state = POWERON_STATE;
0437 break;
0438 default:
0439 kfree(info);
0440 goto out;
0441 }
0442 queue_work(p_slot->wq, &info->work);
0443 out:
0444 mutex_unlock(&p_slot->lock);
0445 }
0446
0447 static void update_slot_info(struct slot *slot)
0448 {
0449 slot->hpc_ops->get_power_status(slot, &slot->pwr_save);
0450 slot->hpc_ops->get_attention_status(slot, &slot->attention_save);
0451 slot->hpc_ops->get_latch_status(slot, &slot->latch_save);
0452 slot->hpc_ops->get_adapter_status(slot, &slot->presence_save);
0453 }
0454
0455
0456
0457
0458 static void handle_button_press_event(struct slot *p_slot)
0459 {
0460 u8 getstatus;
0461 struct controller *ctrl = p_slot->ctrl;
0462
0463 switch (p_slot->state) {
0464 case STATIC_STATE:
0465 p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
0466 if (getstatus) {
0467 p_slot->state = BLINKINGOFF_STATE;
0468 ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n",
0469 slot_name(p_slot));
0470 } else {
0471 p_slot->state = BLINKINGON_STATE;
0472 ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n",
0473 slot_name(p_slot));
0474 }
0475
0476 p_slot->hpc_ops->green_led_blink(p_slot);
0477 p_slot->hpc_ops->set_attention_status(p_slot, 0);
0478
0479 queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
0480 break;
0481 case BLINKINGOFF_STATE:
0482 case BLINKINGON_STATE:
0483
0484
0485
0486
0487
0488 ctrl_info(ctrl, "Button cancel on Slot(%s)\n",
0489 slot_name(p_slot));
0490 cancel_delayed_work(&p_slot->work);
0491 if (p_slot->state == BLINKINGOFF_STATE)
0492 p_slot->hpc_ops->green_led_on(p_slot);
0493 else
0494 p_slot->hpc_ops->green_led_off(p_slot);
0495 p_slot->hpc_ops->set_attention_status(p_slot, 0);
0496 ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n",
0497 slot_name(p_slot));
0498 p_slot->state = STATIC_STATE;
0499 break;
0500 case POWEROFF_STATE:
0501 case POWERON_STATE:
0502
0503
0504
0505
0506
0507 ctrl_info(ctrl, "Button ignore on Slot(%s)\n",
0508 slot_name(p_slot));
0509 update_slot_info(p_slot);
0510 break;
0511 default:
0512 ctrl_warn(ctrl, "Not a valid state\n");
0513 break;
0514 }
0515 }
0516
0517 static void interrupt_event_handler(struct work_struct *work)
0518 {
0519 struct event_info *info = container_of(work, struct event_info, work);
0520 struct slot *p_slot = info->p_slot;
0521
0522 mutex_lock(&p_slot->lock);
0523 switch (info->event_type) {
0524 case INT_BUTTON_PRESS:
0525 handle_button_press_event(p_slot);
0526 break;
0527 case INT_POWER_FAULT:
0528 ctrl_dbg(p_slot->ctrl, "%s: Power fault\n", __func__);
0529 p_slot->hpc_ops->set_attention_status(p_slot, 1);
0530 p_slot->hpc_ops->green_led_off(p_slot);
0531 break;
0532 default:
0533 update_slot_info(p_slot);
0534 break;
0535 }
0536 mutex_unlock(&p_slot->lock);
0537
0538 kfree(info);
0539 }
0540
0541
0542 static int shpchp_enable_slot (struct slot *p_slot)
0543 {
0544 u8 getstatus = 0;
0545 int rc, retval = -ENODEV;
0546 struct controller *ctrl = p_slot->ctrl;
0547
0548
0549 mutex_lock(&p_slot->ctrl->crit_sect);
0550 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
0551 if (rc || !getstatus) {
0552 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
0553 goto out;
0554 }
0555 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
0556 if (rc || getstatus) {
0557 ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
0558 goto out;
0559 }
0560 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
0561 if (rc || getstatus) {
0562 ctrl_info(ctrl, "Already enabled on slot(%s)\n",
0563 slot_name(p_slot));
0564 goto out;
0565 }
0566
0567 p_slot->is_a_board = 1;
0568
0569
0570 p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
0571 p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
0572 ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save);
0573 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
0574
0575 if ((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD &&
0576 p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458)
0577 && p_slot->ctrl->num_slots == 1) {
0578
0579 amd_pogo_errata_save_misc_reg(p_slot);
0580 retval = board_added(p_slot);
0581
0582 amd_pogo_errata_restore_misc_reg(p_slot);
0583 } else
0584 retval = board_added(p_slot);
0585
0586 if (retval) {
0587 p_slot->hpc_ops->get_adapter_status(p_slot,
0588 &(p_slot->presence_save));
0589 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
0590 }
0591
0592 update_slot_info(p_slot);
0593 out:
0594 mutex_unlock(&p_slot->ctrl->crit_sect);
0595 return retval;
0596 }
0597
0598
0599 static int shpchp_disable_slot (struct slot *p_slot)
0600 {
0601 u8 getstatus = 0;
0602 int rc, retval = -ENODEV;
0603 struct controller *ctrl = p_slot->ctrl;
0604
0605 if (!p_slot->ctrl)
0606 return -ENODEV;
0607
0608
0609 mutex_lock(&p_slot->ctrl->crit_sect);
0610
0611 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
0612 if (rc || !getstatus) {
0613 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
0614 goto out;
0615 }
0616 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
0617 if (rc || getstatus) {
0618 ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
0619 goto out;
0620 }
0621 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
0622 if (rc || !getstatus) {
0623 ctrl_info(ctrl, "Already disabled on slot(%s)\n",
0624 slot_name(p_slot));
0625 goto out;
0626 }
0627
0628 retval = remove_board(p_slot);
0629 update_slot_info(p_slot);
0630 out:
0631 mutex_unlock(&p_slot->ctrl->crit_sect);
0632 return retval;
0633 }
0634
0635 int shpchp_sysfs_enable_slot(struct slot *p_slot)
0636 {
0637 int retval = -ENODEV;
0638 struct controller *ctrl = p_slot->ctrl;
0639
0640 mutex_lock(&p_slot->lock);
0641 switch (p_slot->state) {
0642 case BLINKINGON_STATE:
0643 cancel_delayed_work(&p_slot->work);
0644 fallthrough;
0645 case STATIC_STATE:
0646 p_slot->state = POWERON_STATE;
0647 mutex_unlock(&p_slot->lock);
0648 retval = shpchp_enable_slot(p_slot);
0649 mutex_lock(&p_slot->lock);
0650 p_slot->state = STATIC_STATE;
0651 break;
0652 case POWERON_STATE:
0653 ctrl_info(ctrl, "Slot %s is already in powering on state\n",
0654 slot_name(p_slot));
0655 break;
0656 case BLINKINGOFF_STATE:
0657 case POWEROFF_STATE:
0658 ctrl_info(ctrl, "Already enabled on slot %s\n",
0659 slot_name(p_slot));
0660 break;
0661 default:
0662 ctrl_err(ctrl, "Not a valid state on slot %s\n",
0663 slot_name(p_slot));
0664 break;
0665 }
0666 mutex_unlock(&p_slot->lock);
0667
0668 return retval;
0669 }
0670
0671 int shpchp_sysfs_disable_slot(struct slot *p_slot)
0672 {
0673 int retval = -ENODEV;
0674 struct controller *ctrl = p_slot->ctrl;
0675
0676 mutex_lock(&p_slot->lock);
0677 switch (p_slot->state) {
0678 case BLINKINGOFF_STATE:
0679 cancel_delayed_work(&p_slot->work);
0680 fallthrough;
0681 case STATIC_STATE:
0682 p_slot->state = POWEROFF_STATE;
0683 mutex_unlock(&p_slot->lock);
0684 retval = shpchp_disable_slot(p_slot);
0685 mutex_lock(&p_slot->lock);
0686 p_slot->state = STATIC_STATE;
0687 break;
0688 case POWEROFF_STATE:
0689 ctrl_info(ctrl, "Slot %s is already in powering off state\n",
0690 slot_name(p_slot));
0691 break;
0692 case BLINKINGON_STATE:
0693 case POWERON_STATE:
0694 ctrl_info(ctrl, "Already disabled on slot %s\n",
0695 slot_name(p_slot));
0696 break;
0697 default:
0698 ctrl_err(ctrl, "Not a valid state on slot %s\n",
0699 slot_name(p_slot));
0700 break;
0701 }
0702 mutex_unlock(&p_slot->lock);
0703
0704 return retval;
0705 }