Skip to content

Commit a67e947

Browse files
Richard Fitzgeraldrobherring
authored andcommitted
of: Add array read functions with min/max size limits
Add a new set of array reading functions that take a minimum and maximum size limit and will fail if the property size is not within the size limits. This makes it more convenient for drivers that use variable-size DT arrays which must be bounded at both ends - data must be at least N entries but must not overflow the array it is being copied into. It is also more efficient than making this functionality out of existing public functions and avoids duplication. The existing array functions have been left in the API, since there are a very large number of clients of those functions and their existing functionality is still useful. This avoids turning a small API improvement into a major kernel rework. The old functions have been turned into mininmal static inlines calling the new functions. The old functions had no upper limit on the actual size of the dts entry, to preserve this functionality rather than keeping two near-identical implementations, if the new function is called with max=0 there is no limit on the size of the dts entry but only the min number of elements are read. Signed-off-by: Richard Fitzgerald <[email protected]> Signed-off-by: Rob Herring <[email protected]>
1 parent 79ac5d3 commit a67e947

File tree

2 files changed

+234
-66
lines changed

2 files changed

+234
-66
lines changed

drivers/of/base.c

Lines changed: 102 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,108 +1209,145 @@ int of_property_read_u32_index(const struct device_node *np,
12091209
EXPORT_SYMBOL_GPL(of_property_read_u32_index);
12101210

12111211
/**
1212-
* of_property_read_u8_array - Find and read an array of u8 from a property.
1212+
* of_property_read_variable_u8_array - Find and read an array of u8 from a
1213+
* property, with bounds on the minimum and maximum array size.
12131214
*
12141215
* @np: device node from which the property value is to be read.
12151216
* @propname: name of the property to be searched.
12161217
* @out_values: pointer to return value, modified only if return value is 0.
1217-
* @sz: number of array elements to read
1218+
* @sz_min: minimum number of array elements to read
1219+
* @sz_max: maximum number of array elements to read, if zero there is no
1220+
* upper limit on the number of elements in the dts entry but only
1221+
* sz_min will be read.
12181222
*
12191223
* Search for a property in a device node and read 8-bit value(s) from
1220-
* it. Returns 0 on success, -EINVAL if the property does not exist,
1221-
* -ENODATA if property does not have a value, and -EOVERFLOW if the
1222-
* property data isn't large enough.
1224+
* it. Returns number of elements read on success, -EINVAL if the property
1225+
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
1226+
* if the property data is smaller than sz_min or longer than sz_max.
12231227
*
12241228
* dts entry of array should be like:
12251229
* property = /bits/ 8 <0x50 0x60 0x70>;
12261230
*
12271231
* The out_values is modified only if a valid u8 value can be decoded.
12281232
*/
1229-
int of_property_read_u8_array(const struct device_node *np,
1230-
const char *propname, u8 *out_values, size_t sz)
1233+
int of_property_read_variable_u8_array(const struct device_node *np,
1234+
const char *propname, u8 *out_values,
1235+
size_t sz_min, size_t sz_max)
12311236
{
1237+
size_t sz, count;
12321238
const u8 *val = of_find_property_value_of_size(np, propname,
1233-
(sz * sizeof(*out_values)),
1234-
0,
1235-
NULL);
1239+
(sz_min * sizeof(*out_values)),
1240+
(sz_max * sizeof(*out_values)),
1241+
&sz);
12361242

12371243
if (IS_ERR(val))
12381244
return PTR_ERR(val);
12391245

1240-
while (sz--)
1246+
if (!sz_max)
1247+
sz = sz_min;
1248+
else
1249+
sz /= sizeof(*out_values);
1250+
1251+
count = sz;
1252+
while (count--)
12411253
*out_values++ = *val++;
1242-
return 0;
1254+
1255+
return sz;
12431256
}
1244-
EXPORT_SYMBOL_GPL(of_property_read_u8_array);
1257+
EXPORT_SYMBOL_GPL(of_property_read_variable_u8_array);
12451258

12461259
/**
1247-
* of_property_read_u16_array - Find and read an array of u16 from a property.
1260+
* of_property_read_variable_u16_array - Find and read an array of u16 from a
1261+
* property, with bounds on the minimum and maximum array size.
12481262
*
12491263
* @np: device node from which the property value is to be read.
12501264
* @propname: name of the property to be searched.
12511265
* @out_values: pointer to return value, modified only if return value is 0.
1252-
* @sz: number of array elements to read
1266+
* @sz_min: minimum number of array elements to read
1267+
* @sz_max: maximum number of array elements to read, if zero there is no
1268+
* upper limit on the number of elements in the dts entry but only
1269+
* sz_min will be read.
12531270
*
12541271
* Search for a property in a device node and read 16-bit value(s) from
1255-
* it. Returns 0 on success, -EINVAL if the property does not exist,
1256-
* -ENODATA if property does not have a value, and -EOVERFLOW if the
1257-
* property data isn't large enough.
1272+
* it. Returns number of elements read on success, -EINVAL if the property
1273+
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
1274+
* if the property data is smaller than sz_min or longer than sz_max.
12581275
*
12591276
* dts entry of array should be like:
12601277
* property = /bits/ 16 <0x5000 0x6000 0x7000>;
12611278
*
12621279
* The out_values is modified only if a valid u16 value can be decoded.
12631280
*/
1264-
int of_property_read_u16_array(const struct device_node *np,
1265-
const char *propname, u16 *out_values, size_t sz)
1281+
int of_property_read_variable_u16_array(const struct device_node *np,
1282+
const char *propname, u16 *out_values,
1283+
size_t sz_min, size_t sz_max)
12661284
{
1285+
size_t sz, count;
12671286
const __be16 *val = of_find_property_value_of_size(np, propname,
1268-
(sz * sizeof(*out_values)),
1269-
0,
1270-
NULL);
1287+
(sz_min * sizeof(*out_values)),
1288+
(sz_max * sizeof(*out_values)),
1289+
&sz);
12711290

12721291
if (IS_ERR(val))
12731292
return PTR_ERR(val);
12741293

1275-
while (sz--)
1294+
if (!sz_max)
1295+
sz = sz_min;
1296+
else
1297+
sz /= sizeof(*out_values);
1298+
1299+
count = sz;
1300+
while (count--)
12761301
*out_values++ = be16_to_cpup(val++);
1277-
return 0;
1302+
1303+
return sz;
12781304
}
1279-
EXPORT_SYMBOL_GPL(of_property_read_u16_array);
1305+
EXPORT_SYMBOL_GPL(of_property_read_variable_u16_array);
12801306

12811307
/**
1282-
* of_property_read_u32_array - Find and read an array of 32 bit integers
1283-
* from a property.
1308+
* of_property_read_variable_u32_array - Find and read an array of 32 bit
1309+
* integers from a property, with bounds on the minimum and maximum array size.
12841310
*
12851311
* @np: device node from which the property value is to be read.
12861312
* @propname: name of the property to be searched.
12871313
* @out_values: pointer to return value, modified only if return value is 0.
1288-
* @sz: number of array elements to read
1314+
* @sz_min: minimum number of array elements to read
1315+
* @sz_max: maximum number of array elements to read, if zero there is no
1316+
* upper limit on the number of elements in the dts entry but only
1317+
* sz_min will be read.
12891318
*
12901319
* Search for a property in a device node and read 32-bit value(s) from
1291-
* it. Returns 0 on success, -EINVAL if the property does not exist,
1292-
* -ENODATA if property does not have a value, and -EOVERFLOW if the
1293-
* property data isn't large enough.
1320+
* it. Returns number of elements read on success, -EINVAL if the property
1321+
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
1322+
* if the property data is smaller than sz_min or longer than sz_max.
12941323
*
12951324
* The out_values is modified only if a valid u32 value can be decoded.
12961325
*/
1297-
int of_property_read_u32_array(const struct device_node *np,
1326+
int of_property_read_variable_u32_array(const struct device_node *np,
12981327
const char *propname, u32 *out_values,
1299-
size_t sz)
1328+
size_t sz_min, size_t sz_max)
13001329
{
1330+
size_t sz, count;
13011331
const __be32 *val = of_find_property_value_of_size(np, propname,
1302-
(sz * sizeof(*out_values)),
1303-
0,
1304-
NULL);
1332+
(sz_min * sizeof(*out_values)),
1333+
(sz_max * sizeof(*out_values)),
1334+
&sz);
13051335

13061336
if (IS_ERR(val))
13071337
return PTR_ERR(val);
13081338

1309-
while (sz--)
1339+
if (!sz_max)
1340+
sz = sz_min;
1341+
else
1342+
sz /= sizeof(*out_values);
1343+
1344+
count = sz;
1345+
while (count--)
13101346
*out_values++ = be32_to_cpup(val++);
1311-
return 0;
1347+
1348+
return sz;
13121349
}
1313-
EXPORT_SYMBOL_GPL(of_property_read_u32_array);
1350+
EXPORT_SYMBOL_GPL(of_property_read_variable_u32_array);
13141351

13151352
/**
13161353
* of_property_read_u64 - Find and read a 64 bit integer from a property
@@ -1342,40 +1379,51 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
13421379
EXPORT_SYMBOL_GPL(of_property_read_u64);
13431380

13441381
/**
1345-
* of_property_read_u64_array - Find and read an array of 64 bit integers
1346-
* from a property.
1382+
* of_property_read_variable_u64_array - Find and read an array of 64 bit
1383+
* integers from a property, with bounds on the minimum and maximum array size.
13471384
*
13481385
* @np: device node from which the property value is to be read.
13491386
* @propname: name of the property to be searched.
13501387
* @out_values: pointer to return value, modified only if return value is 0.
1351-
* @sz: number of array elements to read
1388+
* @sz_min: minimum number of array elements to read
1389+
* @sz_max: maximum number of array elements to read, if zero there is no
1390+
* upper limit on the number of elements in the dts entry but only
1391+
* sz_min will be read.
13521392
*
13531393
* Search for a property in a device node and read 64-bit value(s) from
1354-
* it. Returns 0 on success, -EINVAL if the property does not exist,
1355-
* -ENODATA if property does not have a value, and -EOVERFLOW if the
1356-
* property data isn't large enough.
1394+
* it. Returns number of elements read on success, -EINVAL if the property
1395+
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
1396+
* if the property data is smaller than sz_min or longer than sz_max.
13571397
*
13581398
* The out_values is modified only if a valid u64 value can be decoded.
13591399
*/
1360-
int of_property_read_u64_array(const struct device_node *np,
1400+
int of_property_read_variable_u64_array(const struct device_node *np,
13611401
const char *propname, u64 *out_values,
1362-
size_t sz)
1402+
size_t sz_min, size_t sz_max)
13631403
{
1404+
size_t sz, count;
13641405
const __be32 *val = of_find_property_value_of_size(np, propname,
1365-
(sz * sizeof(*out_values)),
1366-
0,
1367-
NULL);
1406+
(sz_min * sizeof(*out_values)),
1407+
(sz_max * sizeof(*out_values)),
1408+
&sz);
13681409

13691410
if (IS_ERR(val))
13701411
return PTR_ERR(val);
13711412

1372-
while (sz--) {
1413+
if (!sz_max)
1414+
sz = sz_min;
1415+
else
1416+
sz /= sizeof(*out_values);
1417+
1418+
count = sz;
1419+
while (count--) {
13731420
*out_values++ = of_read_number(val, 2);
13741421
val += 2;
13751422
}
1376-
return 0;
1423+
1424+
return sz;
13771425
}
1378-
EXPORT_SYMBOL_GPL(of_property_read_u64_array);
1426+
EXPORT_SYMBOL_GPL(of_property_read_variable_u64_array);
13791427

13801428
/**
13811429
* of_property_read_string - Find and read a string from a property

0 commit comments

Comments
 (0)