1253 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * IBM Hot Plug Controller Driver4 *5 * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation6 *7 * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)8 * Copyright (C) 2001-2003 IBM Corp.9 *10 * All rights reserved.11 *12 * Send feedback to <gregkh@us.ibm.com>13 *14 */15 16#include <linux/init.h>17#include <linux/module.h>18#include <linux/slab.h>19#include <linux/pci.h>20#include <linux/interrupt.h>21#include <linux/delay.h>22#include <linux/wait.h>23#include "../pci.h"24#include <asm/pci_x86.h> /* for struct irq_routing_table */25#include <asm/io_apic.h>26#include "ibmphp.h"27 28#define attn_on(sl) ibmphp_hpc_writeslot(sl, HPC_SLOT_ATTNON)29#define attn_off(sl) ibmphp_hpc_writeslot(sl, HPC_SLOT_ATTNOFF)30#define attn_LED_blink(sl) ibmphp_hpc_writeslot(sl, HPC_SLOT_BLINKLED)31#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot(sl, READ_REVLEVEL, rev)32#define get_hpc_options(sl, opt) ibmphp_hpc_readslot(sl, READ_HPCOPTIONS, opt)33 34#define DRIVER_VERSION "0.6"35#define DRIVER_DESC "IBM Hot Plug PCI Controller Driver"36 37int ibmphp_debug;38 39static bool debug;40module_param(debug, bool, S_IRUGO | S_IWUSR);41MODULE_PARM_DESC(debug, "Debugging mode enabled or not");42MODULE_LICENSE("GPL");43MODULE_DESCRIPTION(DRIVER_DESC);44 45struct pci_bus *ibmphp_pci_bus;46static int max_slots;47 48static int irqs[16]; /* PIC mode IRQs we're using so far (in case MPS49 * tables don't provide default info for empty slots */50 51static int init_flag;52 53static inline int get_cur_bus_info(struct slot **sl)54{55 int rc = 1;56 struct slot *slot_cur = *sl;57 58 debug("options = %x\n", slot_cur->ctrl->options);59 debug("revision = %x\n", slot_cur->ctrl->revision);60 61 if (READ_BUS_STATUS(slot_cur->ctrl))62 rc = ibmphp_hpc_readslot(slot_cur, READ_BUSSTATUS, NULL);63 64 if (rc)65 return rc;66 67 slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED(slot_cur->busstatus);68 if (READ_BUS_MODE(slot_cur->ctrl))69 slot_cur->bus_on->current_bus_mode =70 CURRENT_BUS_MODE(slot_cur->busstatus);71 else72 slot_cur->bus_on->current_bus_mode = 0xFF;73 74 debug("busstatus = %x, bus_speed = %x, bus_mode = %x\n",75 slot_cur->busstatus,76 slot_cur->bus_on->current_speed,77 slot_cur->bus_on->current_bus_mode);78 79 *sl = slot_cur;80 return 0;81}82 83static inline int slot_update(struct slot **sl)84{85 int rc;86 rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL);87 if (rc)88 return rc;89 if (!init_flag)90 rc = get_cur_bus_info(sl);91 return rc;92}93 94static int __init get_max_slots(void)95{96 struct slot *slot_cur;97 u8 slot_count = 0;98 99 list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {100 /* sometimes the hot-pluggable slots start with 4 (not always from 1) */101 slot_count = max(slot_count, slot_cur->number);102 }103 return slot_count;104}105 106/* This routine will put the correct slot->device information per slot. It's107 * called from initialization of the slot structures. It will also assign108 * interrupt numbers per each slot.109 * Parameters: struct slot110 * Returns 0 or errors111 */112int ibmphp_init_devno(struct slot **cur_slot)113{114 struct irq_routing_table *rtable;115 int len;116 int loop;117 int i;118 119 rtable = pcibios_get_irq_routing_table();120 if (!rtable) {121 err("no BIOS routing table...\n");122 return -ENOMEM;123 }124 125 len = (rtable->size - sizeof(struct irq_routing_table)) /126 sizeof(struct irq_info);127 128 if (!len) {129 kfree(rtable);130 return -1;131 }132 for (loop = 0; loop < len; loop++) {133 if ((*cur_slot)->number == rtable->slots[loop].slot &&134 (*cur_slot)->bus == rtable->slots[loop].bus) {135 (*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn);136 for (i = 0; i < 4; i++)137 (*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus,138 (int) (*cur_slot)->device, i);139 140 debug("(*cur_slot)->irq[0] = %x\n",141 (*cur_slot)->irq[0]);142 debug("(*cur_slot)->irq[1] = %x\n",143 (*cur_slot)->irq[1]);144 debug("(*cur_slot)->irq[2] = %x\n",145 (*cur_slot)->irq[2]);146 debug("(*cur_slot)->irq[3] = %x\n",147 (*cur_slot)->irq[3]);148 149 debug("rtable->exclusive_irqs = %x\n",150 rtable->exclusive_irqs);151 debug("rtable->slots[loop].irq[0].bitmap = %x\n",152 rtable->slots[loop].irq[0].bitmap);153 debug("rtable->slots[loop].irq[1].bitmap = %x\n",154 rtable->slots[loop].irq[1].bitmap);155 debug("rtable->slots[loop].irq[2].bitmap = %x\n",156 rtable->slots[loop].irq[2].bitmap);157 debug("rtable->slots[loop].irq[3].bitmap = %x\n",158 rtable->slots[loop].irq[3].bitmap);159 160 debug("rtable->slots[loop].irq[0].link = %x\n",161 rtable->slots[loop].irq[0].link);162 debug("rtable->slots[loop].irq[1].link = %x\n",163 rtable->slots[loop].irq[1].link);164 debug("rtable->slots[loop].irq[2].link = %x\n",165 rtable->slots[loop].irq[2].link);166 debug("rtable->slots[loop].irq[3].link = %x\n",167 rtable->slots[loop].irq[3].link);168 debug("end of init_devno\n");169 kfree(rtable);170 return 0;171 }172 }173 174 kfree(rtable);175 return -1;176}177 178static inline int power_on(struct slot *slot_cur)179{180 u8 cmd = HPC_SLOT_ON;181 int retval;182 183 retval = ibmphp_hpc_writeslot(slot_cur, cmd);184 if (retval) {185 err("power on failed\n");186 return retval;187 }188 if (CTLR_RESULT(slot_cur->ctrl->status)) {189 err("command not completed successfully in power_on\n");190 return -EIO;191 }192 msleep(3000); /* For ServeRAID cards, and some 66 PCI */193 return 0;194}195 196static inline int power_off(struct slot *slot_cur)197{198 u8 cmd = HPC_SLOT_OFF;199 int retval;200 201 retval = ibmphp_hpc_writeslot(slot_cur, cmd);202 if (retval) {203 err("power off failed\n");204 return retval;205 }206 if (CTLR_RESULT(slot_cur->ctrl->status)) {207 err("command not completed successfully in power_off\n");208 retval = -EIO;209 }210 return retval;211}212 213static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)214{215 int rc = 0;216 struct slot *pslot;217 u8 cmd = 0x00; /* avoid compiler warning */218 219 debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n",220 (ulong) hotplug_slot, value);221 ibmphp_lock_operations();222 223 224 if (hotplug_slot) {225 switch (value) {226 case HPC_SLOT_ATTN_OFF:227 cmd = HPC_SLOT_ATTNOFF;228 break;229 case HPC_SLOT_ATTN_ON:230 cmd = HPC_SLOT_ATTNON;231 break;232 case HPC_SLOT_ATTN_BLINK:233 cmd = HPC_SLOT_BLINKLED;234 break;235 default:236 rc = -ENODEV;237 err("set_attention_status - Error : invalid input [%x]\n",238 value);239 break;240 }241 if (rc == 0) {242 pslot = to_slot(hotplug_slot);243 rc = ibmphp_hpc_writeslot(pslot, cmd);244 }245 } else246 rc = -ENODEV;247 248 ibmphp_unlock_operations();249 250 debug("set_attention_status - Exit rc[%d]\n", rc);251 return rc;252}253 254static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)255{256 int rc = -ENODEV;257 struct slot *pslot;258 struct slot myslot;259 260 debug("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",261 (ulong) hotplug_slot, (ulong) value);262 263 ibmphp_lock_operations();264 if (hotplug_slot) {265 pslot = to_slot(hotplug_slot);266 memcpy(&myslot, pslot, sizeof(struct slot));267 rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,268 &myslot.status);269 if (!rc)270 rc = ibmphp_hpc_readslot(pslot, READ_EXTSLOTSTATUS,271 &myslot.ext_status);272 if (!rc)273 *value = SLOT_ATTN(myslot.status, myslot.ext_status);274 }275 276 ibmphp_unlock_operations();277 debug("get_attention_status - Exit rc[%d] value[%x]\n", rc, *value);278 return rc;279}280 281static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)282{283 int rc = -ENODEV;284 struct slot *pslot;285 struct slot myslot;286 287 debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",288 (ulong) hotplug_slot, (ulong) value);289 ibmphp_lock_operations();290 if (hotplug_slot) {291 pslot = to_slot(hotplug_slot);292 memcpy(&myslot, pslot, sizeof(struct slot));293 rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,294 &myslot.status);295 if (!rc)296 *value = SLOT_LATCH(myslot.status);297 }298 299 ibmphp_unlock_operations();300 debug("get_latch_status - Exit rc[%d] rc[%x] value[%x]\n",301 rc, rc, *value);302 return rc;303}304 305 306static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)307{308 int rc = -ENODEV;309 struct slot *pslot;310 struct slot myslot;311 312 debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",313 (ulong) hotplug_slot, (ulong) value);314 ibmphp_lock_operations();315 if (hotplug_slot) {316 pslot = to_slot(hotplug_slot);317 memcpy(&myslot, pslot, sizeof(struct slot));318 rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,319 &myslot.status);320 if (!rc)321 *value = SLOT_PWRGD(myslot.status);322 }323 324 ibmphp_unlock_operations();325 debug("get_power_status - Exit rc[%d] rc[%x] value[%x]\n",326 rc, rc, *value);327 return rc;328}329 330static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 *value)331{332 int rc = -ENODEV;333 struct slot *pslot;334 u8 present;335 struct slot myslot;336 337 debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",338 (ulong) hotplug_slot, (ulong) value);339 ibmphp_lock_operations();340 if (hotplug_slot) {341 pslot = to_slot(hotplug_slot);342 memcpy(&myslot, pslot, sizeof(struct slot));343 rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,344 &myslot.status);345 if (!rc) {346 present = SLOT_PRESENT(myslot.status);347 if (present == HPC_SLOT_EMPTY)348 *value = 0;349 else350 *value = 1;351 }352 }353 354 ibmphp_unlock_operations();355 debug("get_adapter_present - Exit rc[%d] value[%x]\n", rc, *value);356 return rc;357}358 359static int get_max_bus_speed(struct slot *slot)360{361 int rc = 0;362 u8 mode = 0;363 enum pci_bus_speed speed;364 struct pci_bus *bus = slot->hotplug_slot.pci_slot->bus;365 366 debug("%s - Entry slot[%p]\n", __func__, slot);367 368 ibmphp_lock_operations();369 mode = slot->supported_bus_mode;370 speed = slot->supported_speed;371 ibmphp_unlock_operations();372 373 switch (speed) {374 case BUS_SPEED_33:375 break;376 case BUS_SPEED_66:377 if (mode == BUS_MODE_PCIX)378 speed += 0x01;379 break;380 case BUS_SPEED_100:381 case BUS_SPEED_133:382 speed += 0x01;383 break;384 default:385 /* Note (will need to change): there would be soon 256, 512 also */386 rc = -ENODEV;387 }388 389 if (!rc)390 bus->max_bus_speed = speed;391 392 debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed);393 return rc;394}395 396/****************************************************************************397 * This routine will initialize the ops data structure used in the validate398 * function. It will also power off empty slots that are powered on since BIOS399 * leaves those on, albeit disconnected400 ****************************************************************************/401static int __init init_ops(void)402{403 struct slot *slot_cur;404 int retval;405 int rc;406 407 list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {408 debug("BEFORE GETTING SLOT STATUS, slot # %x\n",409 slot_cur->number);410 if (slot_cur->ctrl->revision == 0xFF)411 if (get_ctrl_revision(slot_cur,412 &slot_cur->ctrl->revision))413 return -1;414 415 if (slot_cur->bus_on->current_speed == 0xFF)416 if (get_cur_bus_info(&slot_cur))417 return -1;418 get_max_bus_speed(slot_cur);419 420 if (slot_cur->ctrl->options == 0xFF)421 if (get_hpc_options(slot_cur, &slot_cur->ctrl->options))422 return -1;423 424 retval = slot_update(&slot_cur);425 if (retval)426 return retval;427 428 debug("status = %x\n", slot_cur->status);429 debug("ext_status = %x\n", slot_cur->ext_status);430 debug("SLOT_POWER = %x\n", SLOT_POWER(slot_cur->status));431 debug("SLOT_PRESENT = %x\n", SLOT_PRESENT(slot_cur->status));432 debug("SLOT_LATCH = %x\n", SLOT_LATCH(slot_cur->status));433 434 if ((SLOT_PWRGD(slot_cur->status)) &&435 !(SLOT_PRESENT(slot_cur->status)) &&436 !(SLOT_LATCH(slot_cur->status))) {437 debug("BEFORE POWER OFF COMMAND\n");438 rc = power_off(slot_cur);439 if (rc)440 return rc;441 442 /* retval = slot_update(&slot_cur);443 * if (retval)444 * return retval;445 * ibmphp_update_slot_info(slot_cur);446 */447 }448 }449 init_flag = 0;450 return 0;451}452 453/* This operation will check whether the slot is within the bounds and454 * the operation is valid to perform on that slot455 * Parameters: slot, operation456 * Returns: 0 or error codes457 */458static int validate(struct slot *slot_cur, int opn)459{460 int number;461 int retval;462 463 if (!slot_cur)464 return -ENODEV;465 number = slot_cur->number;466 if ((number > max_slots) || (number < 0))467 return -EBADSLT;468 debug("slot_number in validate is %d\n", slot_cur->number);469 470 retval = slot_update(&slot_cur);471 if (retval)472 return retval;473 474 switch (opn) {475 case ENABLE:476 if (!(SLOT_PWRGD(slot_cur->status)) &&477 (SLOT_PRESENT(slot_cur->status)) &&478 !(SLOT_LATCH(slot_cur->status)))479 return 0;480 break;481 case DISABLE:482 if ((SLOT_PWRGD(slot_cur->status)) &&483 (SLOT_PRESENT(slot_cur->status)) &&484 !(SLOT_LATCH(slot_cur->status)))485 return 0;486 break;487 default:488 break;489 }490 err("validate failed....\n");491 return -EINVAL;492}493 494/****************************************************************************495 * This routine is for updating the data structures in the hotplug core496 * Parameters: struct slot497 * Returns: 0 or error498 ****************************************************************************/499int ibmphp_update_slot_info(struct slot *slot_cur)500{501 struct pci_bus *bus = slot_cur->hotplug_slot.pci_slot->bus;502 u8 bus_speed;503 u8 mode;504 505 bus_speed = slot_cur->bus_on->current_speed;506 mode = slot_cur->bus_on->current_bus_mode;507 508 switch (bus_speed) {509 case BUS_SPEED_33:510 break;511 case BUS_SPEED_66:512 if (mode == BUS_MODE_PCIX)513 bus_speed += 0x01;514 else if (mode == BUS_MODE_PCI)515 ;516 else517 bus_speed = PCI_SPEED_UNKNOWN;518 break;519 case BUS_SPEED_100:520 case BUS_SPEED_133:521 bus_speed += 0x01;522 break;523 default:524 bus_speed = PCI_SPEED_UNKNOWN;525 }526 527 bus->cur_bus_speed = bus_speed;528 // To do: bus_names529 530 return 0;531}532 533 534/******************************************************************************535 * This function will return the pci_func, given bus and devfunc, or NULL. It536 * is called from visit routines537 ******************************************************************************/538 539static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function)540{541 struct pci_func *func_cur;542 struct slot *slot_cur;543 list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {544 if (slot_cur->func) {545 func_cur = slot_cur->func;546 while (func_cur) {547 if ((func_cur->busno == busno) &&548 (func_cur->device == device) &&549 (func_cur->function == function))550 return func_cur;551 func_cur = func_cur->next;552 }553 }554 }555 return NULL;556}557 558/*************************************************************559 * This routine frees up memory used by struct slot, including560 * the pointers to pci_func, bus, hotplug_slot, controller,561 * and deregistering from the hotplug core562 *************************************************************/563static void free_slots(void)564{565 struct slot *slot_cur, *next;566 567 debug("%s -- enter\n", __func__);568 569 list_for_each_entry_safe(slot_cur, next, &ibmphp_slot_head,570 ibm_slot_list) {571 pci_hp_del(&slot_cur->hotplug_slot);572 slot_cur->ctrl = NULL;573 slot_cur->bus_on = NULL;574 575 /*576 * We don't want to actually remove the resources,577 * since ibmphp_free_resources() will do just that.578 */579 ibmphp_unconfigure_card(&slot_cur, -1);580 581 pci_hp_destroy(&slot_cur->hotplug_slot);582 kfree(slot_cur);583 }584 debug("%s -- exit\n", __func__);585}586 587static void ibm_unconfigure_device(struct pci_func *func)588{589 struct pci_dev *temp;590 u8 j;591 592 debug("inside %s\n", __func__);593 debug("func->device = %x, func->function = %x\n",594 func->device, func->function);595 debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0);596 597 pci_lock_rescan_remove();598 599 for (j = 0; j < 0x08; j++) {600 temp = pci_get_domain_bus_and_slot(0, func->busno,601 (func->device << 3) | j);602 if (temp) {603 pci_stop_and_remove_bus_device(temp);604 pci_dev_put(temp);605 }606 }607 608 pci_dev_put(func->dev);609 610 pci_unlock_rescan_remove();611}612 613/*614 * The following function is to fix kernel bug regarding615 * getting bus entries, here we manually add those primary616 * bus entries to kernel bus structure whenever apply617 */618static u8 bus_structure_fixup(u8 busno)619{620 struct pci_bus *bus, *b;621 struct pci_dev *dev;622 u16 l;623 624 if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num(busno)))625 return 1;626 627 bus = kmalloc(sizeof(*bus), GFP_KERNEL);628 if (!bus)629 return 1;630 631 dev = kmalloc(sizeof(*dev), GFP_KERNEL);632 if (!dev) {633 kfree(bus);634 return 1;635 }636 637 bus->number = busno;638 bus->ops = ibmphp_pci_bus->ops;639 dev->bus = bus;640 for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) {641 if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&642 (l != 0x0000) && (l != 0xffff)) {643 debug("%s - Inside bus_structure_fixup()\n",644 __func__);645 b = pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);646 if (!b)647 continue;648 649 pci_bus_add_devices(b);650 break;651 }652 }653 654 kfree(dev);655 kfree(bus);656 657 return 0;658}659 660static int ibm_configure_device(struct pci_func *func)661{662 struct pci_bus *child;663 int num;664 int flag = 0; /* this is to make sure we don't double scan the bus,665 for bridged devices primarily */666 667 pci_lock_rescan_remove();668 669 if (!(bus_structure_fixup(func->busno)))670 flag = 1;671 if (func->dev == NULL)672 func->dev = pci_get_domain_bus_and_slot(0, func->busno,673 PCI_DEVFN(func->device, func->function));674 675 if (func->dev == NULL) {676 struct pci_bus *bus = pci_find_bus(0, func->busno);677 if (!bus)678 goto out;679 680 num = pci_scan_slot(bus,681 PCI_DEVFN(func->device, func->function));682 if (num)683 pci_bus_add_devices(bus);684 685 func->dev = pci_get_domain_bus_and_slot(0, func->busno,686 PCI_DEVFN(func->device, func->function));687 if (func->dev == NULL) {688 err("ERROR... : pci_dev still NULL\n");689 goto out;690 }691 }692 if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {693 pci_hp_add_bridge(func->dev);694 child = func->dev->subordinate;695 if (child)696 pci_bus_add_devices(child);697 }698 699 out:700 pci_unlock_rescan_remove();701 return 0;702}703 704/*******************************************************705 * Returns whether the bus is empty or not706 *******************************************************/707static int is_bus_empty(struct slot *slot_cur)708{709 int rc;710 struct slot *tmp_slot;711 u8 i = slot_cur->bus_on->slot_min;712 713 while (i <= slot_cur->bus_on->slot_max) {714 if (i == slot_cur->number) {715 i++;716 continue;717 }718 tmp_slot = ibmphp_get_slot_from_physical_num(i);719 if (!tmp_slot)720 return 0;721 rc = slot_update(&tmp_slot);722 if (rc)723 return 0;724 if (SLOT_PRESENT(tmp_slot->status) &&725 SLOT_PWRGD(tmp_slot->status))726 return 0;727 i++;728 }729 return 1;730}731 732/***********************************************************733 * If the HPC permits and the bus currently empty, tries to set the734 * bus speed and mode at the maximum card and bus capability735 * Parameters: slot736 * Returns: bus is set (0) or error code737 ***********************************************************/738static int set_bus(struct slot *slot_cur)739{740 int rc;741 u8 speed;742 u8 cmd = 0x0;743 int retval;744 static const struct pci_device_id ciobx[] = {745 { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 0x0101) },746 { },747 };748 749 debug("%s - entry slot # %d\n", __func__, slot_cur->number);750 if (SET_BUS_STATUS(slot_cur->ctrl) && is_bus_empty(slot_cur)) {751 rc = slot_update(&slot_cur);752 if (rc)753 return rc;754 speed = SLOT_SPEED(slot_cur->ext_status);755 debug("ext_status = %x, speed = %x\n", slot_cur->ext_status, speed);756 switch (speed) {757 case HPC_SLOT_SPEED_33:758 cmd = HPC_BUS_33CONVMODE;759 break;760 case HPC_SLOT_SPEED_66:761 if (SLOT_PCIX(slot_cur->ext_status)) {762 if ((slot_cur->supported_speed >= BUS_SPEED_66) &&763 (slot_cur->supported_bus_mode == BUS_MODE_PCIX))764 cmd = HPC_BUS_66PCIXMODE;765 else if (!SLOT_BUS_MODE(slot_cur->ext_status))766 /* if max slot/bus capability is 66 pci767 and there's no bus mode mismatch, then768 the adapter supports 66 pci */769 cmd = HPC_BUS_66CONVMODE;770 else771 cmd = HPC_BUS_33CONVMODE;772 } else {773 if (slot_cur->supported_speed >= BUS_SPEED_66)774 cmd = HPC_BUS_66CONVMODE;775 else776 cmd = HPC_BUS_33CONVMODE;777 }778 break;779 case HPC_SLOT_SPEED_133:780 switch (slot_cur->supported_speed) {781 case BUS_SPEED_33:782 cmd = HPC_BUS_33CONVMODE;783 break;784 case BUS_SPEED_66:785 if (slot_cur->supported_bus_mode == BUS_MODE_PCIX)786 cmd = HPC_BUS_66PCIXMODE;787 else788 cmd = HPC_BUS_66CONVMODE;789 break;790 case BUS_SPEED_100:791 cmd = HPC_BUS_100PCIXMODE;792 break;793 case BUS_SPEED_133:794 /* This is to take care of the bug in CIOBX chip */795 if (pci_dev_present(ciobx))796 ibmphp_hpc_writeslot(slot_cur,797 HPC_BUS_100PCIXMODE);798 cmd = HPC_BUS_133PCIXMODE;799 break;800 default:801 err("Wrong bus speed\n");802 return -ENODEV;803 }804 break;805 default:806 err("wrong slot speed\n");807 return -ENODEV;808 }809 debug("setting bus speed for slot %d, cmd %x\n",810 slot_cur->number, cmd);811 retval = ibmphp_hpc_writeslot(slot_cur, cmd);812 if (retval) {813 err("setting bus speed failed\n");814 return retval;815 }816 if (CTLR_RESULT(slot_cur->ctrl->status)) {817 err("command not completed successfully in set_bus\n");818 return -EIO;819 }820 }821 /* This is for x440, once Brandon fixes the firmware,822 will not need this delay */823 msleep(1000);824 debug("%s -Exit\n", __func__);825 return 0;826}827 828/* This routine checks the bus limitations that the slot is on from the BIOS.829 * This is used in deciding whether or not to power up the slot.830 * (electrical/spec limitations. For example, >1 133 MHz or >2 66 PCI cards on831 * same bus)832 * Parameters: slot833 * Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus834 */835static int check_limitations(struct slot *slot_cur)836{837 u8 i;838 struct slot *tmp_slot;839 u8 count = 0;840 u8 limitation = 0;841 842 for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) {843 tmp_slot = ibmphp_get_slot_from_physical_num(i);844 if (!tmp_slot)845 return -ENODEV;846 if ((SLOT_PWRGD(tmp_slot->status)) &&847 !(SLOT_CONNECT(tmp_slot->status)))848 count++;849 }850 get_cur_bus_info(&slot_cur);851 switch (slot_cur->bus_on->current_speed) {852 case BUS_SPEED_33:853 limitation = slot_cur->bus_on->slots_at_33_conv;854 break;855 case BUS_SPEED_66:856 if (slot_cur->bus_on->current_bus_mode == BUS_MODE_PCIX)857 limitation = slot_cur->bus_on->slots_at_66_pcix;858 else859 limitation = slot_cur->bus_on->slots_at_66_conv;860 break;861 case BUS_SPEED_100:862 limitation = slot_cur->bus_on->slots_at_100_pcix;863 break;864 case BUS_SPEED_133:865 limitation = slot_cur->bus_on->slots_at_133_pcix;866 break;867 }868 869 if ((count + 1) > limitation)870 return -EINVAL;871 return 0;872}873 874static inline void print_card_capability(struct slot *slot_cur)875{876 info("capability of the card is ");877 if ((slot_cur->ext_status & CARD_INFO) == PCIX133)878 info(" 133 MHz PCI-X\n");879 else if ((slot_cur->ext_status & CARD_INFO) == PCIX66)880 info(" 66 MHz PCI-X\n");881 else if ((slot_cur->ext_status & CARD_INFO) == PCI66)882 info(" 66 MHz PCI\n");883 else884 info(" 33 MHz PCI\n");885 886}887 888/* This routine will power on the slot, configure the device(s) and find the889 * drivers for them.890 * Parameters: hotplug_slot891 * Returns: 0 or failure codes892 */893static int enable_slot(struct hotplug_slot *hs)894{895 int rc, i, rcpr;896 struct slot *slot_cur;897 u8 function;898 struct pci_func *tmp_func;899 900 ibmphp_lock_operations();901 902 debug("ENABLING SLOT........\n");903 slot_cur = to_slot(hs);904 905 rc = validate(slot_cur, ENABLE);906 if (rc) {907 err("validate function failed\n");908 goto error_nopower;909 }910 911 attn_LED_blink(slot_cur);912 913 rc = set_bus(slot_cur);914 if (rc) {915 err("was not able to set the bus\n");916 goto error_nopower;917 }918 919 /*-----------------debugging------------------------------*/920 get_cur_bus_info(&slot_cur);921 debug("the current bus speed right after set_bus = %x\n",922 slot_cur->bus_on->current_speed);923 /*----------------------------------------------------------*/924 925 rc = check_limitations(slot_cur);926 if (rc) {927 err("Adding this card exceeds the limitations of this bus.\n");928 err("(i.e., >1 133MHz cards running on same bus, or >2 66 PCI cards running on same bus.\n");929 err("Try hot-adding into another bus\n");930 rc = -EINVAL;931 goto error_nopower;932 }933 934 rc = power_on(slot_cur);935 936 if (rc) {937 err("something wrong when powering up... please see below for details\n");938 /* need to turn off before on, otherwise, blinking overwrites */939 attn_off(slot_cur);940 attn_on(slot_cur);941 if (slot_update(&slot_cur)) {942 attn_off(slot_cur);943 attn_on(slot_cur);944 rc = -ENODEV;945 goto exit;946 }947 /* Check to see the error of why it failed */948 if ((SLOT_POWER(slot_cur->status)) &&949 !(SLOT_PWRGD(slot_cur->status)))950 err("power fault occurred trying to power up\n");951 else if (SLOT_BUS_SPEED(slot_cur->status)) {952 err("bus speed mismatch occurred. please check current bus speed and card capability\n");953 print_card_capability(slot_cur);954 } else if (SLOT_BUS_MODE(slot_cur->ext_status)) {955 err("bus mode mismatch occurred. please check current bus mode and card capability\n");956 print_card_capability(slot_cur);957 }958 ibmphp_update_slot_info(slot_cur);959 goto exit;960 }961 debug("after power_on\n");962 /*-----------------------debugging---------------------------*/963 get_cur_bus_info(&slot_cur);964 debug("the current bus speed right after power_on = %x\n",965 slot_cur->bus_on->current_speed);966 /*----------------------------------------------------------*/967 968 rc = slot_update(&slot_cur);969 if (rc)970 goto error_power;971 972 rc = -EINVAL;973 if (SLOT_POWER(slot_cur->status) && !(SLOT_PWRGD(slot_cur->status))) {974 err("power fault occurred trying to power up...\n");975 goto error_power;976 }977 if (SLOT_POWER(slot_cur->status) && (SLOT_BUS_SPEED(slot_cur->status))) {978 err("bus speed mismatch occurred. please check current bus speed and card capability\n");979 print_card_capability(slot_cur);980 goto error_power;981 }982 /* Don't think this case will happen after above checks...983 * but just in case, for paranoia sake */984 if (!(SLOT_POWER(slot_cur->status))) {985 err("power on failed...\n");986 goto error_power;987 }988 989 slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);990 if (!slot_cur->func) {991 /* do update_slot_info here? */992 rc = -ENOMEM;993 goto error_power;994 }995 slot_cur->func->busno = slot_cur->bus;996 slot_cur->func->device = slot_cur->device;997 for (i = 0; i < 4; i++)998 slot_cur->func->irq[i] = slot_cur->irq[i];999 1000 debug("b4 configure_card, slot_cur->bus = %x, slot_cur->device = %x\n",1001 slot_cur->bus, slot_cur->device);1002 1003 if (ibmphp_configure_card(slot_cur->func, slot_cur->number)) {1004 err("configure_card was unsuccessful...\n");1005 /* true because don't need to actually deallocate resources,1006 * just remove references */1007 ibmphp_unconfigure_card(&slot_cur, 1);1008 debug("after unconfigure_card\n");1009 slot_cur->func = NULL;1010 rc = -ENOMEM;1011 goto error_power;1012 }1013 1014 function = 0x00;1015 do {1016 tmp_func = ibm_slot_find(slot_cur->bus, slot_cur->func->device,1017 function++);1018 if (tmp_func && !(tmp_func->dev))1019 ibm_configure_device(tmp_func);1020 } while (tmp_func);1021 1022 attn_off(slot_cur);1023 if (slot_update(&slot_cur)) {1024 rc = -EFAULT;1025 goto exit;1026 }1027 ibmphp_print_test();1028 rc = ibmphp_update_slot_info(slot_cur);1029exit:1030 ibmphp_unlock_operations();1031 return rc;1032 1033error_nopower:1034 attn_off(slot_cur); /* need to turn off if was blinking b4 */1035 attn_on(slot_cur);1036error_cont:1037 rcpr = slot_update(&slot_cur);1038 if (rcpr) {1039 rc = rcpr;1040 goto exit;1041 }1042 ibmphp_update_slot_info(slot_cur);1043 goto exit;1044 1045error_power:1046 attn_off(slot_cur); /* need to turn off if was blinking b4 */1047 attn_on(slot_cur);1048 rcpr = power_off(slot_cur);1049 if (rcpr) {1050 rc = rcpr;1051 goto exit;1052 }1053 goto error_cont;1054}1055 1056/**************************************************************1057* HOT REMOVING ADAPTER CARD *1058* INPUT: POINTER TO THE HOTPLUG SLOT STRUCTURE *1059* OUTPUT: SUCCESS 0 ; FAILURE: UNCONFIGURE , VALIDATE *1060* DISABLE POWER , *1061**************************************************************/1062static int ibmphp_disable_slot(struct hotplug_slot *hotplug_slot)1063{1064 struct slot *slot = to_slot(hotplug_slot);1065 int rc;1066 1067 ibmphp_lock_operations();1068 rc = ibmphp_do_disable_slot(slot);1069 ibmphp_unlock_operations();1070 return rc;1071}1072 1073int ibmphp_do_disable_slot(struct slot *slot_cur)1074{1075 int rc;1076 u8 flag;1077 1078 debug("DISABLING SLOT...\n");1079 1080 if ((slot_cur == NULL) || (slot_cur->ctrl == NULL))1081 return -ENODEV;1082 1083 flag = slot_cur->flag;1084 slot_cur->flag = 1;1085 1086 if (flag == 1) {1087 rc = validate(slot_cur, DISABLE);1088 /* checking if powered off already & valid slot # */1089 if (rc)1090 goto error;1091 }1092 attn_LED_blink(slot_cur);1093 1094 if (slot_cur->func == NULL) {1095 /* We need this for functions that were there on bootup */1096 slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);1097 if (!slot_cur->func) {1098 rc = -ENOMEM;1099 goto error;1100 }1101 slot_cur->func->busno = slot_cur->bus;1102 slot_cur->func->device = slot_cur->device;1103 }1104 1105 ibm_unconfigure_device(slot_cur->func);1106 1107 /*1108 * If we got here from latch suddenly opening on operating card or1109 * a power fault, there's no power to the card, so cannot1110 * read from it to determine what resources it occupied. This operation1111 * is forbidden anyhow. The best we can do is remove it from kernel1112 * lists at least */1113 1114 if (!flag) {1115 attn_off(slot_cur);1116 return 0;1117 }1118 1119 rc = ibmphp_unconfigure_card(&slot_cur, 0);1120 slot_cur->func = NULL;1121 debug("in disable_slot. after unconfigure_card\n");1122 if (rc) {1123 err("could not unconfigure card.\n");1124 goto error;1125 }1126 1127 rc = ibmphp_hpc_writeslot(slot_cur, HPC_SLOT_OFF);1128 if (rc)1129 goto error;1130 1131 attn_off(slot_cur);1132 rc = slot_update(&slot_cur);1133 if (rc)1134 goto exit;1135 1136 rc = ibmphp_update_slot_info(slot_cur);1137 ibmphp_print_test();1138exit:1139 return rc;1140 1141error:1142 /* Need to turn off if was blinking b4 */1143 attn_off(slot_cur);1144 attn_on(slot_cur);1145 if (slot_update(&slot_cur)) {1146 rc = -EFAULT;1147 goto exit;1148 }1149 if (flag)1150 ibmphp_update_slot_info(slot_cur);1151 goto exit;1152}1153 1154const struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {1155 .set_attention_status = set_attention_status,1156 .enable_slot = enable_slot,1157 .disable_slot = ibmphp_disable_slot,1158 .hardware_test = NULL,1159 .get_power_status = get_power_status,1160 .get_attention_status = get_attention_status,1161 .get_latch_status = get_latch_status,1162 .get_adapter_status = get_adapter_present,1163};1164 1165static void ibmphp_unload(void)1166{1167 free_slots();1168 debug("after slots\n");1169 ibmphp_free_resources();1170 debug("after resources\n");1171 ibmphp_free_bus_info_queue();1172 debug("after bus info\n");1173 ibmphp_free_ebda_hpc_queue();1174 debug("after ebda hpc\n");1175 ibmphp_free_ebda_pci_rsrc_queue();1176 debug("after ebda pci rsrc\n");1177 kfree(ibmphp_pci_bus);1178}1179 1180static int __init ibmphp_init(void)1181{1182 struct pci_bus *bus;1183 int i = 0;1184 int rc = 0;1185 1186 init_flag = 1;1187 1188 info(DRIVER_DESC " version: " DRIVER_VERSION "\n");1189 1190 ibmphp_pci_bus = kmalloc(sizeof(*ibmphp_pci_bus), GFP_KERNEL);1191 if (!ibmphp_pci_bus) {1192 rc = -ENOMEM;1193 goto exit;1194 }1195 1196 bus = pci_find_bus(0, 0);1197 if (!bus) {1198 err("Can't find the root pci bus, can not continue\n");1199 rc = -ENODEV;1200 goto error;1201 }1202 memcpy(ibmphp_pci_bus, bus, sizeof(*ibmphp_pci_bus));1203 1204 ibmphp_debug = debug;1205 1206 for (i = 0; i < 16; i++)1207 irqs[i] = 0;1208 1209 rc = ibmphp_access_ebda();1210 if (rc)1211 goto error;1212 debug("after ibmphp_access_ebda()\n");1213 1214 rc = ibmphp_rsrc_init();1215 if (rc)1216 goto error;1217 debug("AFTER Resource & EBDA INITIALIZATIONS\n");1218 1219 max_slots = get_max_slots();1220 1221 rc = ibmphp_register_pci();1222 if (rc)1223 goto error;1224 1225 if (init_ops()) {1226 rc = -ENODEV;1227 goto error;1228 }1229 1230 ibmphp_print_test();1231 rc = ibmphp_hpc_start_poll_thread();1232 if (rc)1233 goto error;1234 1235exit:1236 return rc;1237 1238error:1239 ibmphp_unload();1240 goto exit;1241}1242 1243static void __exit ibmphp_exit(void)1244{1245 ibmphp_hpc_stop_poll_thread();1246 debug("after polling\n");1247 ibmphp_unload();1248 debug("done\n");1249}1250 1251module_init(ibmphp_init);1252module_exit(ibmphp_exit);1253