1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * mdio-boardinfo - Collect pre-declarations for MDIO devices 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/slab.h> 8 #include <linux/export.h> 9 #include <linux/mutex.h> 10 #include <linux/list.h> 11 12 #include "mdio-boardinfo.h" 13 14 static LIST_HEAD(mdio_board_list); 15 static DEFINE_MUTEX(mdio_board_lock); 16 17 /** 18 * mdiobus_setup_mdiodev_from_board_info - create and setup MDIO devices 19 * from pre-collected board specific MDIO information 20 * @bus: Bus the board_info belongs to 21 * @cb: Callback to create device on bus 22 * Context: can sleep 23 */ 24 void mdiobus_setup_mdiodev_from_board_info(struct mii_bus *bus, 25 int (*cb) 26 (struct mii_bus *bus, 27 struct mdio_board_info *bi)) 28 { 29 struct mdio_board_entry *be; 30 struct mdio_board_entry *tmp; 31 struct mdio_board_info *bi; 32 int ret; 33 34 mutex_lock(&mdio_board_lock); 35 list_for_each_entry_safe(be, tmp, &mdio_board_list, list) { 36 bi = &be->board_info; 37 38 if (strcmp(bus->id, bi->bus_id)) 39 continue; 40 41 mutex_unlock(&mdio_board_lock); 42 ret = cb(bus, bi); 43 mutex_lock(&mdio_board_lock); 44 if (ret) 45 continue; 46 47 } 48 mutex_unlock(&mdio_board_lock); 49 } 50 EXPORT_SYMBOL(mdiobus_setup_mdiodev_from_board_info); 51 52 /** 53 * mdio_register_board_info - register MDIO devices for a given board 54 * @info: array of devices descriptors 55 * @n: number of descriptors provided 56 * Context: can sleep 57 * 58 * The board info passed can be marked with __initdata but be pointers 59 * such as platform_data etc. are copied as-is 60 */ 61 int mdiobus_register_board_info(const struct mdio_board_info *info, 62 unsigned int n) 63 { 64 struct mdio_board_entry *be; 65 unsigned int i; 66 67 be = kcalloc(n, sizeof(*be), GFP_KERNEL); 68 if (!be) 69 return -ENOMEM; 70 71 for (i = 0; i < n; i++, be++, info++) { 72 memcpy(&be->board_info, info, sizeof(*info)); 73 mutex_lock(&mdio_board_lock); 74 list_add_tail(&be->list, &mdio_board_list); 75 mutex_unlock(&mdio_board_lock); 76 } 77 78 return 0; 79 } 80 EXPORT_SYMBOL(mdiobus_register_board_info); 81