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
pick_largest_resource(void * gp,struct device * dev,struct resource * resource)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
largest_resource(struct bus * bus,struct resource ** result_res,unsigned long type_mask,unsigned long type)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 }
62