/** * get_max_resource - get the largest resource * * Gets the largest node that is at least "size" big from the * list pointed to by head. It aligns the node on top and bottom * to "size" alignment before returning it. */ struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size) { struct pci_resource *max; struct pci_resource *temp; struct pci_resource *split_node; u64 temp_qword; if (!(*head)) return NULL; if (acpiphp_resource_sort_and_combine(head)) return NULL; if (sort_by_max_size(head)) return NULL; for (max = *head;max; max = max->next) { /* If not big enough we could probably just bail, instead we'll continue to the next. */ if (max->length < size) continue; if (max->base & (size - 1)) { /* this one isn't base aligned properly so we'll make a new entry and split it up */ temp_qword = (max->base | (size-1)) + 1; /* Short circuit if adjusted size is too small */ if ((max->length - (temp_qword - max->base)) < size) continue; split_node = acpiphp_make_resource(max->base, temp_qword - max->base); if (!split_node) return NULL; max->base = temp_qword; max->length -= split_node->length; /* Put it next in the list */ split_node->next = max->next; max->next = split_node; } if ((max->base + max->length) & (size - 1)) { /* this one isn't end aligned properly at the top so we'll make a new entry and split it up */ temp_qword = ((max->base + max->length) & ~(size - 1)); split_node = acpiphp_make_resource(temp_qword, max->length + max->base - temp_qword); if (!split_node) return NULL; max->length -= split_node->length; /* Put it in the list */ split_node->next = max->next; max->next = split_node; } /* Make sure it didn't shrink too much when we aligned it */ if (max->length < size) continue; /* Now take it out of the list */ temp = (struct pci_resource*) *head; if (temp == max) { *head = max->next; } else { while (temp && temp->next != max) { temp = temp->next; } temp->next = max->next; } max->next = NULL; return max; } /* If we get here, we couldn't find one */ return NULL; }
/* * get_max_resource * * Gets the largest node that is at least "size" big from the * list pointed to by head. It aligns the node on top and bottom * to "size" alignment before returning it. */ struct pci_resource *hotplug_get_max_resource (struct pci_resource **head, u32 size) { struct pci_resource *max; struct pci_resource *temp; struct pci_resource *split_node; u32 temp_dword; if (!(*head)) return(NULL); if (hotplug_resource_sort_and_combine(head)) return(NULL); if (sort_by_max_size(head)) return(NULL); for (max = *head;max; max = max->next) { // If not big enough we could probably just bail, // instead we'll continue to the next. if (max->length < size) continue; if (max->base & (size - 1)) { // this one isn't base aligned properly // so we'll make a new entry and split it up temp_dword = (max->base | (size-1)) + 1; // Short circuit if adjusted size is too small if ((max->length - (temp_dword - max->base)) < size) continue; split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!split_node) return(NULL); split_node->base = max->base; split_node->length = temp_dword - max->base; max->base = temp_dword; max->length -= split_node->length; // Put it next in the list split_node->next = max->next; max->next = split_node; } if ((max->base + max->length) & (size - 1)) { // this one isn't end aligned properly at the top // so we'll make a new entry and split it up split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!split_node) return(NULL); temp_dword = ((max->base + max->length) & ~(size - 1)); split_node->base = temp_dword; split_node->length = max->length + max->base - split_node->base; max->length -= split_node->length; // Put it in the list split_node->next = max->next; max->next = split_node; } // Make sure it didn't shrink too much when we aligned it if (max->length < size) continue; // Now take it out of the list temp = (struct pci_resource*) *head; if (temp == max) { *head = max->next; } else { while (temp && temp->next != max) { temp = temp->next; } temp->next = max->next; } max->next = NULL; return(max); } // If we get here, we couldn't find one return(NULL); }