2912 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Compaq Hot Plug Controller Driver4 *5 * Copyright (C) 1995,2001 Compaq Computer Corporation6 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)7 * Copyright (C) 2001 IBM Corp.8 *9 * All rights reserved.10 *11 * Send feedback to <greg@kroah.com>12 *13 */14 15#include <linux/module.h>16#include <linux/kernel.h>17#include <linux/types.h>18#include <linux/slab.h>19#include <linux/workqueue.h>20#include <linux/interrupt.h>21#include <linux/delay.h>22#include <linux/wait.h>23#include <linux/pci.h>24#include <linux/pci_hotplug.h>25#include <linux/kthread.h>26#include "cpqphp.h"27 28static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,29 u8 behind_bridge, struct resource_lists *resources);30static int configure_new_function(struct controller *ctrl, struct pci_func *func,31 u8 behind_bridge, struct resource_lists *resources);32static void interrupt_event_handler(struct controller *ctrl);33 34 35static struct task_struct *cpqhp_event_thread;36static struct timer_list *pushbutton_pending; /* = NULL */37 38/* delay is in jiffies to wait for */39static void long_delay(int delay)40{41 /*42 * XXX(hch): if someone is bored please convert all callers43 * to call msleep_interruptible directly. They really want44 * to specify timeouts in natural units and spend a lot of45 * effort converting them to jiffies..46 */47 msleep_interruptible(jiffies_to_msecs(delay));48}49 50 51/* FIXME: The following line needs to be somewhere else... */52#define WRONG_BUS_FREQUENCY 0x0753static u8 handle_switch_change(u8 change, struct controller *ctrl)54{55 int hp_slot;56 u8 rc = 0;57 u16 temp_word;58 struct pci_func *func;59 struct event_info *taskInfo;60 61 if (!change)62 return 0;63 64 /* Switch Change */65 dbg("cpqsbd: Switch interrupt received.\n");66 67 for (hp_slot = 0; hp_slot < 6; hp_slot++) {68 if (change & (0x1L << hp_slot)) {69 /*70 * this one changed.71 */72 func = cpqhp_slot_find(ctrl->bus,73 (hp_slot + ctrl->slot_device_offset), 0);74 75 /* this is the structure that tells the worker thread76 * what to do77 */78 taskInfo = &(ctrl->event_queue[ctrl->next_event]);79 ctrl->next_event = (ctrl->next_event + 1) % 10;80 taskInfo->hp_slot = hp_slot;81 82 rc++;83 84 temp_word = ctrl->ctrl_int_comp >> 16;85 func->presence_save = (temp_word >> hp_slot) & 0x01;86 func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;87 88 if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {89 /*90 * Switch opened91 */92 93 func->switch_save = 0;94 95 taskInfo->event_type = INT_SWITCH_OPEN;96 } else {97 /*98 * Switch closed99 */100 101 func->switch_save = 0x10;102 103 taskInfo->event_type = INT_SWITCH_CLOSE;104 }105 }106 }107 108 return rc;109}110 111/**112 * cpqhp_find_slot - find the struct slot of given device113 * @ctrl: scan lots of this controller114 * @device: the device id to find115 */116static struct slot *cpqhp_find_slot(struct controller *ctrl, u8 device)117{118 struct slot *slot = ctrl->slot;119 120 while (slot && (slot->device != device))121 slot = slot->next;122 123 return slot;124}125 126 127static u8 handle_presence_change(u16 change, struct controller *ctrl)128{129 int hp_slot;130 u8 rc = 0;131 u8 temp_byte;132 u16 temp_word;133 struct pci_func *func;134 struct event_info *taskInfo;135 struct slot *p_slot;136 137 if (!change)138 return 0;139 140 /*141 * Presence Change142 */143 dbg("cpqsbd: Presence/Notify input change.\n");144 dbg(" Changed bits are 0x%4.4x\n", change);145 146 for (hp_slot = 0; hp_slot < 6; hp_slot++) {147 if (change & (0x0101 << hp_slot)) {148 /*149 * this one changed.150 */151 func = cpqhp_slot_find(ctrl->bus,152 (hp_slot + ctrl->slot_device_offset), 0);153 154 taskInfo = &(ctrl->event_queue[ctrl->next_event]);155 ctrl->next_event = (ctrl->next_event + 1) % 10;156 taskInfo->hp_slot = hp_slot;157 158 rc++;159 160 p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));161 if (!p_slot)162 return 0;163 164 /* If the switch closed, must be a button165 * If not in button mode, nevermind166 */167 if (func->switch_save && (ctrl->push_button == 1)) {168 temp_word = ctrl->ctrl_int_comp >> 16;169 temp_byte = (temp_word >> hp_slot) & 0x01;170 temp_byte |= (temp_word >> (hp_slot + 7)) & 0x02;171 172 if (temp_byte != func->presence_save) {173 /*174 * button Pressed (doesn't do anything)175 */176 dbg("hp_slot %d button pressed\n", hp_slot);177 taskInfo->event_type = INT_BUTTON_PRESS;178 } else {179 /*180 * button Released - TAKE ACTION!!!!181 */182 dbg("hp_slot %d button released\n", hp_slot);183 taskInfo->event_type = INT_BUTTON_RELEASE;184 185 /* Cancel if we are still blinking */186 if ((p_slot->state == BLINKINGON_STATE)187 || (p_slot->state == BLINKINGOFF_STATE)) {188 taskInfo->event_type = INT_BUTTON_CANCEL;189 dbg("hp_slot %d button cancel\n", hp_slot);190 } else if ((p_slot->state == POWERON_STATE)191 || (p_slot->state == POWEROFF_STATE)) {192 /* info(msg_button_ignore, p_slot->number); */193 taskInfo->event_type = INT_BUTTON_IGNORE;194 dbg("hp_slot %d button ignore\n", hp_slot);195 }196 }197 } else {198 /* Switch is open, assume a presence change199 * Save the presence state200 */201 temp_word = ctrl->ctrl_int_comp >> 16;202 func->presence_save = (temp_word >> hp_slot) & 0x01;203 func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;204 205 if ((!(ctrl->ctrl_int_comp & (0x010000 << hp_slot))) ||206 (!(ctrl->ctrl_int_comp & (0x01000000 << hp_slot)))) {207 /* Present */208 taskInfo->event_type = INT_PRESENCE_ON;209 } else {210 /* Not Present */211 taskInfo->event_type = INT_PRESENCE_OFF;212 }213 }214 }215 }216 217 return rc;218}219 220 221static u8 handle_power_fault(u8 change, struct controller *ctrl)222{223 int hp_slot;224 u8 rc = 0;225 struct pci_func *func;226 struct event_info *taskInfo;227 228 if (!change)229 return 0;230 231 /*232 * power fault233 */234 235 info("power fault interrupt\n");236 237 for (hp_slot = 0; hp_slot < 6; hp_slot++) {238 if (change & (0x01 << hp_slot)) {239 /*240 * this one changed.241 */242 func = cpqhp_slot_find(ctrl->bus,243 (hp_slot + ctrl->slot_device_offset), 0);244 245 taskInfo = &(ctrl->event_queue[ctrl->next_event]);246 ctrl->next_event = (ctrl->next_event + 1) % 10;247 taskInfo->hp_slot = hp_slot;248 249 rc++;250 251 if (ctrl->ctrl_int_comp & (0x00000100 << hp_slot)) {252 /*253 * power fault Cleared254 */255 func->status = 0x00;256 257 taskInfo->event_type = INT_POWER_FAULT_CLEAR;258 } else {259 /*260 * power fault261 */262 taskInfo->event_type = INT_POWER_FAULT;263 264 if (ctrl->rev < 4) {265 amber_LED_on(ctrl, hp_slot);266 green_LED_off(ctrl, hp_slot);267 set_SOGO(ctrl);268 269 /* this is a fatal condition, we want270 * to crash the machine to protect from271 * data corruption. simulated_NMI272 * shouldn't ever return */273 /* FIXME274 simulated_NMI(hp_slot, ctrl); */275 276 /* The following code causes a software277 * crash just in case simulated_NMI did278 * return */279 /*FIXME280 panic(msg_power_fault); */281 } else {282 /* set power fault status for this board */283 func->status = 0xFF;284 info("power fault bit %x set\n", hp_slot);285 }286 }287 }288 }289 290 return rc;291}292 293 294/**295 * sort_by_size - sort nodes on the list by their length, smallest first.296 * @head: list to sort297 */298static int sort_by_size(struct pci_resource **head)299{300 struct pci_resource *current_res;301 struct pci_resource *next_res;302 int out_of_order = 1;303 304 if (!(*head))305 return 1;306 307 if (!((*head)->next))308 return 0;309 310 while (out_of_order) {311 out_of_order = 0;312 313 /* Special case for swapping list head */314 if (((*head)->next) &&315 ((*head)->length > (*head)->next->length)) {316 out_of_order++;317 current_res = *head;318 *head = (*head)->next;319 current_res->next = (*head)->next;320 (*head)->next = current_res;321 }322 323 current_res = *head;324 325 while (current_res->next && current_res->next->next) {326 if (current_res->next->length > current_res->next->next->length) {327 out_of_order++;328 next_res = current_res->next;329 current_res->next = current_res->next->next;330 current_res = current_res->next;331 next_res->next = current_res->next;332 current_res->next = next_res;333 } else334 current_res = current_res->next;335 }336 } /* End of out_of_order loop */337 338 return 0;339}340 341 342/**343 * sort_by_max_size - sort nodes on the list by their length, largest first.344 * @head: list to sort345 */346static int sort_by_max_size(struct pci_resource **head)347{348 struct pci_resource *current_res;349 struct pci_resource *next_res;350 int out_of_order = 1;351 352 if (!(*head))353 return 1;354 355 if (!((*head)->next))356 return 0;357 358 while (out_of_order) {359 out_of_order = 0;360 361 /* Special case for swapping list head */362 if (((*head)->next) &&363 ((*head)->length < (*head)->next->length)) {364 out_of_order++;365 current_res = *head;366 *head = (*head)->next;367 current_res->next = (*head)->next;368 (*head)->next = current_res;369 }370 371 current_res = *head;372 373 while (current_res->next && current_res->next->next) {374 if (current_res->next->length < current_res->next->next->length) {375 out_of_order++;376 next_res = current_res->next;377 current_res->next = current_res->next->next;378 current_res = current_res->next;379 next_res->next = current_res->next;380 current_res->next = next_res;381 } else382 current_res = current_res->next;383 }384 } /* End of out_of_order loop */385 386 return 0;387}388 389 390/**391 * do_pre_bridge_resource_split - find node of resources that are unused392 * @head: new list head393 * @orig_head: original list head394 * @alignment: max node size (?)395 */396static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **head,397 struct pci_resource **orig_head, u32 alignment)398{399 struct pci_resource *prevnode = NULL;400 struct pci_resource *node;401 struct pci_resource *split_node;402 u32 rc;403 u32 temp_dword;404 dbg("do_pre_bridge_resource_split\n");405 406 if (!(*head) || !(*orig_head))407 return NULL;408 409 rc = cpqhp_resource_sort_and_combine(head);410 411 if (rc)412 return NULL;413 414 if ((*head)->base != (*orig_head)->base)415 return NULL;416 417 if ((*head)->length == (*orig_head)->length)418 return NULL;419 420 421 /* If we got here, there the bridge requires some of the resource, but422 * we may be able to split some off of the front423 */424 425 node = *head;426 427 if (node->length & (alignment - 1)) {428 /* this one isn't an aligned length, so we'll make a new entry429 * and split it up.430 */431 split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);432 433 if (!split_node)434 return NULL;435 436 temp_dword = (node->length | (alignment-1)) + 1 - alignment;437 438 split_node->base = node->base;439 split_node->length = temp_dword;440 441 node->length -= temp_dword;442 node->base += split_node->length;443 444 /* Put it in the list */445 *head = split_node;446 split_node->next = node;447 }448 449 if (node->length < alignment)450 return NULL;451 452 /* Now unlink it */453 if (*head == node) {454 *head = node->next;455 } else {456 prevnode = *head;457 while (prevnode->next != node)458 prevnode = prevnode->next;459 460 prevnode->next = node->next;461 }462 node->next = NULL;463 464 return node;465}466 467 468/**469 * do_bridge_resource_split - find one node of resources that aren't in use470 * @head: list head471 * @alignment: max node size (?)472 */473static struct pci_resource *do_bridge_resource_split(struct pci_resource **head, u32 alignment)474{475 struct pci_resource *prevnode = NULL;476 struct pci_resource *node;477 u32 rc;478 u32 temp_dword;479 480 rc = cpqhp_resource_sort_and_combine(head);481 482 if (rc)483 return NULL;484 485 node = *head;486 487 while (node->next) {488 prevnode = node;489 node = node->next;490 kfree(prevnode);491 }492 493 if (node->length < alignment)494 goto error;495 496 if (node->base & (alignment - 1)) {497 /* Short circuit if adjusted size is too small */498 temp_dword = (node->base | (alignment-1)) + 1;499 if ((node->length - (temp_dword - node->base)) < alignment)500 goto error;501 502 node->length -= (temp_dword - node->base);503 node->base = temp_dword;504 }505 506 if (node->length & (alignment - 1))507 /* There's stuff in use after this node */508 goto error;509 510 return node;511error:512 kfree(node);513 return NULL;514}515 516 517/**518 * get_io_resource - find first node of given size not in ISA aliasing window.519 * @head: list to search520 * @size: size of node to find, must be a power of two.521 *522 * Description: This function sorts the resource list by size and then523 * returns the first node of "size" length that is not in the ISA aliasing524 * window. If it finds a node larger than "size" it will split it up.525 */526static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size)527{528 struct pci_resource *prevnode;529 struct pci_resource *node;530 struct pci_resource *split_node;531 u32 temp_dword;532 533 if (!(*head))534 return NULL;535 536 if (cpqhp_resource_sort_and_combine(head))537 return NULL;538 539 if (sort_by_size(head))540 return NULL;541 542 for (node = *head; node; node = node->next) {543 if (node->length < size)544 continue;545 546 if (node->base & (size - 1)) {547 /* this one isn't base aligned properly548 * so we'll make a new entry and split it up549 */550 temp_dword = (node->base | (size-1)) + 1;551 552 /* Short circuit if adjusted size is too small */553 if ((node->length - (temp_dword - node->base)) < size)554 continue;555 556 split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);557 558 if (!split_node)559 return NULL;560 561 split_node->base = node->base;562 split_node->length = temp_dword - node->base;563 node->base = temp_dword;564 node->length -= split_node->length;565 566 /* Put it in the list */567 split_node->next = node->next;568 node->next = split_node;569 } /* End of non-aligned base */570 571 /* Don't need to check if too small since we already did */572 if (node->length > size) {573 /* this one is longer than we need574 * so we'll make a new entry and split it up575 */576 split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);577 578 if (!split_node)579 return NULL;580 581 split_node->base = node->base + size;582 split_node->length = node->length - size;583 node->length = size;584 585 /* Put it in the list */586 split_node->next = node->next;587 node->next = split_node;588 } /* End of too big on top end */589 590 /* For IO make sure it's not in the ISA aliasing space */591 if (node->base & 0x300L)592 continue;593 594 /* If we got here, then it is the right size595 * Now take it out of the list and break596 */597 if (*head == node) {598 *head = node->next;599 } else {600 prevnode = *head;601 while (prevnode->next != node)602 prevnode = prevnode->next;603 604 prevnode->next = node->next;605 }606 node->next = NULL;607 break;608 }609 610 return node;611}612 613 614/**615 * get_max_resource - get largest node which has at least the given size.616 * @head: the list to search the node in617 * @size: the minimum size of the node to find618 *619 * Description: Gets the largest node that is at least "size" big from the620 * list pointed to by head. It aligns the node on top and bottom621 * to "size" alignment before returning it.622 */623static struct pci_resource *get_max_resource(struct pci_resource **head, u32 size)624{625 struct pci_resource *max;626 struct pci_resource *temp;627 struct pci_resource *split_node;628 u32 temp_dword;629 630 if (cpqhp_resource_sort_and_combine(head))631 return NULL;632 633 if (sort_by_max_size(head))634 return NULL;635 636 for (max = *head; max; max = max->next) {637 /* If not big enough we could probably just bail,638 * instead we'll continue to the next.639 */640 if (max->length < size)641 continue;642 643 if (max->base & (size - 1)) {644 /* this one isn't base aligned properly645 * so we'll make a new entry and split it up646 */647 temp_dword = (max->base | (size-1)) + 1;648 649 /* Short circuit if adjusted size is too small */650 if ((max->length - (temp_dword - max->base)) < size)651 continue;652 653 split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);654 655 if (!split_node)656 return NULL;657 658 split_node->base = max->base;659 split_node->length = temp_dword - max->base;660 max->base = temp_dword;661 max->length -= split_node->length;662 663 split_node->next = max->next;664 max->next = split_node;665 }666 667 if ((max->base + max->length) & (size - 1)) {668 /* this one isn't end aligned properly at the top669 * so we'll make a new entry and split it up670 */671 split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);672 673 if (!split_node)674 return NULL;675 temp_dword = ((max->base + max->length) & ~(size - 1));676 split_node->base = temp_dword;677 split_node->length = max->length + max->base678 - split_node->base;679 max->length -= split_node->length;680 681 split_node->next = max->next;682 max->next = split_node;683 }684 685 /* Make sure it didn't shrink too much when we aligned it */686 if (max->length < size)687 continue;688 689 /* Now take it out of the list */690 temp = *head;691 if (temp == max) {692 *head = max->next;693 } else {694 while (temp && temp->next != max)695 temp = temp->next;696 697 if (temp)698 temp->next = max->next;699 }700 701 max->next = NULL;702 break;703 }704 705 return max;706}707 708 709/**710 * get_resource - find resource of given size and split up larger ones.711 * @head: the list to search for resources712 * @size: the size limit to use713 *714 * Description: This function sorts the resource list by size and then715 * returns the first node of "size" length. If it finds a node716 * larger than "size" it will split it up.717 *718 * size must be a power of two.719 */720static struct pci_resource *get_resource(struct pci_resource **head, u32 size)721{722 struct pci_resource *prevnode;723 struct pci_resource *node;724 struct pci_resource *split_node;725 u32 temp_dword;726 727 if (cpqhp_resource_sort_and_combine(head))728 return NULL;729 730 if (sort_by_size(head))731 return NULL;732 733 for (node = *head; node; node = node->next) {734 dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",735 __func__, size, node, node->base, node->length);736 if (node->length < size)737 continue;738 739 if (node->base & (size - 1)) {740 dbg("%s: not aligned\n", __func__);741 /* this one isn't base aligned properly742 * so we'll make a new entry and split it up743 */744 temp_dword = (node->base | (size-1)) + 1;745 746 /* Short circuit if adjusted size is too small */747 if ((node->length - (temp_dword - node->base)) < size)748 continue;749 750 split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);751 752 if (!split_node)753 return NULL;754 755 split_node->base = node->base;756 split_node->length = temp_dword - node->base;757 node->base = temp_dword;758 node->length -= split_node->length;759 760 split_node->next = node->next;761 node->next = split_node;762 } /* End of non-aligned base */763 764 /* Don't need to check if too small since we already did */765 if (node->length > size) {766 dbg("%s: too big\n", __func__);767 /* this one is longer than we need768 * so we'll make a new entry and split it up769 */770 split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);771 772 if (!split_node)773 return NULL;774 775 split_node->base = node->base + size;776 split_node->length = node->length - size;777 node->length = size;778 779 /* Put it in the list */780 split_node->next = node->next;781 node->next = split_node;782 } /* End of too big on top end */783 784 dbg("%s: got one!!!\n", __func__);785 /* If we got here, then it is the right size786 * Now take it out of the list */787 if (*head == node) {788 *head = node->next;789 } else {790 prevnode = *head;791 while (prevnode->next != node)792 prevnode = prevnode->next;793 794 prevnode->next = node->next;795 }796 node->next = NULL;797 break;798 }799 return node;800}801 802 803/**804 * cpqhp_resource_sort_and_combine - sort nodes by base addresses and clean up805 * @head: the list to sort and clean up806 *807 * Description: Sorts all of the nodes in the list in ascending order by808 * their base addresses. Also does garbage collection by809 * combining adjacent nodes.810 *811 * Returns %0 if success.812 */813int cpqhp_resource_sort_and_combine(struct pci_resource **head)814{815 struct pci_resource *node1;816 struct pci_resource *node2;817 int out_of_order = 1;818 819 dbg("%s: head = %p, *head = %p\n", __func__, head, *head);820 821 if (!(*head))822 return 1;823 824 dbg("*head->next = %p\n", (*head)->next);825 826 if (!(*head)->next)827 return 0; /* only one item on the list, already sorted! */828 829 dbg("*head->base = 0x%x\n", (*head)->base);830 dbg("*head->next->base = 0x%x\n", (*head)->next->base);831 while (out_of_order) {832 out_of_order = 0;833 834 /* Special case for swapping list head */835 if (((*head)->next) &&836 ((*head)->base > (*head)->next->base)) {837 node1 = *head;838 (*head) = (*head)->next;839 node1->next = (*head)->next;840 (*head)->next = node1;841 out_of_order++;842 }843 844 node1 = (*head);845 846 while (node1->next && node1->next->next) {847 if (node1->next->base > node1->next->next->base) {848 out_of_order++;849 node2 = node1->next;850 node1->next = node1->next->next;851 node1 = node1->next;852 node2->next = node1->next;853 node1->next = node2;854 } else855 node1 = node1->next;856 }857 } /* End of out_of_order loop */858 859 node1 = *head;860 861 while (node1 && node1->next) {862 if ((node1->base + node1->length) == node1->next->base) {863 /* Combine */864 dbg("8..\n");865 node1->length += node1->next->length;866 node2 = node1->next;867 node1->next = node1->next->next;868 kfree(node2);869 } else870 node1 = node1->next;871 }872 873 return 0;874}875 876 877irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)878{879 struct controller *ctrl = data;880 u8 schedule_flag = 0;881 u8 reset;882 u16 misc;883 u32 Diff;884 885 886 misc = readw(ctrl->hpc_reg + MISC);887 /*888 * Check to see if it was our interrupt889 */890 if (!(misc & 0x000C))891 return IRQ_NONE;892 893 if (misc & 0x0004) {894 /*895 * Serial Output interrupt Pending896 */897 898 /* Clear the interrupt */899 misc |= 0x0004;900 writew(misc, ctrl->hpc_reg + MISC);901 902 /* Read to clear posted writes */903 misc = readw(ctrl->hpc_reg + MISC);904 905 dbg("%s - waking up\n", __func__);906 wake_up_interruptible(&ctrl->queue);907 }908 909 if (misc & 0x0008) {910 /* General-interrupt-input interrupt Pending */911 Diff = readl(ctrl->hpc_reg + INT_INPUT_CLEAR) ^ ctrl->ctrl_int_comp;912 913 ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);914 915 /* Clear the interrupt */916 writel(Diff, ctrl->hpc_reg + INT_INPUT_CLEAR);917 918 /* Read it back to clear any posted writes */919 readl(ctrl->hpc_reg + INT_INPUT_CLEAR);920 921 if (!Diff)922 /* Clear all interrupts */923 writel(0xFFFFFFFF, ctrl->hpc_reg + INT_INPUT_CLEAR);924 925 schedule_flag += handle_switch_change((u8)(Diff & 0xFFL), ctrl);926 schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl);927 schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl);928 }929 930 reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);931 if (reset & 0x40) {932 /* Bus reset has completed */933 reset &= 0xCF;934 writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE);935 reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);936 wake_up_interruptible(&ctrl->queue);937 }938 939 if (schedule_flag) {940 wake_up_process(cpqhp_event_thread);941 dbg("Waking even thread");942 }943 return IRQ_HANDLED;944}945 946 947/**948 * cpqhp_slot_create - Creates a node and adds it to the proper bus.949 * @busnumber: bus where new node is to be located950 *951 * Returns pointer to the new node or %NULL if unsuccessful.952 */953struct pci_func *cpqhp_slot_create(u8 busnumber)954{955 struct pci_func *new_slot;956 struct pci_func *next;957 958 new_slot = kzalloc(sizeof(*new_slot), GFP_KERNEL);959 if (new_slot == NULL)960 return new_slot;961 962 new_slot->next = NULL;963 new_slot->configured = 1;964 965 if (cpqhp_slot_list[busnumber] == NULL) {966 cpqhp_slot_list[busnumber] = new_slot;967 } else {968 next = cpqhp_slot_list[busnumber];969 while (next->next != NULL)970 next = next->next;971 next->next = new_slot;972 }973 return new_slot;974}975 976 977/**978 * slot_remove - Removes a node from the linked list of slots.979 * @old_slot: slot to remove980 *981 * Returns %0 if successful, !0 otherwise.982 */983static int slot_remove(struct pci_func *old_slot)984{985 struct pci_func *next;986 987 if (old_slot == NULL)988 return 1;989 990 next = cpqhp_slot_list[old_slot->bus];991 if (next == NULL)992 return 1;993 994 if (next == old_slot) {995 cpqhp_slot_list[old_slot->bus] = old_slot->next;996 cpqhp_destroy_board_resources(old_slot);997 kfree(old_slot);998 return 0;999 }1000 1001 while ((next->next != old_slot) && (next->next != NULL))1002 next = next->next;1003 1004 if (next->next == old_slot) {1005 next->next = old_slot->next;1006 cpqhp_destroy_board_resources(old_slot);1007 kfree(old_slot);1008 return 0;1009 } else1010 return 2;1011}1012 1013 1014/**1015 * bridge_slot_remove - Removes a node from the linked list of slots.1016 * @bridge: bridge to remove1017 *1018 * Returns %0 if successful, !0 otherwise.1019 */1020static int bridge_slot_remove(struct pci_func *bridge)1021{1022 u8 subordinateBus, secondaryBus;1023 u8 tempBus;1024 struct pci_func *next;1025 1026 secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;1027 subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;1028 1029 for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {1030 next = cpqhp_slot_list[tempBus];1031 1032 while (!slot_remove(next))1033 next = cpqhp_slot_list[tempBus];1034 }1035 1036 next = cpqhp_slot_list[bridge->bus];1037 1038 if (next == NULL)1039 return 1;1040 1041 if (next == bridge) {1042 cpqhp_slot_list[bridge->bus] = bridge->next;1043 goto out;1044 }1045 1046 while ((next->next != bridge) && (next->next != NULL))1047 next = next->next;1048 1049 if (next->next != bridge)1050 return 2;1051 next->next = bridge->next;1052out:1053 kfree(bridge);1054 return 0;1055}1056 1057 1058/**1059 * cpqhp_slot_find - Looks for a node by bus, and device, multiple functions accessed1060 * @bus: bus to find1061 * @device: device to find1062 * @index: is %0 for first function found, %1 for the second...1063 *1064 * Returns pointer to the node if successful, %NULL otherwise.1065 */1066struct pci_func *cpqhp_slot_find(u8 bus, u8 device, u8 index)1067{1068 int found = -1;1069 struct pci_func *func;1070 1071 func = cpqhp_slot_list[bus];1072 1073 if ((func == NULL) || ((func->device == device) && (index == 0)))1074 return func;1075 1076 if (func->device == device)1077 found++;1078 1079 while (func->next != NULL) {1080 func = func->next;1081 1082 if (func->device == device)1083 found++;1084 1085 if (found == index)1086 return func;1087 }1088 1089 return NULL;1090}1091 1092 1093/* DJZ: I don't think is_bridge will work as is.1094 * FIXME */1095static int is_bridge(struct pci_func *func)1096{1097 /* Check the header type */1098 if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)1099 return 1;1100 else1101 return 0;1102}1103 1104 1105/**1106 * set_controller_speed - set the frequency and/or mode of a specific controller segment.1107 * @ctrl: controller to change frequency/mode for.1108 * @adapter_speed: the speed of the adapter we want to match.1109 * @hp_slot: the slot number where the adapter is installed.1110 *1111 * Returns %0 if we successfully change frequency and/or mode to match the1112 * adapter speed.1113 */1114static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)1115{1116 struct slot *slot;1117 struct pci_bus *bus = ctrl->pci_bus;1118 u8 reg;1119 u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);1120 u16 reg16;1121 u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);1122 1123 if (bus->cur_bus_speed == adapter_speed)1124 return 0;1125 1126 /* We don't allow freq/mode changes if we find another adapter running1127 * in another slot on this controller1128 */1129 for (slot = ctrl->slot; slot; slot = slot->next) {1130 if (slot->device == (hp_slot + ctrl->slot_device_offset))1131 continue;1132 if (get_presence_status(ctrl, slot) == 0)1133 continue;1134 /* If another adapter is running on the same segment but at a1135 * lower speed/mode, we allow the new adapter to function at1136 * this rate if supported1137 */1138 if (bus->cur_bus_speed < adapter_speed)1139 return 0;1140 1141 return 1;1142 }1143 1144 /* If the controller doesn't support freq/mode changes and the1145 * controller is running at a higher mode, we bail1146 */1147 if ((bus->cur_bus_speed > adapter_speed) && (!ctrl->pcix_speed_capability))1148 return 1;1149 1150 /* But we allow the adapter to run at a lower rate if possible */1151 if ((bus->cur_bus_speed < adapter_speed) && (!ctrl->pcix_speed_capability))1152 return 0;1153 1154 /* We try to set the max speed supported by both the adapter and1155 * controller1156 */1157 if (bus->max_bus_speed < adapter_speed) {1158 if (bus->cur_bus_speed == bus->max_bus_speed)1159 return 0;1160 adapter_speed = bus->max_bus_speed;1161 }1162 1163 writel(0x0L, ctrl->hpc_reg + LED_CONTROL);1164 writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);1165 1166 set_SOGO(ctrl);1167 wait_for_ctrl_irq(ctrl);1168 1169 if (adapter_speed != PCI_SPEED_133MHz_PCIX)1170 reg = 0xF5;1171 else1172 reg = 0xF4;1173 pci_write_config_byte(ctrl->pci_dev, 0x41, reg);1174 1175 reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);1176 reg16 &= ~0x000F;1177 switch (adapter_speed) {1178 case(PCI_SPEED_133MHz_PCIX):1179 reg = 0x75;1180 reg16 |= 0xB;1181 break;1182 case(PCI_SPEED_100MHz_PCIX):1183 reg = 0x74;1184 reg16 |= 0xA;1185 break;1186 case(PCI_SPEED_66MHz_PCIX):1187 reg = 0x73;1188 reg16 |= 0x9;1189 break;1190 case(PCI_SPEED_66MHz):1191 reg = 0x73;1192 reg16 |= 0x1;1193 break;1194 default: /* 33MHz PCI 2.2 */1195 reg = 0x71;1196 break;1197 1198 }1199 reg16 |= 0xB << 12;1200 writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);1201 1202 mdelay(5);1203 1204 /* Re-enable interrupts */1205 writel(0, ctrl->hpc_reg + INT_MASK);1206 1207 pci_write_config_byte(ctrl->pci_dev, 0x41, reg);1208 1209 /* Restart state machine */1210 reg = ~0xF;1211 pci_read_config_byte(ctrl->pci_dev, 0x43, ®);1212 pci_write_config_byte(ctrl->pci_dev, 0x43, reg);1213 1214 /* Only if mode change...*/1215 if (((bus->cur_bus_speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||1216 ((bus->cur_bus_speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz)))1217 set_SOGO(ctrl);1218 1219 wait_for_ctrl_irq(ctrl);1220 mdelay(1100);1221 1222 /* Restore LED/Slot state */1223 writel(leds, ctrl->hpc_reg + LED_CONTROL);1224 writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);1225 1226 set_SOGO(ctrl);1227 wait_for_ctrl_irq(ctrl);1228 1229 bus->cur_bus_speed = adapter_speed;1230 slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);1231 1232 info("Successfully changed frequency/mode for adapter in slot %d\n",1233 slot->number);1234 return 0;1235}1236 1237/* the following routines constitute the bulk of the1238 * hotplug controller logic1239 */1240 1241 1242/**1243 * board_replaced - Called after a board has been replaced in the system.1244 * @func: PCI device/function information1245 * @ctrl: hotplug controller1246 *1247 * This is only used if we don't have resources for hot add.1248 * Turns power on for the board.1249 * Checks to see if board is the same.1250 * If board is same, reconfigures it.1251 * If board isn't same, turns it back off.1252 */1253static u32 board_replaced(struct pci_func *func, struct controller *ctrl)1254{1255 struct pci_bus *bus = ctrl->pci_bus;1256 u8 hp_slot;1257 u8 temp_byte;1258 u8 adapter_speed;1259 u32 rc = 0;1260 1261 hp_slot = func->device - ctrl->slot_device_offset;1262 1263 /*1264 * The switch is open.1265 */1266 if (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot))1267 rc = INTERLOCK_OPEN;1268 /*1269 * The board is already on1270 */1271 else if (is_slot_enabled(ctrl, hp_slot))1272 rc = CARD_FUNCTIONING;1273 else {1274 mutex_lock(&ctrl->crit_sect);1275 1276 /* turn on board without attaching to the bus */1277 enable_slot_power(ctrl, hp_slot);1278 1279 set_SOGO(ctrl);1280 1281 /* Wait for SOBS to be unset */1282 wait_for_ctrl_irq(ctrl);1283 1284 /* Change bits in slot power register to force another shift out1285 * NOTE: this is to work around the timer bug */1286 temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);1287 writeb(0x00, ctrl->hpc_reg + SLOT_POWER);1288 writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);1289 1290 set_SOGO(ctrl);1291 1292 /* Wait for SOBS to be unset */1293 wait_for_ctrl_irq(ctrl);1294 1295 adapter_speed = get_adapter_speed(ctrl, hp_slot);1296 if (bus->cur_bus_speed != adapter_speed)1297 if (set_controller_speed(ctrl, adapter_speed, hp_slot))1298 rc = WRONG_BUS_FREQUENCY;1299 1300 /* turn off board without attaching to the bus */1301 disable_slot_power(ctrl, hp_slot);1302 1303 set_SOGO(ctrl);1304 1305 /* Wait for SOBS to be unset */1306 wait_for_ctrl_irq(ctrl);1307 1308 mutex_unlock(&ctrl->crit_sect);1309 1310 if (rc)1311 return rc;1312 1313 mutex_lock(&ctrl->crit_sect);1314 1315 slot_enable(ctrl, hp_slot);1316 green_LED_blink(ctrl, hp_slot);1317 1318 amber_LED_off(ctrl, hp_slot);1319 1320 set_SOGO(ctrl);1321 1322 /* Wait for SOBS to be unset */1323 wait_for_ctrl_irq(ctrl);1324 1325 mutex_unlock(&ctrl->crit_sect);1326 1327 /* Wait for ~1 second because of hot plug spec */1328 long_delay(1*HZ);1329 1330 /* Check for a power fault */1331 if (func->status == 0xFF) {1332 /* power fault occurred, but it was benign */1333 rc = POWER_FAILURE;1334 func->status = 0;1335 } else1336 rc = cpqhp_valid_replace(ctrl, func);1337 1338 if (!rc) {1339 /* It must be the same board */1340 1341 rc = cpqhp_configure_board(ctrl, func);1342 1343 /* If configuration fails, turn it off1344 * Get slot won't work for devices behind1345 * bridges, but in this case it will always be1346 * called for the "base" bus/dev/func of an1347 * adapter.1348 */1349 1350 mutex_lock(&ctrl->crit_sect);1351 1352 amber_LED_on(ctrl, hp_slot);1353 green_LED_off(ctrl, hp_slot);1354 slot_disable(ctrl, hp_slot);1355 1356 set_SOGO(ctrl);1357 1358 /* Wait for SOBS to be unset */1359 wait_for_ctrl_irq(ctrl);1360 1361 mutex_unlock(&ctrl->crit_sect);1362 1363 if (rc)1364 return rc;1365 else1366 return 1;1367 1368 } else {1369 /* Something is wrong1370 1371 * Get slot won't work for devices behind bridges, but1372 * in this case it will always be called for the "base"1373 * bus/dev/func of an adapter.1374 */1375 1376 mutex_lock(&ctrl->crit_sect);1377 1378 amber_LED_on(ctrl, hp_slot);1379 green_LED_off(ctrl, hp_slot);1380 slot_disable(ctrl, hp_slot);1381 1382 set_SOGO(ctrl);1383 1384 /* Wait for SOBS to be unset */1385 wait_for_ctrl_irq(ctrl);1386 1387 mutex_unlock(&ctrl->crit_sect);1388 }1389 1390 }1391 return rc;1392 1393}1394 1395 1396/**1397 * board_added - Called after a board has been added to the system.1398 * @func: PCI device/function info1399 * @ctrl: hotplug controller1400 *1401 * Turns power on for the board.1402 * Configures board.1403 */1404static u32 board_added(struct pci_func *func, struct controller *ctrl)1405{1406 u8 hp_slot;1407 u8 temp_byte;1408 u8 adapter_speed;1409 int index;1410 u32 temp_register = 0xFFFFFFFF;1411 u32 rc = 0;1412 struct pci_func *new_slot = NULL;1413 struct pci_bus *bus = ctrl->pci_bus;1414 struct resource_lists res_lists;1415 1416 hp_slot = func->device - ctrl->slot_device_offset;1417 dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",1418 __func__, func->device, ctrl->slot_device_offset, hp_slot);1419 1420 mutex_lock(&ctrl->crit_sect);1421 1422 /* turn on board without attaching to the bus */1423 enable_slot_power(ctrl, hp_slot);1424 1425 set_SOGO(ctrl);1426 1427 /* Wait for SOBS to be unset */1428 wait_for_ctrl_irq(ctrl);1429 1430 /* Change bits in slot power register to force another shift out1431 * NOTE: this is to work around the timer bug1432 */1433 temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);1434 writeb(0x00, ctrl->hpc_reg + SLOT_POWER);1435 writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);1436 1437 set_SOGO(ctrl);1438 1439 /* Wait for SOBS to be unset */1440 wait_for_ctrl_irq(ctrl);1441 1442 adapter_speed = get_adapter_speed(ctrl, hp_slot);1443 if (bus->cur_bus_speed != adapter_speed)1444 if (set_controller_speed(ctrl, adapter_speed, hp_slot))1445 rc = WRONG_BUS_FREQUENCY;1446 1447 /* turn off board without attaching to the bus */1448 disable_slot_power(ctrl, hp_slot);1449 1450 set_SOGO(ctrl);1451 1452 /* Wait for SOBS to be unset */1453 wait_for_ctrl_irq(ctrl);1454 1455 mutex_unlock(&ctrl->crit_sect);1456 1457 if (rc)1458 return rc;1459 1460 cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);1461 1462 /* turn on board and blink green LED */1463 1464 dbg("%s: before down\n", __func__);1465 mutex_lock(&ctrl->crit_sect);1466 dbg("%s: after down\n", __func__);1467 1468 dbg("%s: before slot_enable\n", __func__);1469 slot_enable(ctrl, hp_slot);1470 1471 dbg("%s: before green_LED_blink\n", __func__);1472 green_LED_blink(ctrl, hp_slot);1473 1474 dbg("%s: before amber_LED_blink\n", __func__);1475 amber_LED_off(ctrl, hp_slot);1476 1477 dbg("%s: before set_SOGO\n", __func__);1478 set_SOGO(ctrl);1479 1480 /* Wait for SOBS to be unset */1481 dbg("%s: before wait_for_ctrl_irq\n", __func__);1482 wait_for_ctrl_irq(ctrl);1483 dbg("%s: after wait_for_ctrl_irq\n", __func__);1484 1485 dbg("%s: before up\n", __func__);1486 mutex_unlock(&ctrl->crit_sect);1487 dbg("%s: after up\n", __func__);1488 1489 /* Wait for ~1 second because of hot plug spec */1490 dbg("%s: before long_delay\n", __func__);1491 long_delay(1*HZ);1492 dbg("%s: after long_delay\n", __func__);1493 1494 dbg("%s: func status = %x\n", __func__, func->status);1495 /* Check for a power fault */1496 if (func->status == 0xFF) {1497 /* power fault occurred, but it was benign */1498 temp_register = 0xFFFFFFFF;1499 dbg("%s: temp register set to %x by power fault\n", __func__, temp_register);1500 rc = POWER_FAILURE;1501 func->status = 0;1502 } else {1503 /* Get vendor/device ID u32 */1504 ctrl->pci_bus->number = func->bus;1505 rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);1506 dbg("%s: pci_read_config_dword returns %d\n", __func__, rc);1507 dbg("%s: temp_register is %x\n", __func__, temp_register);1508 1509 if (rc != 0) {1510 /* Something's wrong here */1511 temp_register = 0xFFFFFFFF;1512 dbg("%s: temp register set to %x by error\n", __func__, temp_register);1513 }1514 /* Preset return code. It will be changed later if things go okay. */1515 rc = NO_ADAPTER_PRESENT;1516 }1517 1518 /* All F's is an empty slot or an invalid board */1519 if (temp_register != 0xFFFFFFFF) {1520 res_lists.io_head = ctrl->io_head;1521 res_lists.mem_head = ctrl->mem_head;1522 res_lists.p_mem_head = ctrl->p_mem_head;1523 res_lists.bus_head = ctrl->bus_head;1524 res_lists.irqs = NULL;1525 1526 rc = configure_new_device(ctrl, func, 0, &res_lists);1527 1528 dbg("%s: back from configure_new_device\n", __func__);1529 ctrl->io_head = res_lists.io_head;1530 ctrl->mem_head = res_lists.mem_head;1531 ctrl->p_mem_head = res_lists.p_mem_head;1532 ctrl->bus_head = res_lists.bus_head;1533 1534 cpqhp_resource_sort_and_combine(&(ctrl->mem_head));1535 cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));1536 cpqhp_resource_sort_and_combine(&(ctrl->io_head));1537 cpqhp_resource_sort_and_combine(&(ctrl->bus_head));1538 1539 if (rc) {1540 mutex_lock(&ctrl->crit_sect);1541 1542 amber_LED_on(ctrl, hp_slot);1543 green_LED_off(ctrl, hp_slot);1544 slot_disable(ctrl, hp_slot);1545 1546 set_SOGO(ctrl);1547 1548 /* Wait for SOBS to be unset */1549 wait_for_ctrl_irq(ctrl);1550 1551 mutex_unlock(&ctrl->crit_sect);1552 return rc;1553 } else {1554 cpqhp_save_slot_config(ctrl, func);1555 }1556 1557 1558 func->status = 0;1559 func->switch_save = 0x10;1560 func->is_a_board = 0x01;1561 1562 /* next, we will instantiate the linux pci_dev structures (with1563 * appropriate driver notification, if already present) */1564 dbg("%s: configure linux pci_dev structure\n", __func__);1565 index = 0;1566 do {1567 new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++);1568 if (new_slot && !new_slot->pci_dev)1569 cpqhp_configure_device(ctrl, new_slot);1570 } while (new_slot);1571 1572 mutex_lock(&ctrl->crit_sect);1573 1574 green_LED_on(ctrl, hp_slot);1575 1576 set_SOGO(ctrl);1577 1578 /* Wait for SOBS to be unset */1579 wait_for_ctrl_irq(ctrl);1580 1581 mutex_unlock(&ctrl->crit_sect);1582 } else {1583 mutex_lock(&ctrl->crit_sect);1584 1585 amber_LED_on(ctrl, hp_slot);1586 green_LED_off(ctrl, hp_slot);1587 slot_disable(ctrl, hp_slot);1588 1589 set_SOGO(ctrl);1590 1591 /* Wait for SOBS to be unset */1592 wait_for_ctrl_irq(ctrl);1593 1594 mutex_unlock(&ctrl->crit_sect);1595 1596 return rc;1597 }1598 return 0;1599}1600 1601 1602/**1603 * remove_board - Turns off slot and LEDs1604 * @func: PCI device/function info1605 * @replace_flag: whether replacing or adding a new device1606 * @ctrl: target controller1607 */1608static u32 remove_board(struct pci_func *func, u32 replace_flag, struct controller *ctrl)1609{1610 int index;1611 u8 skip = 0;1612 u8 device;1613 u8 hp_slot;1614 u8 temp_byte;1615 struct resource_lists res_lists;1616 struct pci_func *temp_func;1617 1618 if (cpqhp_unconfigure_device(func))1619 return 1;1620 1621 device = func->device;1622 1623 hp_slot = func->device - ctrl->slot_device_offset;1624 dbg("In %s, hp_slot = %d\n", __func__, hp_slot);1625 1626 /* When we get here, it is safe to change base address registers.1627 * We will attempt to save the base address register lengths */1628 if (replace_flag || !ctrl->add_support)1629 cpqhp_save_base_addr_length(ctrl, func);1630 else if (!func->bus_head && !func->mem_head &&1631 !func->p_mem_head && !func->io_head) {1632 /* Here we check to see if we've saved any of the board's1633 * resources already. If so, we'll skip the attempt to1634 * determine what's being used. */1635 index = 0;1636 temp_func = cpqhp_slot_find(func->bus, func->device, index++);1637 while (temp_func) {1638 if (temp_func->bus_head || temp_func->mem_head1639 || temp_func->p_mem_head || temp_func->io_head) {1640 skip = 1;1641 break;1642 }1643 temp_func = cpqhp_slot_find(temp_func->bus, temp_func->device, index++);1644 }1645 1646 if (!skip)1647 cpqhp_save_used_resources(ctrl, func);1648 }1649 /* Change status to shutdown */1650 if (func->is_a_board)1651 func->status = 0x01;1652 func->configured = 0;1653 1654 mutex_lock(&ctrl->crit_sect);1655 1656 green_LED_off(ctrl, hp_slot);1657 slot_disable(ctrl, hp_slot);1658 1659 set_SOGO(ctrl);1660 1661 /* turn off SERR for slot */1662 temp_byte = readb(ctrl->hpc_reg + SLOT_SERR);1663 temp_byte &= ~(0x01 << hp_slot);1664 writeb(temp_byte, ctrl->hpc_reg + SLOT_SERR);1665 1666 /* Wait for SOBS to be unset */1667 wait_for_ctrl_irq(ctrl);1668 1669 mutex_unlock(&ctrl->crit_sect);1670 1671 if (!replace_flag && ctrl->add_support) {1672 while (func) {1673 res_lists.io_head = ctrl->io_head;1674 res_lists.mem_head = ctrl->mem_head;1675 res_lists.p_mem_head = ctrl->p_mem_head;1676 res_lists.bus_head = ctrl->bus_head;1677 1678 cpqhp_return_board_resources(func, &res_lists);1679 1680 ctrl->io_head = res_lists.io_head;1681 ctrl->mem_head = res_lists.mem_head;1682 ctrl->p_mem_head = res_lists.p_mem_head;1683 ctrl->bus_head = res_lists.bus_head;1684 1685 cpqhp_resource_sort_and_combine(&(ctrl->mem_head));1686 cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));1687 cpqhp_resource_sort_and_combine(&(ctrl->io_head));1688 cpqhp_resource_sort_and_combine(&(ctrl->bus_head));1689 1690 if (is_bridge(func)) {1691 bridge_slot_remove(func);1692 } else1693 slot_remove(func);1694 1695 func = cpqhp_slot_find(ctrl->bus, device, 0);1696 }1697 1698 /* Setup slot structure with entry for empty slot */1699 func = cpqhp_slot_create(ctrl->bus);1700 1701 if (func == NULL)1702 return 1;1703 1704 func->bus = ctrl->bus;1705 func->device = device;1706 func->function = 0;1707 func->configured = 0;1708 func->switch_save = 0x10;1709 func->is_a_board = 0;1710 func->p_task_event = NULL;1711 }1712 1713 return 0;1714}1715 1716static void pushbutton_helper_thread(struct timer_list *t)1717{1718 pushbutton_pending = t;1719 1720 wake_up_process(cpqhp_event_thread);1721}1722 1723 1724/* this is the main worker thread */1725static int event_thread(void *data)1726{1727 struct controller *ctrl;1728 1729 while (1) {1730 dbg("!!!!event_thread sleeping\n");1731 set_current_state(TASK_INTERRUPTIBLE);1732 schedule();1733 1734 if (kthread_should_stop())1735 break;1736 /* Do stuff here */1737 if (pushbutton_pending)1738 cpqhp_pushbutton_thread(pushbutton_pending);1739 else1740 for (ctrl = cpqhp_ctrl_list; ctrl; ctrl = ctrl->next)1741 interrupt_event_handler(ctrl);1742 }1743 dbg("event_thread signals exit\n");1744 return 0;1745}1746 1747int cpqhp_event_start_thread(void)1748{1749 cpqhp_event_thread = kthread_run(event_thread, NULL, "phpd_event");1750 if (IS_ERR(cpqhp_event_thread)) {1751 err("Can't start up our event thread\n");1752 return PTR_ERR(cpqhp_event_thread);1753 }1754 1755 return 0;1756}1757 1758 1759void cpqhp_event_stop_thread(void)1760{1761 kthread_stop(cpqhp_event_thread);1762}1763 1764 1765static void interrupt_event_handler(struct controller *ctrl)1766{1767 int loop;1768 int change = 1;1769 struct pci_func *func;1770 u8 hp_slot;1771 struct slot *p_slot;1772 1773 while (change) {1774 change = 0;1775 1776 for (loop = 0; loop < 10; loop++) {1777 /* dbg("loop %d\n", loop); */1778 if (ctrl->event_queue[loop].event_type != 0) {1779 hp_slot = ctrl->event_queue[loop].hp_slot;1780 1781 func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);1782 if (!func)1783 return;1784 1785 p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);1786 if (!p_slot)1787 return;1788 1789 dbg("hp_slot %d, func %p, p_slot %p\n",1790 hp_slot, func, p_slot);1791 1792 if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {1793 dbg("button pressed\n");1794 } else if (ctrl->event_queue[loop].event_type ==1795 INT_BUTTON_CANCEL) {1796 dbg("button cancel\n");1797 del_timer(&p_slot->task_event);1798 1799 mutex_lock(&ctrl->crit_sect);1800 1801 if (p_slot->state == BLINKINGOFF_STATE) {1802 /* slot is on */1803 dbg("turn on green LED\n");1804 green_LED_on(ctrl, hp_slot);1805 } else if (p_slot->state == BLINKINGON_STATE) {1806 /* slot is off */1807 dbg("turn off green LED\n");1808 green_LED_off(ctrl, hp_slot);1809 }1810 1811 info(msg_button_cancel, p_slot->number);1812 1813 p_slot->state = STATIC_STATE;1814 1815 amber_LED_off(ctrl, hp_slot);1816 1817 set_SOGO(ctrl);1818 1819 /* Wait for SOBS to be unset */1820 wait_for_ctrl_irq(ctrl);1821 1822 mutex_unlock(&ctrl->crit_sect);1823 }1824 /*** button Released (No action on press...) */1825 else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) {1826 dbg("button release\n");1827 1828 if (is_slot_enabled(ctrl, hp_slot)) {1829 dbg("slot is on\n");1830 p_slot->state = BLINKINGOFF_STATE;1831 info(msg_button_off, p_slot->number);1832 } else {1833 dbg("slot is off\n");1834 p_slot->state = BLINKINGON_STATE;1835 info(msg_button_on, p_slot->number);1836 }1837 mutex_lock(&ctrl->crit_sect);1838 1839 dbg("blink green LED and turn off amber\n");1840 1841 amber_LED_off(ctrl, hp_slot);1842 green_LED_blink(ctrl, hp_slot);1843 1844 set_SOGO(ctrl);1845 1846 /* Wait for SOBS to be unset */1847 wait_for_ctrl_irq(ctrl);1848 1849 mutex_unlock(&ctrl->crit_sect);1850 timer_setup(&p_slot->task_event,1851 pushbutton_helper_thread,1852 0);1853 p_slot->hp_slot = hp_slot;1854 p_slot->ctrl = ctrl;1855/* p_slot->physical_slot = physical_slot; */1856 p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */1857 1858 dbg("add_timer p_slot = %p\n", p_slot);1859 add_timer(&p_slot->task_event);1860 }1861 /***********POWER FAULT */1862 else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {1863 dbg("power fault\n");1864 }1865 1866 ctrl->event_queue[loop].event_type = 0;1867 1868 change = 1;1869 }1870 } /* End of FOR loop */1871 }1872}1873 1874 1875/**1876 * cpqhp_pushbutton_thread - handle pushbutton events1877 * @t: pointer to struct timer_list which holds all timer-related callbacks1878 *1879 * Scheduled procedure to handle blocking stuff for the pushbuttons.1880 * Handles all pending events and exits.1881 */1882void cpqhp_pushbutton_thread(struct timer_list *t)1883{1884 u8 hp_slot;1885 struct pci_func *func;1886 struct slot *p_slot = from_timer(p_slot, t, task_event);1887 struct controller *ctrl = (struct controller *) p_slot->ctrl;1888 1889 pushbutton_pending = NULL;1890 hp_slot = p_slot->hp_slot;1891 1892 if (is_slot_enabled(ctrl, hp_slot)) {1893 p_slot->state = POWEROFF_STATE;1894 /* power Down board */1895 func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);1896 dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl);1897 if (!func) {1898 dbg("Error! func NULL in %s\n", __func__);1899 return;1900 }1901 1902 if (cpqhp_process_SS(ctrl, func) != 0) {1903 amber_LED_on(ctrl, hp_slot);1904 green_LED_on(ctrl, hp_slot);1905 1906 set_SOGO(ctrl);1907 1908 /* Wait for SOBS to be unset */1909 wait_for_ctrl_irq(ctrl);1910 }1911 1912 p_slot->state = STATIC_STATE;1913 } else {1914 p_slot->state = POWERON_STATE;1915 /* slot is off */1916 1917 func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);1918 dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl);1919 if (!func) {1920 dbg("Error! func NULL in %s\n", __func__);1921 return;1922 }1923 1924 if (ctrl != NULL) {1925 if (cpqhp_process_SI(ctrl, func) != 0) {1926 amber_LED_on(ctrl, hp_slot);1927 green_LED_off(ctrl, hp_slot);1928 1929 set_SOGO(ctrl);1930 1931 /* Wait for SOBS to be unset */1932 wait_for_ctrl_irq(ctrl);1933 }1934 }1935 1936 p_slot->state = STATIC_STATE;1937 }1938}1939 1940 1941int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func)1942{1943 u8 device, hp_slot;1944 u16 temp_word;1945 u32 tempdword;1946 int rc;1947 struct slot *p_slot;1948 1949 tempdword = 0;1950 1951 device = func->device;1952 hp_slot = device - ctrl->slot_device_offset;1953 p_slot = cpqhp_find_slot(ctrl, device);1954 1955 /* Check to see if the interlock is closed */1956 tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);1957 1958 if (tempdword & (0x01 << hp_slot))1959 return 1;1960 1961 if (func->is_a_board) {1962 rc = board_replaced(func, ctrl);1963 } else {1964 /* add board */1965 slot_remove(func);1966 1967 func = cpqhp_slot_create(ctrl->bus);1968 if (func == NULL)1969 return 1;1970 1971 func->bus = ctrl->bus;1972 func->device = device;1973 func->function = 0;1974 func->configured = 0;1975 func->is_a_board = 1;1976 1977 /* We have to save the presence info for these slots */1978 temp_word = ctrl->ctrl_int_comp >> 16;1979 func->presence_save = (temp_word >> hp_slot) & 0x01;1980 func->presence_save |= (temp_word >> (hp_slot + 7)) & 0x02;1981 1982 if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {1983 func->switch_save = 0;1984 } else {1985 func->switch_save = 0x10;1986 }1987 1988 rc = board_added(func, ctrl);1989 if (rc) {1990 if (is_bridge(func)) {1991 bridge_slot_remove(func);1992 } else1993 slot_remove(func);1994 1995 /* Setup slot structure with entry for empty slot */1996 func = cpqhp_slot_create(ctrl->bus);1997 1998 if (func == NULL)1999 return 1;2000 2001 func->bus = ctrl->bus;2002 func->device = device;2003 func->function = 0;2004 func->configured = 0;2005 func->is_a_board = 0;2006 2007 /* We have to save the presence info for these slots */2008 temp_word = ctrl->ctrl_int_comp >> 16;2009 func->presence_save = (temp_word >> hp_slot) & 0x01;2010 func->presence_save |=2011 (temp_word >> (hp_slot + 7)) & 0x02;2012 2013 if (ctrl->ctrl_int_comp & (0x1L << hp_slot)) {2014 func->switch_save = 0;2015 } else {2016 func->switch_save = 0x10;2017 }2018 }2019 }2020 2021 if (rc)2022 dbg("%s: rc = %d\n", __func__, rc);2023 2024 return rc;2025}2026 2027 2028int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)2029{2030 u8 device, class_code, header_type, BCR;2031 u8 index = 0;2032 u8 replace_flag;2033 u32 rc = 0;2034 unsigned int devfn;2035 struct slot *p_slot;2036 struct pci_bus *pci_bus = ctrl->pci_bus;2037 2038 device = func->device;2039 func = cpqhp_slot_find(ctrl->bus, device, index++);2040 p_slot = cpqhp_find_slot(ctrl, device);2041 2042 /* Make sure there are no video controllers here */2043 while (func && !rc) {2044 pci_bus->number = func->bus;2045 devfn = PCI_DEVFN(func->device, func->function);2046 2047 /* Check the Class Code */2048 rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);2049 if (rc)2050 return rc;2051 2052 if (class_code == PCI_BASE_CLASS_DISPLAY) {2053 /* Display/Video adapter (not supported) */2054 rc = REMOVE_NOT_SUPPORTED;2055 } else {2056 /* See if it's a bridge */2057 rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);2058 if (rc)2059 return rc;2060 2061 /* If it's a bridge, check the VGA Enable bit */2062 if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {2063 rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);2064 if (rc)2065 return rc;2066 2067 /* If the VGA Enable bit is set, remove isn't2068 * supported */2069 if (BCR & PCI_BRIDGE_CTL_VGA)2070 rc = REMOVE_NOT_SUPPORTED;2071 }2072 }2073 2074 func = cpqhp_slot_find(ctrl->bus, device, index++);2075 }2076 2077 func = cpqhp_slot_find(ctrl->bus, device, 0);2078 if ((func != NULL) && !rc) {2079 /* FIXME: Replace flag should be passed into process_SS */2080 replace_flag = !(ctrl->add_support);2081 rc = remove_board(func, replace_flag, ctrl);2082 } else if (!rc) {2083 rc = 1;2084 }2085 2086 return rc;2087}2088 2089/**2090 * switch_leds - switch the leds, go from one site to the other.2091 * @ctrl: controller to use2092 * @num_of_slots: number of slots to use2093 * @work_LED: LED control value2094 * @direction: 1 to start from the left side, 0 to start right.2095 */2096static void switch_leds(struct controller *ctrl, const int num_of_slots,2097 u32 *work_LED, const int direction)2098{2099 int loop;2100 2101 for (loop = 0; loop < num_of_slots; loop++) {2102 if (direction)2103 *work_LED = *work_LED >> 1;2104 else2105 *work_LED = *work_LED << 1;2106 writel(*work_LED, ctrl->hpc_reg + LED_CONTROL);2107 2108 set_SOGO(ctrl);2109 2110 /* Wait for SOGO interrupt */2111 wait_for_ctrl_irq(ctrl);2112 2113 /* Get ready for next iteration */2114 long_delay((2*HZ)/10);2115 }2116}2117 2118/**2119 * cpqhp_hardware_test - runs hardware tests2120 * @ctrl: target controller2121 * @test_num: the number written to the "test" file in sysfs.2122 *2123 * For hot plug ctrl folks to play with.2124 */2125int cpqhp_hardware_test(struct controller *ctrl, int test_num)2126{2127 u32 save_LED;2128 u32 work_LED;2129 int loop;2130 int num_of_slots;2131 2132 num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0f;2133 2134 switch (test_num) {2135 case 1:2136 /* Do stuff here! */2137 2138 /* Do that funky LED thing */2139 /* so we can restore them later */2140 save_LED = readl(ctrl->hpc_reg + LED_CONTROL);2141 work_LED = 0x01010101;2142 switch_leds(ctrl, num_of_slots, &work_LED, 0);2143 switch_leds(ctrl, num_of_slots, &work_LED, 1);2144 switch_leds(ctrl, num_of_slots, &work_LED, 0);2145 switch_leds(ctrl, num_of_slots, &work_LED, 1);2146 2147 work_LED = 0x01010000;2148 writel(work_LED, ctrl->hpc_reg + LED_CONTROL);2149 switch_leds(ctrl, num_of_slots, &work_LED, 0);2150 switch_leds(ctrl, num_of_slots, &work_LED, 1);2151 work_LED = 0x00000101;2152 writel(work_LED, ctrl->hpc_reg + LED_CONTROL);2153 switch_leds(ctrl, num_of_slots, &work_LED, 0);2154 switch_leds(ctrl, num_of_slots, &work_LED, 1);2155 2156 work_LED = 0x01010000;2157 writel(work_LED, ctrl->hpc_reg + LED_CONTROL);2158 for (loop = 0; loop < num_of_slots; loop++) {2159 set_SOGO(ctrl);2160 2161 /* Wait for SOGO interrupt */2162 wait_for_ctrl_irq(ctrl);2163 2164 /* Get ready for next iteration */2165 long_delay((3*HZ)/10);2166 work_LED = work_LED >> 16;2167 writel(work_LED, ctrl->hpc_reg + LED_CONTROL);2168 2169 set_SOGO(ctrl);2170 2171 /* Wait for SOGO interrupt */2172 wait_for_ctrl_irq(ctrl);2173 2174 /* Get ready for next iteration */2175 long_delay((3*HZ)/10);2176 work_LED = work_LED << 16;2177 writel(work_LED, ctrl->hpc_reg + LED_CONTROL);2178 work_LED = work_LED << 1;2179 writel(work_LED, ctrl->hpc_reg + LED_CONTROL);2180 }2181 2182 /* put it back the way it was */2183 writel(save_LED, ctrl->hpc_reg + LED_CONTROL);2184 2185 set_SOGO(ctrl);2186 2187 /* Wait for SOBS to be unset */2188 wait_for_ctrl_irq(ctrl);2189 break;2190 case 2:2191 /* Do other stuff here! */2192 break;2193 case 3:2194 /* and more... */2195 break;2196 }2197 return 0;2198}2199 2200 2201/**2202 * configure_new_device - Configures the PCI header information of one board.2203 * @ctrl: pointer to controller structure2204 * @func: pointer to function structure2205 * @behind_bridge: 1 if this is a recursive call, 0 if not2206 * @resources: pointer to set of resource lists2207 *2208 * Returns 0 if success.2209 */2210static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,2211 u8 behind_bridge, struct resource_lists *resources)2212{2213 u8 temp_byte, function, max_functions, stop_it;2214 int rc;2215 u32 ID;2216 struct pci_func *new_slot;2217 int index;2218 2219 new_slot = func;2220 2221 dbg("%s\n", __func__);2222 /* Check for Multi-function device */2223 ctrl->pci_bus->number = func->bus;2224 rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);2225 if (rc) {2226 dbg("%s: rc = %d\n", __func__, rc);2227 return rc;2228 }2229 2230 if (temp_byte & 0x80) /* Multi-function device */2231 max_functions = 8;2232 else2233 max_functions = 1;2234 2235 function = 0;2236 2237 do {2238 rc = configure_new_function(ctrl, new_slot, behind_bridge, resources);2239 2240 if (rc) {2241 dbg("configure_new_function failed %d\n", rc);2242 index = 0;2243 2244 while (new_slot) {2245 new_slot = cpqhp_slot_find(new_slot->bus, new_slot->device, index++);2246 2247 if (new_slot)2248 cpqhp_return_board_resources(new_slot, resources);2249 }2250 2251 return rc;2252 }2253 2254 function++;2255 2256 stop_it = 0;2257 2258 /* The following loop skips to the next present function2259 * and creates a board structure */2260 2261 while ((function < max_functions) && (!stop_it)) {2262 pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);2263 2264 if (PCI_POSSIBLE_ERROR(ID)) {2265 function++;2266 } else {2267 /* Setup slot structure. */2268 new_slot = cpqhp_slot_create(func->bus);2269 2270 if (new_slot == NULL)2271 return 1;2272 2273 new_slot->bus = func->bus;2274 new_slot->device = func->device;2275 new_slot->function = function;2276 new_slot->is_a_board = 1;2277 new_slot->status = 0;2278 2279 stop_it++;2280 }2281 }2282 2283 } while (function < max_functions);2284 dbg("returning from configure_new_device\n");2285 2286 return 0;2287}2288 2289 2290/*2291 * Configuration logic that involves the hotplug data structures and2292 * their bookkeeping2293 */2294 2295 2296/**2297 * configure_new_function - Configures the PCI header information of one device2298 * @ctrl: pointer to controller structure2299 * @func: pointer to function structure2300 * @behind_bridge: 1 if this is a recursive call, 0 if not2301 * @resources: pointer to set of resource lists2302 *2303 * Calls itself recursively for bridged devices.2304 * Returns 0 if success.2305 */2306static int configure_new_function(struct controller *ctrl, struct pci_func *func,2307 u8 behind_bridge,2308 struct resource_lists *resources)2309{2310 int cloop;2311 u8 IRQ = 0;2312 u8 temp_byte;2313 u8 device;2314 u8 class_code;2315 u16 command;2316 u16 temp_word;2317 u32 temp_dword;2318 u32 rc;2319 u32 temp_register;2320 u32 base;2321 u32 ID;2322 unsigned int devfn;2323 struct pci_resource *mem_node;2324 struct pci_resource *p_mem_node;2325 struct pci_resource *io_node;2326 struct pci_resource *bus_node;2327 struct pci_resource *hold_mem_node;2328 struct pci_resource *hold_p_mem_node;2329 struct pci_resource *hold_IO_node;2330 struct pci_resource *hold_bus_node;2331 struct irq_mapping irqs;2332 struct pci_func *new_slot;2333 struct pci_bus *pci_bus;2334 struct resource_lists temp_resources;2335 2336 pci_bus = ctrl->pci_bus;2337 pci_bus->number = func->bus;2338 devfn = PCI_DEVFN(func->device, func->function);2339 2340 /* Check for Bridge */2341 rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);2342 if (rc)2343 return rc;2344 2345 if ((temp_byte & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {2346 /* set Primary bus */2347 dbg("set Primary bus = %d\n", func->bus);2348 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);2349 if (rc)2350 return rc;2351 2352 /* find range of buses to use */2353 dbg("find ranges of buses to use\n");2354 bus_node = get_max_resource(&(resources->bus_head), 1);2355 2356 /* If we don't have any buses to allocate, we can't continue */2357 if (!bus_node)2358 return -ENOMEM;2359 2360 /* set Secondary bus */2361 temp_byte = bus_node->base;2362 dbg("set Secondary bus = %d\n", bus_node->base);2363 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);2364 if (rc)2365 return rc;2366 2367 /* set subordinate bus */2368 temp_byte = bus_node->base + bus_node->length - 1;2369 dbg("set subordinate bus = %d\n", bus_node->base + bus_node->length - 1);2370 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);2371 if (rc)2372 return rc;2373 2374 /* set subordinate Latency Timer and base Latency Timer */2375 temp_byte = 0x40;2376 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);2377 if (rc)2378 return rc;2379 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);2380 if (rc)2381 return rc;2382 2383 /* set Cache Line size */2384 temp_byte = 0x08;2385 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);2386 if (rc)2387 return rc;2388 2389 /* Setup the IO, memory, and prefetchable windows */2390 io_node = get_max_resource(&(resources->io_head), 0x1000);2391 if (!io_node)2392 return -ENOMEM;2393 mem_node = get_max_resource(&(resources->mem_head), 0x100000);2394 if (!mem_node)2395 return -ENOMEM;2396 p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000);2397 if (!p_mem_node)2398 return -ENOMEM;2399 dbg("Setup the IO, memory, and prefetchable windows\n");2400 dbg("io_node\n");2401 dbg("(base, len, next) (%x, %x, %p)\n", io_node->base,2402 io_node->length, io_node->next);2403 dbg("mem_node\n");2404 dbg("(base, len, next) (%x, %x, %p)\n", mem_node->base,2405 mem_node->length, mem_node->next);2406 dbg("p_mem_node\n");2407 dbg("(base, len, next) (%x, %x, %p)\n", p_mem_node->base,2408 p_mem_node->length, p_mem_node->next);2409 2410 /* set up the IRQ info */2411 if (!resources->irqs) {2412 irqs.barber_pole = 0;2413 irqs.interrupt[0] = 0;2414 irqs.interrupt[1] = 0;2415 irqs.interrupt[2] = 0;2416 irqs.interrupt[3] = 0;2417 irqs.valid_INT = 0;2418 } else {2419 irqs.barber_pole = resources->irqs->barber_pole;2420 irqs.interrupt[0] = resources->irqs->interrupt[0];2421 irqs.interrupt[1] = resources->irqs->interrupt[1];2422 irqs.interrupt[2] = resources->irqs->interrupt[2];2423 irqs.interrupt[3] = resources->irqs->interrupt[3];2424 irqs.valid_INT = resources->irqs->valid_INT;2425 }2426 2427 /* set up resource lists that are now aligned on top and bottom2428 * for anything behind the bridge. */2429 temp_resources.bus_head = bus_node;2430 temp_resources.io_head = io_node;2431 temp_resources.mem_head = mem_node;2432 temp_resources.p_mem_head = p_mem_node;2433 temp_resources.irqs = &irqs;2434 2435 /* Make copies of the nodes we are going to pass down so that2436 * if there is a problem,we can just use these to free resources2437 */2438 hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);2439 hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);2440 hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);2441 hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL);2442 2443 if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {2444 kfree(hold_bus_node);2445 kfree(hold_IO_node);2446 kfree(hold_mem_node);2447 kfree(hold_p_mem_node);2448 2449 return 1;2450 }2451 2452 memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));2453 2454 bus_node->base += 1;2455 bus_node->length -= 1;2456 bus_node->next = NULL;2457 2458 /* If we have IO resources copy them and fill in the bridge's2459 * IO range registers */2460 memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));2461 io_node->next = NULL;2462 2463 /* set IO base and Limit registers */2464 temp_byte = io_node->base >> 8;2465 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);2466 2467 temp_byte = (io_node->base + io_node->length - 1) >> 8;2468 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);2469 2470 /* Copy the memory resources and fill in the bridge's memory2471 * range registers.2472 */2473 memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));2474 mem_node->next = NULL;2475 2476 /* set Mem base and Limit registers */2477 temp_word = mem_node->base >> 16;2478 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);2479 2480 temp_word = (mem_node->base + mem_node->length - 1) >> 16;2481 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);2482 2483 memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));2484 p_mem_node->next = NULL;2485 2486 /* set Pre Mem base and Limit registers */2487 temp_word = p_mem_node->base >> 16;2488 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);2489 2490 temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;2491 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);2492 2493 /* Adjust this to compensate for extra adjustment in first loop2494 */2495 irqs.barber_pole--;2496 2497 rc = 0;2498 2499 /* Here we actually find the devices and configure them */2500 for (device = 0; (device <= 0x1F) && !rc; device++) {2501 irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;2502 2503 ID = 0xFFFFFFFF;2504 pci_bus->number = hold_bus_node->base;2505 pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), 0x00, &ID);2506 pci_bus->number = func->bus;2507 2508 if (!PCI_POSSIBLE_ERROR(ID)) { /* device present */2509 /* Setup slot structure. */2510 new_slot = cpqhp_slot_create(hold_bus_node->base);2511 2512 if (new_slot == NULL) {2513 rc = -ENOMEM;2514 continue;2515 }2516 2517 new_slot->bus = hold_bus_node->base;2518 new_slot->device = device;2519 new_slot->function = 0;2520 new_slot->is_a_board = 1;2521 new_slot->status = 0;2522 2523 rc = configure_new_device(ctrl, new_slot, 1, &temp_resources);2524 dbg("configure_new_device rc=0x%x\n", rc);2525 } /* End of IF (device in slot?) */2526 } /* End of FOR loop */2527 2528 if (rc)2529 goto free_and_out;2530 /* save the interrupt routing information */2531 if (resources->irqs) {2532 resources->irqs->interrupt[0] = irqs.interrupt[0];2533 resources->irqs->interrupt[1] = irqs.interrupt[1];2534 resources->irqs->interrupt[2] = irqs.interrupt[2];2535 resources->irqs->interrupt[3] = irqs.interrupt[3];2536 resources->irqs->valid_INT = irqs.valid_INT;2537 } else if (!behind_bridge) {2538 /* We need to hook up the interrupts here */2539 for (cloop = 0; cloop < 4; cloop++) {2540 if (irqs.valid_INT & (0x01 << cloop)) {2541 rc = cpqhp_set_irq(func->bus, func->device,2542 cloop + 1, irqs.interrupt[cloop]);2543 if (rc)2544 goto free_and_out;2545 }2546 } /* end of for loop */2547 }2548 /* Return unused bus resources2549 * First use the temporary node to store information for2550 * the board */2551 if (bus_node && temp_resources.bus_head) {2552 hold_bus_node->length = bus_node->base - hold_bus_node->base;2553 2554 hold_bus_node->next = func->bus_head;2555 func->bus_head = hold_bus_node;2556 2557 temp_byte = temp_resources.bus_head->base - 1;2558 2559 /* set subordinate bus */2560 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);2561 2562 if (temp_resources.bus_head->length == 0) {2563 kfree(temp_resources.bus_head);2564 temp_resources.bus_head = NULL;2565 } else {2566 return_resource(&(resources->bus_head), temp_resources.bus_head);2567 }2568 }2569 2570 /* If we have IO space available and there is some left,2571 * return the unused portion */2572 if (hold_IO_node && temp_resources.io_head) {2573 io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),2574 &hold_IO_node, 0x1000);2575 2576 /* Check if we were able to split something off */2577 if (io_node) {2578 hold_IO_node->base = io_node->base + io_node->length;2579 2580 temp_byte = (hold_IO_node->base) >> 8;2581 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_IO_BASE, temp_byte);2582 2583 return_resource(&(resources->io_head), io_node);2584 }2585 2586 io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);2587 2588 /* Check if we were able to split something off */2589 if (io_node) {2590 /* First use the temporary node to store2591 * information for the board */2592 hold_IO_node->length = io_node->base - hold_IO_node->base;2593 2594 /* If we used any, add it to the board's list */2595 if (hold_IO_node->length) {2596 hold_IO_node->next = func->io_head;2597 func->io_head = hold_IO_node;2598 2599 temp_byte = (io_node->base - 1) >> 8;2600 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);2601 2602 return_resource(&(resources->io_head), io_node);2603 } else {2604 /* it doesn't need any IO */2605 temp_word = 0x0000;2606 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_IO_LIMIT, temp_word);2607 2608 return_resource(&(resources->io_head), io_node);2609 kfree(hold_IO_node);2610 }2611 } else {2612 /* it used most of the range */2613 hold_IO_node->next = func->io_head;2614 func->io_head = hold_IO_node;2615 }2616 } else if (hold_IO_node) {2617 /* it used the whole range */2618 hold_IO_node->next = func->io_head;2619 func->io_head = hold_IO_node;2620 }2621 /* If we have memory space available and there is some left,2622 * return the unused portion */2623 if (hold_mem_node && temp_resources.mem_head) {2624 mem_node = do_pre_bridge_resource_split(&(temp_resources. mem_head),2625 &hold_mem_node, 0x100000);2626 2627 /* Check if we were able to split something off */2628 if (mem_node) {2629 hold_mem_node->base = mem_node->base + mem_node->length;2630 2631 temp_word = (hold_mem_node->base) >> 16;2632 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);2633 2634 return_resource(&(resources->mem_head), mem_node);2635 }2636 2637 mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000);2638 2639 /* Check if we were able to split something off */2640 if (mem_node) {2641 /* First use the temporary node to store2642 * information for the board */2643 hold_mem_node->length = mem_node->base - hold_mem_node->base;2644 2645 if (hold_mem_node->length) {2646 hold_mem_node->next = func->mem_head;2647 func->mem_head = hold_mem_node;2648 2649 /* configure end address */2650 temp_word = (mem_node->base - 1) >> 16;2651 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);2652 2653 /* Return unused resources to the pool */2654 return_resource(&(resources->mem_head), mem_node);2655 } else {2656 /* it doesn't need any Mem */2657 temp_word = 0x0000;2658 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);2659 2660 return_resource(&(resources->mem_head), mem_node);2661 kfree(hold_mem_node);2662 }2663 } else {2664 /* it used most of the range */2665 hold_mem_node->next = func->mem_head;2666 func->mem_head = hold_mem_node;2667 }2668 } else if (hold_mem_node) {2669 /* it used the whole range */2670 hold_mem_node->next = func->mem_head;2671 func->mem_head = hold_mem_node;2672 }2673 /* If we have prefetchable memory space available and there2674 * is some left at the end, return the unused portion */2675 if (temp_resources.p_mem_head) {2676 p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),2677 &hold_p_mem_node, 0x100000);2678 2679 /* Check if we were able to split something off */2680 if (p_mem_node) {2681 hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;2682 2683 temp_word = (hold_p_mem_node->base) >> 16;2684 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);2685 2686 return_resource(&(resources->p_mem_head), p_mem_node);2687 }2688 2689 p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000);2690 2691 /* Check if we were able to split something off */2692 if (p_mem_node) {2693 /* First use the temporary node to store2694 * information for the board */2695 hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;2696 2697 /* If we used any, add it to the board's list */2698 if (hold_p_mem_node->length) {2699 hold_p_mem_node->next = func->p_mem_head;2700 func->p_mem_head = hold_p_mem_node;2701 2702 temp_word = (p_mem_node->base - 1) >> 16;2703 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);2704 2705 return_resource(&(resources->p_mem_head), p_mem_node);2706 } else {2707 /* it doesn't need any PMem */2708 temp_word = 0x0000;2709 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);2710 2711 return_resource(&(resources->p_mem_head), p_mem_node);2712 kfree(hold_p_mem_node);2713 }2714 } else {2715 /* it used the most of the range */2716 hold_p_mem_node->next = func->p_mem_head;2717 func->p_mem_head = hold_p_mem_node;2718 }2719 } else if (hold_p_mem_node) {2720 /* it used the whole range */2721 hold_p_mem_node->next = func->p_mem_head;2722 func->p_mem_head = hold_p_mem_node;2723 }2724 /* We should be configuring an IRQ and the bridge's base address2725 * registers if it needs them. Although we have never seen such2726 * a device */2727 2728 /* enable card */2729 command = 0x0157; /* = PCI_COMMAND_IO |2730 * PCI_COMMAND_MEMORY |2731 * PCI_COMMAND_MASTER |2732 * PCI_COMMAND_INVALIDATE |2733 * PCI_COMMAND_PARITY |2734 * PCI_COMMAND_SERR */2735 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);2736 2737 /* set Bridge Control Register */2738 command = 0x07; /* = PCI_BRIDGE_CTL_PARITY |2739 * PCI_BRIDGE_CTL_SERR |2740 * PCI_BRIDGE_CTL_NO_ISA */2741 rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);2742 } else if ((temp_byte & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_NORMAL) {2743 /* Standard device */2744 rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);2745 2746 if (class_code == PCI_BASE_CLASS_DISPLAY) {2747 /* Display (video) adapter (not supported) */2748 return DEVICE_TYPE_NOT_SUPPORTED;2749 }2750 /* Figure out IO and memory needs */2751 for (cloop = 0x10; cloop <= 0x24; cloop += 4) {2752 temp_register = 0xFFFFFFFF;2753 2754 dbg("CND: bus=%d, devfn=%d, offset=%d\n", pci_bus->number, devfn, cloop);2755 rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);2756 2757 rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);2758 dbg("CND: base = 0x%x\n", temp_register);2759 2760 if (temp_register) { /* If this register is implemented */2761 if ((temp_register & 0x03L) == 0x01) {2762 /* Map IO */2763 2764 /* set base = amount of IO space */2765 base = temp_register & 0xFFFFFFFC;2766 base = ~base + 1;2767 2768 dbg("CND: length = 0x%x\n", base);2769 io_node = get_io_resource(&(resources->io_head), base);2770 if (!io_node)2771 return -ENOMEM;2772 dbg("Got io_node start = %8.8x, length = %8.8x next (%p)\n",2773 io_node->base, io_node->length, io_node->next);2774 dbg("func (%p) io_head (%p)\n", func, func->io_head);2775 2776 /* allocate the resource to the board */2777 base = io_node->base;2778 io_node->next = func->io_head;2779 func->io_head = io_node;2780 } else if ((temp_register & 0x0BL) == 0x08) {2781 /* Map prefetchable memory */2782 base = temp_register & 0xFFFFFFF0;2783 base = ~base + 1;2784 2785 dbg("CND: length = 0x%x\n", base);2786 p_mem_node = get_resource(&(resources->p_mem_head), base);2787 2788 /* allocate the resource to the board */2789 if (p_mem_node) {2790 base = p_mem_node->base;2791 2792 p_mem_node->next = func->p_mem_head;2793 func->p_mem_head = p_mem_node;2794 } else2795 return -ENOMEM;2796 } else if ((temp_register & 0x0BL) == 0x00) {2797 /* Map memory */2798 base = temp_register & 0xFFFFFFF0;2799 base = ~base + 1;2800 2801 dbg("CND: length = 0x%x\n", base);2802 mem_node = get_resource(&(resources->mem_head), base);2803 2804 /* allocate the resource to the board */2805 if (mem_node) {2806 base = mem_node->base;2807 2808 mem_node->next = func->mem_head;2809 func->mem_head = mem_node;2810 } else2811 return -ENOMEM;2812 } else {2813 /* Reserved bits or requesting space below 1M */2814 return NOT_ENOUGH_RESOURCES;2815 }2816 2817 rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);2818 2819 /* Check for 64-bit base */2820 if ((temp_register & 0x07L) == 0x04) {2821 cloop += 4;2822 2823 /* Upper 32 bits of address always zero2824 * on today's systems */2825 /* FIXME this is probably not true on2826 * Alpha and ia64??? */2827 base = 0;2828 rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);2829 }2830 }2831 } /* End of base register loop */2832 if (cpqhp_legacy_mode) {2833 /* Figure out which interrupt pin this function uses */2834 rc = pci_bus_read_config_byte(pci_bus, devfn,2835 PCI_INTERRUPT_PIN, &temp_byte);2836 2837 /* If this function needs an interrupt and we are behind2838 * a bridge and the pin is tied to something that's2839 * already mapped, set this one the same */2840 if (temp_byte && resources->irqs &&2841 (resources->irqs->valid_INT &2842 (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {2843 /* We have to share with something already set up */2844 IRQ = resources->irqs->interrupt[(temp_byte +2845 resources->irqs->barber_pole - 1) & 0x03];2846 } else {2847 /* Program IRQ based on card type */2848 rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);2849 2850 if (class_code == PCI_BASE_CLASS_STORAGE)2851 IRQ = cpqhp_disk_irq;2852 else2853 IRQ = cpqhp_nic_irq;2854 }2855 2856 /* IRQ Line */2857 rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);2858 }2859 2860 if (!behind_bridge) {2861 rc = cpqhp_set_irq(func->bus, func->device, temp_byte, IRQ);2862 if (rc)2863 return 1;2864 } else {2865 /* TBD - this code may also belong in the other clause2866 * of this If statement */2867 resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;2868 resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;2869 }2870 2871 /* Latency Timer */2872 temp_byte = 0x40;2873 rc = pci_bus_write_config_byte(pci_bus, devfn,2874 PCI_LATENCY_TIMER, temp_byte);2875 2876 /* Cache Line size */2877 temp_byte = 0x08;2878 rc = pci_bus_write_config_byte(pci_bus, devfn,2879 PCI_CACHE_LINE_SIZE, temp_byte);2880 2881 /* disable ROM base Address */2882 temp_dword = 0x00L;2883 rc = pci_bus_write_config_word(pci_bus, devfn,2884 PCI_ROM_ADDRESS, temp_dword);2885 2886 /* enable card */2887 temp_word = 0x0157; /* = PCI_COMMAND_IO |2888 * PCI_COMMAND_MEMORY |2889 * PCI_COMMAND_MASTER |2890 * PCI_COMMAND_INVALIDATE |2891 * PCI_COMMAND_PARITY |2892 * PCI_COMMAND_SERR */2893 rc = pci_bus_write_config_word(pci_bus, devfn,2894 PCI_COMMAND, temp_word);2895 } else { /* End of Not-A-Bridge else */2896 /* It's some strange type of PCI adapter (Cardbus?) */2897 return DEVICE_TYPE_NOT_SUPPORTED;2898 }2899 2900 func->configured = 1;2901 2902 return 0;2903free_and_out:2904 cpqhp_destroy_resource_list(&temp_resources);2905 2906 return_resource(&(resources->bus_head), hold_bus_node);2907 return_resource(&(resources->io_head), hold_IO_node);2908 return_resource(&(resources->mem_head), hold_mem_node);2909 return_resource(&(resources->p_mem_head), hold_p_mem_node);2910 return rc;2911}2912