/ src / device / resource_allocator_common.c
resource_allocator_common.c
 1  /* SPDX-License-Identifier: GPL-2.0-only */
 2  
 3  #include <device/device.h>
 4  #include <stddef.h>
 5  
 6  struct pick_largest_state {
 7  	struct resource *last;
 8  	const struct device *result_dev;
 9  	struct resource *result;
10  	int seen_last;
11  };
12  
13  static void pick_largest_resource(void *gp, struct device *dev,
14  				  struct resource *resource)
15  {
16  	struct pick_largest_state *state = gp;
17  	struct resource *last;
18  
19  	last = state->last;
20  
21  	/* Be certain to pick the successor to last. */
22  	if (resource == last) {
23  		state->seen_last = 1;
24  		return;
25  	}
26  	if (resource->flags & IORESOURCE_FIXED)
27  		return;	/* Skip it. */
28  	if (last && ((last->align < resource->align) ||
29  		     ((last->align == resource->align) &&
30  		      (last->size < resource->size)) ||
31  		     ((last->align == resource->align) &&
32  		      (last->size == resource->size) && (!state->seen_last)))) {
33  		return;
34  	}
35  	if (!state->result ||
36  	    (state->result->align < resource->align) ||
37  	    ((state->result->align == resource->align) &&
38  	     (state->result->size < resource->size))) {
39  		state->result_dev = dev;
40  		state->result = resource;
41  	}
42  }
43  
44  const struct device *largest_resource(struct bus *bus,
45  				      struct resource **result_res,
46  				      unsigned long type_mask,
47  				      unsigned long type)
48  {
49  	struct pick_largest_state state;
50  
51  	state.last = *result_res;
52  	state.result_dev = NULL;
53  	state.result = NULL;
54  	state.seen_last = 0;
55  
56  	search_bus_resources(bus, type_mask, type, pick_largest_resource,
57  			     &state);
58  
59  	*result_res = state.result;
60  	return state.result_dev;
61  }