Esempio n. 1
0
/**
 * 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;
}
Esempio n. 2
0
/*
 * 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);
}