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 }