📄 ibmphp_core.c
字号:
ibmphp_unlock_operations(); debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value); return rc;}/*static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 * value, u8 flag){ int rc = -ENODEV; struct slot *pslot; struct slot myslot; debug("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); if (flag) ibmphp_lock_operations(); if (hotplug_slot && value) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status)); if (!(SLOT_LATCH (myslot.status)) && (SLOT_PRESENT (myslot.status))) { rc = ibmphp_hpc_readslot(pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status)); if (!rc) *value = SLOT_SPEED(myslot.ext_status); } else *value = MAX_ADAPTER_NONE; } } if (flag) ibmphp_unlock_operations(); debug("get_max_adapter_speed_1 - Exit rc[%d] value[%x]\n", rc, *value); return rc;}static int get_bus_name(struct hotplug_slot *hotplug_slot, char * value){ int rc = -ENODEV; struct slot *pslot = NULL; debug("get_bus_name - Entry hotplug_slot[%lx]\n", (ulong)hotplug_slot); ibmphp_lock_operations(); if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { rc = 0; snprintf(value, 100, "Bus %x", pslot->bus); } } else rc = -ENODEV; ibmphp_unlock_operations(); debug("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value); return rc;}*//**************************************************************************** * This routine will initialize the ops data structure used in the validate * function. It will also power off empty slots that are powered on since BIOS * leaves those on, albeit disconnected ****************************************************************************/static int __init init_ops(void){ struct slot *slot_cur; struct list_head *tmp; int retval; int rc; list_for_each(tmp, &ibmphp_slot_head) { slot_cur = list_entry(tmp, struct slot, ibm_slot_list); if (!slot_cur) return -ENODEV; debug("BEFORE GETTING SLOT STATUS, slot # %x\n", slot_cur->number); if (slot_cur->ctrl->revision == 0xFF) if (get_ctrl_revision(slot_cur, &slot_cur->ctrl->revision)) return -1; if (slot_cur->bus_on->current_speed == 0xFF) if (get_cur_bus_info(&slot_cur)) return -1; if (slot_cur->ctrl->options == 0xFF) if (get_hpc_options(slot_cur, &slot_cur->ctrl->options)) return -1; retval = slot_update(&slot_cur); if (retval) return retval; debug("status = %x\n", slot_cur->status); debug("ext_status = %x\n", slot_cur->ext_status); debug("SLOT_POWER = %x\n", SLOT_POWER(slot_cur->status)); debug("SLOT_PRESENT = %x\n", SLOT_PRESENT(slot_cur->status)); debug("SLOT_LATCH = %x\n", SLOT_LATCH(slot_cur->status)); if ((SLOT_PWRGD(slot_cur->status)) && !(SLOT_PRESENT(slot_cur->status)) && !(SLOT_LATCH(slot_cur->status))) { debug("BEFORE POWER OFF COMMAND\n"); rc = power_off(slot_cur); if (rc) return rc; /* retval = slot_update(&slot_cur); * if (retval) * return retval; * ibmphp_update_slot_info(slot_cur); */ } } init_flag = 0; return 0;}/* This operation will check whether the slot is within the bounds and * the operation is valid to perform on that slot * Parameters: slot, operation * Returns: 0 or error codes */static int validate(struct slot *slot_cur, int opn){ int number; int retval; if (!slot_cur) return -ENODEV; number = slot_cur->number; if ((number > max_slots) || (number < 0)) return -EBADSLT; debug("slot_number in validate is %d\n", slot_cur->number); retval = slot_update(&slot_cur); if (retval) return retval; switch (opn) { case ENABLE: if (!(SLOT_PWRGD(slot_cur->status)) && (SLOT_PRESENT(slot_cur->status)) && !(SLOT_LATCH(slot_cur->status))) return 0; break; case DISABLE: if ((SLOT_PWRGD(slot_cur->status)) && (SLOT_PRESENT(slot_cur->status)) && !(SLOT_LATCH(slot_cur->status))) return 0; break; default: break; } err("validate failed....\n"); return -EINVAL;}/**************************************************************************** * This routine is for updating the data structures in the hotplug core * Parameters: struct slot * Returns: 0 or error ****************************************************************************/int ibmphp_update_slot_info(struct slot *slot_cur){ struct hotplug_slot_info *info; int rc; u8 bus_speed; u8 mode; info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!info) { err("out of system memory\n"); return -ENOMEM; } info->power_status = SLOT_PWRGD(slot_cur->status); info->attention_status = SLOT_ATTN(slot_cur->status, slot_cur->ext_status); info->latch_status = SLOT_LATCH(slot_cur->status); if (!SLOT_PRESENT(slot_cur->status)) { info->adapter_status = 0;/* info->max_adapter_speed_status = MAX_ADAPTER_NONE; */ } else { info->adapter_status = 1;/* get_max_adapter_speed_1(slot_cur->hotplug_slot, &info->max_adapter_speed_status, 0); */ } bus_speed = slot_cur->bus_on->current_speed; mode = slot_cur->bus_on->current_bus_mode; switch (bus_speed) { case BUS_SPEED_33: break; case BUS_SPEED_66: if (mode == BUS_MODE_PCIX) bus_speed += 0x01; else if (mode == BUS_MODE_PCI) ; else bus_speed = PCI_SPEED_UNKNOWN; break; case BUS_SPEED_100: case BUS_SPEED_133: bus_speed += 0x01; break; default: bus_speed = PCI_SPEED_UNKNOWN; } info->cur_bus_speed = bus_speed; info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed; // To do: bus_names rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info); kfree(info); return rc;}/****************************************************************************** * This function will return the pci_func, given bus and devfunc, or NULL. It * is called from visit routines ******************************************************************************/static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function){ struct pci_func *func_cur; struct slot *slot_cur; struct list_head * tmp; list_for_each(tmp, &ibmphp_slot_head) { slot_cur = list_entry(tmp, struct slot, ibm_slot_list); if (slot_cur->func) { func_cur = slot_cur->func; while (func_cur) { if ((func_cur->busno == busno) && (func_cur->device == device) && (func_cur->function == function)) return func_cur; func_cur = func_cur->next; } } } return NULL;}/************************************************************* * This routine frees up memory used by struct slot, including * the pointers to pci_func, bus, hotplug_slot, controller, * and deregistering from the hotplug core *************************************************************/static void free_slots(void){ struct slot *slot_cur; struct list_head * tmp; struct list_head * next; debug("%s -- enter\n", __func__); list_for_each_safe(tmp, next, &ibmphp_slot_head) { slot_cur = list_entry(tmp, struct slot, ibm_slot_list); pci_hp_deregister(slot_cur->hotplug_slot); } debug("%s -- exit\n", __func__);}static void ibm_unconfigure_device(struct pci_func *func){ struct pci_dev *temp; u8 j; debug("inside %s\n", __func__); debug("func->device = %x, func->function = %x\n", func->device, func->function); debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0); for (j = 0; j < 0x08; j++) { temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j); if (temp) { pci_remove_bus_device(temp); pci_dev_put(temp); } } pci_dev_put(func->dev);}/* * The following function is to fix kernel bug regarding * getting bus entries, here we manually add those primary * bus entries to kernel bus structure whenever apply */static u8 bus_structure_fixup(u8 busno){ struct pci_bus *bus; struct pci_dev *dev; u16 l; if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num(busno))) return 1; bus = kmalloc(sizeof(*bus), GFP_KERNEL); if (!bus) { err("%s - out of memory\n", __func__); return 1; } dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { kfree(bus); err("%s - out of memory\n", __func__); return 1; } bus->number = busno; bus->ops = ibmphp_pci_bus->ops; dev->bus = bus; for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) { if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) && (l != 0x0000) && (l != 0xffff)) { debug("%s - Inside bus_struture_fixup()\n", __func__); pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL); break; } } kfree(dev); kfree(bus); return 0;}static int ibm_configure_device(struct pci_func *func){ unsigned char bus; struct pci_bus *child; int num; int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ if (!(bus_structure_fixup(func->busno))) flag = 1; if (func->dev == NULL) func->dev = pci_get_bus_and_slot(func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { struct pci_bus *bus = pci_find_bus(0, func->busno); if (!bus) return 0; num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function)); if (num) pci_bus_add_devices(bus); func->dev = pci_get_bus_and_slot(func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { err("ERROR... : pci_dev still NULL\n"); return 0; } } if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus); child = pci_add_new_bus(func->dev->bus, func->dev, bus); pci_do_scan_bus(child); } return 0;}/******************************************************* * Returns whether the bus is empty or not *******************************************************/static int is_bus_empty(struct slot * slot_cur){ int rc; struct slot * tmp_slot; u8 i = slot_cur->bus_on->slot_min; while (i <= slot_cur->bus_on->slot_max) { if (i == slot_cur->number) { i++; continue; } tmp_slot = ibmphp_get_slot_from_physical_num(i); if (!tmp_slot) return 0; rc = slot_update(&tmp_slot); if (rc) return 0; if (SLOT_PRESENT(tmp_slot->status) && SLOT_PWRGD(tmp_slot->status)) return 0; i++; } return 1;}/*********************************************************** * If the HPC permits and the bus currently empty, tries to set the * bus speed and mode at the maximum card and bus capability * Parameters: slot * Returns: bus is set (0) or error code ***********************************************************/static int set_bus(struct slot * slot_cur){ int rc; u8 speed; u8 cmd = 0x0; int retval; static struct pci_device_id ciobx[] = { { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 0x0101) }, { }, }; debug("%s - entry slot # %d\n", __func__, slot_cur->number); if (SET_BUS_STATUS(slot_cur->ctrl) && is_bus_empty(slot_cur)) { rc = slot_update(&slot_cur); if (rc) return rc; speed = SLOT_SPEED(slot_cur->ext_status); debug("ext_status = %x, speed = %x\n", slot_cur->ext_status, speed); switch (speed) { case HPC_SLOT_SPEED_33: cmd = HPC_BUS_33CONVMODE; break; case HPC_SLOT_SPEED_66: if (SLOT_PCIX(slot_cur->ext_status)) { if ((slot_cur->supported_speed >= BUS_SPEED_66) && (slot_cur->supported_bus_mode == BUS_MODE_PCIX)) cmd = HPC_BUS_66PCIXMODE; else if (!SLOT_BUS_MODE(slot_cur->ext_status)) /* if max slot/bus capability is 66 pci and there's no bus mode mismatch, then the adapter supports 66 pci */ cmd = HPC_BUS_66CONVMODE; else cmd = HPC_BUS_33CONVMODE; } else { if (slot_cur->supported_speed >= BUS_SPEED_66) cmd = HPC_BUS_66CONVMODE; else cmd = HPC_BUS_33CONVMODE; } break; case HPC_SLOT_SPEED_133: switch (slot_cur->supported_speed) { case BUS_SPEED_33: cmd = HPC_BUS_33CONVMODE; break; case BUS_SPEED_66: if (slot_cur->supported_bus_mode == BUS_MODE_PCIX) cmd = HPC_BUS_66PCIXMODE; else cmd = HPC_BUS_66CONVMODE; break; case BUS_SPEED_100: cmd = HPC_BUS_100PCIXMODE; break; case BUS_SPEED_133: /* This is to take care of the bug in CIOBX chip */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -