📄 shpchprm_acpi.c
字号:
}static void free_a_slot(struct acpi_php_slot *aps){ dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun); free_pci_resource (aps->io_head); free_pci_resource (aps->bus_head); free_pci_resource (aps->mem_head); free_pci_resource (aps->p_mem_head); kfree(aps);}static void free_a_bridge( struct acpi_bridge *ab){ struct acpi_php_slot *aps, *next; switch (ab->type) { case BRIDGE_TYPE_HOST: dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); break; case BRIDGE_TYPE_P2P: dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); break; }; /* free slots first */ for (aps = ab->slots; aps; aps = next) { next = aps->next; free_a_slot(aps); } free_pci_resource (ab->io_head); free_pci_resource (ab->tio_head); free_pci_resource (ab->bus_head); free_pci_resource (ab->tbus_head); free_pci_resource (ab->mem_head); free_pci_resource (ab->tmem_head); free_pci_resource (ab->p_mem_head); free_pci_resource (ab->tp_mem_head); kfree(ab);}static void shpchprm_free_bridges ( struct acpi_bridge *ab){ if (!ab) return; if (ab->child) shpchprm_free_bridges (ab->child); if (ab->next) shpchprm_free_bridges (ab->next); free_a_bridge(ab);}void shpchprm_cleanup(void){ shpchprm_free_bridges (acpi_bridges_head);}static int get_number_of_slots ( struct acpi_bridge *ab, int selfonly ){ struct acpi_php_slot *aps; int prev_slot = -1; int slot_num = 0; for ( aps = ab->slots; aps; aps = aps->next) if (aps->dev != prev_slot) { prev_slot = aps->dev; slot_num++; } if (ab->child) slot_num += get_number_of_slots (ab->child, 0); if (selfonly) return slot_num; if (ab->next) slot_num += get_number_of_slots (ab->next, 0); return slot_num;}static int print_acpi_resources (struct acpi_bridge *ab){ struct acpi_php_slot *aps; int i; switch (ab->type) { case BRIDGE_TYPE_HOST: dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle)); break; case BRIDGE_TYPE_P2P: dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle)); break; }; print_pci_resources (ab); for ( i = -1, aps = ab->slots; aps; aps = aps->next) { if (aps->dev == i) continue; dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); print_slot_resources(aps); i = aps->dev; } if (ab->child) print_acpi_resources (ab->child); if (ab->next) print_acpi_resources (ab->next); return 0;}int shpchprm_print_pirt(void){ dbg("SHPCHPRM ACPI Slots\n"); if (acpi_bridges_head) print_acpi_resources (acpi_bridges_head); return 0;}static struct acpi_php_slot * get_acpi_slot ( struct acpi_bridge *ab, u32 sun ){ struct acpi_php_slot *aps = NULL; for ( aps = ab->slots; aps; aps = aps->next) if (aps->sun == sun) return aps; if (!aps && ab->child) { aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun); if (aps) return aps; } if (!aps && ab->next) { aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun); if (aps) return aps; } return aps;}#if 0static void * shpchprm_get_slot(struct slot *slot){ struct acpi_bridge *ab = acpi_bridges_head; struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number); aps->slot = slot; dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); return (void *)aps;}#endifstatic void shpchprm_dump_func_res( struct pci_func *fun){ struct pci_func *func = fun; if (func->bus_head) { dbg(": BUS Resources:\n"); print_pci_resource (func->bus_head); } if (func->io_head) { dbg(": IO Resources:\n"); print_pci_resource (func->io_head); } if (func->mem_head) { dbg(": MEM Resources:\n"); print_pci_resource (func->mem_head); } if (func->p_mem_head) { dbg(": PMEM Resources:\n"); print_pci_resource (func->p_mem_head); }}static void shpchprm_dump_ctrl_res( struct controller *ctlr){ struct controller *ctrl = ctlr; if (ctrl->bus_head) { dbg(": BUS Resources:\n"); print_pci_resource (ctrl->bus_head); } if (ctrl->io_head) { dbg(": IO Resources:\n"); print_pci_resource (ctrl->io_head); } if (ctrl->mem_head) { dbg(": MEM Resources:\n"); print_pci_resource (ctrl->mem_head); } if (ctrl->p_mem_head) { dbg(": PMEM Resources:\n"); print_pci_resource (ctrl->p_mem_head); }}static int shpchprm_get_used_resources ( struct controller *ctrl, struct pci_func *func ){ return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);}static int configure_existing_function( struct controller *ctrl, struct pci_func *func ){ int rc; /* see how much resources the func has used. */ rc = shpchprm_get_used_resources (ctrl, func); if (!rc) { /* subtract the resources used by the func from ctrl resources */ rc = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head); rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head); rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head); rc |= shpchprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); if (rc) warn("aCEF: cannot del used resources\n"); } else err("aCEF: cannot get used resources\n"); return rc;}static int bind_pci_resources_to_slots ( struct controller *ctrl){ struct pci_func *func, new_func; int busn = ctrl->slot_bus; int devn, funn; u32 vid; for (devn = 0; devn < 32; devn++) { for (funn = 0; funn < 8; funn++) { /* if (devn == ctrl->device && funn == ctrl->function) continue; */ /* find out if this entry is for an occupied slot */ vid = 0xFFFFFFFF; pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); if (vid != 0xFFFFFFFF) { func = shpchp_slot_find(busn, devn, funn); if (!func) { memset(&new_func, 0, sizeof(struct pci_func)); new_func.bus = busn; new_func.device = devn; new_func.function = funn; new_func.is_a_board = 1; configure_existing_function(ctrl, &new_func); shpchprm_dump_func_res(&new_func); } else { configure_existing_function(ctrl, func); shpchprm_dump_func_res(func); } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); } } } return 0;}static int bind_pci_resources( struct controller *ctrl, struct acpi_bridge *ab ){ int status = 0; if (ab->bus_head) { dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus); status = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head); if (shpchprm_delete_resources (&ab->bus_head, ctrl->bus_head)) warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus); if (status) { err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); return status; } } else info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus); if (ab->io_head) { dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus); status = shpchprm_add_resources (&ctrl->io_head, ab->io_head); if (shpchprm_delete_resources (&ab->io_head, ctrl->io_head)) warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus); if (status) { err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); return status; } } else info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus); if (ab->mem_head) { dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus); status = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head); if (shpchprm_delete_resources (&ab->mem_head, ctrl->mem_head)) warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus); if (status) { err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); return status; } } else info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus); if (ab->p_mem_head) { dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus); status = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head); if (shpchprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head)) warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus); if (status) { err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); return status; } } else info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus); return status;}static int no_pci_resources( struct acpi_bridge *ab){ return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);}static int find_pci_bridge_resources ( struct controller *ctrl, struct acpi_bridge *ab ){ int rc = 0; struct pci_func func; memset(&func, 0, sizeof(struct pci_func)); func.bus = ab->pbus; func.device = ab->pdevice; func.function = ab->pfunction; func.is_a_board = 1; /* Get used resources for this PCI bridge */ rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD); ab->io_head = func.io_head; ab->mem_head = func.mem_head; ab->p_mem_head = func.p_mem_head; ab->bus_head = func.bus_head; if (ab->bus_head) shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 1); return rc;}static int get_pci_resources_from_bridge( struct controller *ctrl, struct acpi_bridge *ab ){ int rc = 0; dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus); rc = find_pci_bridge_resources (ctrl, ab); shpchp_resource_sort_and_combine(&ab->bus_head); shpchp_resource_sort_and_combine(&ab->io_head); shpchp_resource_sort_and_combine(&ab->mem_head); shpchp_resource_sort_and_combine(&ab->p_mem_head); shpchprm_add_resources (&ab->tbus_head, ab->bus_head); shpchprm_add_resources (&ab->tio_head, ab->io_head); shpchprm_add_resources (&ab->tmem_head, ab->mem_head); shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); return rc;}static int get_pci_resources( struct controller *ctrl, struct acpi_bridge *ab ){ int rc = 0; if (no_pci_resources(ab)) { dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus); rc = get_pci_resources_from_bridge(ctrl, ab); } return rc;}int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum){ int offset = devnum - ctrl->slot_device_offset; dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); return 0;}/* * Get resources for this ctrl. * 1. get total resources from ACPI _CRS or bridge (this ctrl) * 2. find used resources of existing adapters * 3. subtract used resources from total resources */int shpchprm_find_available_resources( struct controller *ctrl){ int rc = 0; struct acpi_bridge *ab; ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number); if (!ab) { err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); return -1; } if (no_pci_resources(ab)) { rc = get_pci_resources(ctrl, ab); if (rc) { err("pfar:cannot get pci resources of PCI 0x%x.\n",ctrl->pci_dev->subordinate->number); return -1; } } rc = bind_pci_resources(ctrl, ab); dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); shpchprm_dump_ctrl_res(ctrl); bind_pci_resources_to_slots (ctrl); dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); shpchprm_dump_ctrl_res(ctrl); return rc;}int shpchprm_set_hpp( struct controller *ctrl, struct pci_func *func, u8 card_type ){ struct acpi_bridge *ab; struct pci_bus lpci_bus, *pci_bus; int rc = 0; unsigned int devfn; u8 cls= 0x08; /* default cache line size */ u8 lt = 0x40; /* default latency timer */ u8 ep = 0; u8 es = 0; memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); pci_bus = &lpci_bus; pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); if (ab) { if (ab->_hpp) { lt = (u8)ab->_hpp->latency_timer; cls = (u8)ab->_hpp->cache_line_size; ep = (u8)ab->_hpp->enable_perr; es = (u8)ab->_hpp->enable_serr; } else dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); } else dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); if (card_type == PCI_HEADER_TYPE_BRIDGE) { /* set subordinate Latency Timer */ rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt); } /* set base Latency Timer */ rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt); dbg(" set latency timer =0x%02x: %x\n", lt, rc); rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls); dbg(" set cache_line_size=0x%02x: %x\n", cls, rc); return rc;}void shpchprm_enable_card( struct controller *ctrl, struct pci_func *func, u8 card_type){ u16 command, cmd, bcommand, bcmd; struct pci_bus lpci_bus, *pci_bus; struct acpi_bridge *ab; unsigned int devfn; int rc; memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); pci_bus = &lpci_bus; pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); if (card_type == PCI_HEADER_TYPE_BRIDGE) { rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); } cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA; ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); if (ab) { if (ab->_hpp) { if (ab->_hpp->enable_perr) { command |= PCI_COMMAND_PARITY; bcommand |= PCI_BRIDGE_CTL_PARITY; } else { command &= ~PCI_COMMAND_PARITY; bcommand &= ~PCI_BRIDGE_CTL_PARITY; } if (ab->_hpp->enable_serr) { command |= PCI_COMMAND_SERR; bcommand |= PCI_BRIDGE_CTL_SERR; } else { command &= ~PCI_COMMAND_SERR; bcommand &= ~PCI_BRIDGE_CTL_SERR; } } else dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); } else dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); if (command != cmd) { rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); } if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) { rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -