Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

device property: Add helper to match multiple connections

In some cases multiple connections with the same connection id
needs to be resolved from a fwnode graph.

One such example is when separate hardware is used for performing muxing
and/or orientation switching of the SuperSpeed and SBU lines in a USB
Type-C connector. In this case the connector needs to belong to a graph
with multiple matching remote endpoints, and the Type-C controller needs
to be able to resolve them both.

Add a new API that allows this kind of lookup.

Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20220422222351.1297276-2-bjorn.andersson@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Bjorn Andersson and committed by
Greg Kroah-Hartman
7a20917d 3c162511

+114
+109
drivers/base/property.c
··· 1218 1218 return NULL; 1219 1219 } 1220 1220 1221 + static unsigned int fwnode_graph_devcon_matches(struct fwnode_handle *fwnode, 1222 + const char *con_id, void *data, 1223 + devcon_match_fn_t match, 1224 + void **matches, 1225 + unsigned int matches_len) 1226 + { 1227 + struct fwnode_handle *node; 1228 + struct fwnode_handle *ep; 1229 + unsigned int count = 0; 1230 + void *ret; 1231 + 1232 + fwnode_graph_for_each_endpoint(fwnode, ep) { 1233 + if (matches && count >= matches_len) { 1234 + fwnode_handle_put(ep); 1235 + break; 1236 + } 1237 + 1238 + node = fwnode_graph_get_remote_port_parent(ep); 1239 + if (!fwnode_device_is_available(node)) { 1240 + fwnode_handle_put(node); 1241 + continue; 1242 + } 1243 + 1244 + ret = match(node, con_id, data); 1245 + fwnode_handle_put(node); 1246 + if (ret) { 1247 + if (matches) 1248 + matches[count] = ret; 1249 + count++; 1250 + } 1251 + } 1252 + return count; 1253 + } 1254 + 1221 1255 static void * 1222 1256 fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id, 1223 1257 void *data, devcon_match_fn_t match) ··· 1272 1238 } 1273 1239 1274 1240 return NULL; 1241 + } 1242 + 1243 + static unsigned int fwnode_devcon_matches(struct fwnode_handle *fwnode, 1244 + const char *con_id, void *data, 1245 + devcon_match_fn_t match, 1246 + void **matches, 1247 + unsigned int matches_len) 1248 + { 1249 + struct fwnode_handle *node; 1250 + unsigned int count = 0; 1251 + unsigned int i; 1252 + void *ret; 1253 + 1254 + for (i = 0; ; i++) { 1255 + if (matches && count >= matches_len) 1256 + break; 1257 + 1258 + node = fwnode_find_reference(fwnode, con_id, i); 1259 + if (IS_ERR(node)) 1260 + break; 1261 + 1262 + ret = match(node, NULL, data); 1263 + fwnode_handle_put(node); 1264 + if (ret) { 1265 + if (matches) 1266 + matches[count] = ret; 1267 + count++; 1268 + } 1269 + } 1270 + 1271 + return count; 1275 1272 } 1276 1273 1277 1274 /** ··· 1332 1267 return fwnode_devcon_match(fwnode, con_id, data, match); 1333 1268 } 1334 1269 EXPORT_SYMBOL_GPL(fwnode_connection_find_match); 1270 + 1271 + /** 1272 + * fwnode_connection_find_matches - Find connections from a device node 1273 + * @fwnode: Device node with the connection 1274 + * @con_id: Identifier for the connection 1275 + * @data: Data for the match function 1276 + * @match: Function to check and convert the connection description 1277 + * @matches: (Optional) array of pointers to fill with matches 1278 + * @matches_len: Length of @matches 1279 + * 1280 + * Find up to @matches_len connections with unique identifier @con_id between 1281 + * @fwnode and other device nodes. @match will be used to convert the 1282 + * connection description to data the caller is expecting to be returned 1283 + * through the @matches array. 1284 + * If @matches is NULL @matches_len is ignored and the total number of resolved 1285 + * matches is returned. 1286 + * 1287 + * Return: Number of matches resolved, or negative errno. 1288 + */ 1289 + int fwnode_connection_find_matches(struct fwnode_handle *fwnode, 1290 + const char *con_id, void *data, 1291 + devcon_match_fn_t match, 1292 + void **matches, unsigned int matches_len) 1293 + { 1294 + unsigned int count_graph; 1295 + unsigned int count_ref; 1296 + 1297 + if (!fwnode || !match) 1298 + return -EINVAL; 1299 + 1300 + count_graph = fwnode_graph_devcon_matches(fwnode, con_id, data, match, 1301 + matches, matches_len); 1302 + 1303 + if (matches) { 1304 + matches += count_graph; 1305 + matches_len -= count_graph; 1306 + } 1307 + 1308 + count_ref = fwnode_devcon_matches(fwnode, con_id, data, match, 1309 + matches, matches_len); 1310 + 1311 + return count_graph + count_ref; 1312 + } 1313 + EXPORT_SYMBOL_GPL(fwnode_connection_find_matches);
+5
include/linux/property.h
··· 447 447 return fwnode_connection_find_match(dev_fwnode(dev), con_id, data, match); 448 448 } 449 449 450 + int fwnode_connection_find_matches(struct fwnode_handle *fwnode, 451 + const char *con_id, void *data, 452 + devcon_match_fn_t match, 453 + void **matches, unsigned int matches_len); 454 + 450 455 /* -------------------------------------------------------------------------- */ 451 456 /* Software fwnode support - when HW description is incomplete or missing */ 452 457