Commit 3d788276 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'devprop-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull device properties framework fixes from Rafael Wysocki:
 "These fix an issue related to device removal introduced during the 4.9
  cycle and fix up new functionality added recently.

  Specifics:

   - Fix a device properties management issue, introduced during the 4.9
     cycle, that causes device properties associated with a parent
     device to go away on a removal of its child in some cases (Jarkko
     Nikula).

   - Fix inconsistencies in error codes returned by a new function
     helper in the device properties framework depending on the
     underlying low-level firmware interface, DT or ACPI, by making the
     meaning of error codes returned in the ACPI case agree with the
     meaning of DT error codes in analogous situations (Sakari Ailus)"

* tag 'devprop-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI: properties: Fix __acpi_node_get_property_reference() return codes
  ACPI: properties: Align return codes of __acpi_node_get_property_reference()
  device property: Track owner device of device property
parents 8ff0b97c 51858a27
...@@ -571,10 +571,9 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data, ...@@ -571,10 +571,9 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data,
* } * }
* } * }
* *
* Calling this function with index %2 return %-ENOENT and with index %3 * Calling this function with index %2 or index %3 return %-ENOENT. If the
* returns the last entry. If the property does not contain any more values * property does not contain any more values %-ENOENT is returned. The NULL
* %-ENODATA is returned. The NULL entry must be single integer and * entry must be single integer and preferably contain value %0.
* preferably contain value %0.
* *
* Return: %0 on success, negative error code on failure. * Return: %0 on success, negative error code on failure.
*/ */
...@@ -590,11 +589,11 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ...@@ -590,11 +589,11 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
data = acpi_device_data_of_node(fwnode); data = acpi_device_data_of_node(fwnode);
if (!data) if (!data)
return -EINVAL; return -ENOENT;
ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj); ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
if (ret) if (ret)
return ret; return ret == -EINVAL ? -ENOENT : -EINVAL;
/* /*
* The simplest case is when the value is a single reference. Just * The simplest case is when the value is a single reference. Just
...@@ -606,7 +605,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ...@@ -606,7 +605,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
ret = acpi_bus_get_device(obj->reference.handle, &device); ret = acpi_bus_get_device(obj->reference.handle, &device);
if (ret) if (ret)
return ret; return ret == -ENODEV ? -EINVAL : ret;
args->adev = device; args->adev = device;
args->nargs = 0; args->nargs = 0;
...@@ -622,8 +621,10 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ...@@ -622,8 +621,10 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
* The index argument is then used to determine which reference * The index argument is then used to determine which reference
* the caller wants (along with the arguments). * the caller wants (along with the arguments).
*/ */
if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count) if (obj->type != ACPI_TYPE_PACKAGE)
return -EPROTO; return -EINVAL;
if (index >= obj->package.count)
return -ENOENT;
element = obj->package.elements; element = obj->package.elements;
end = element + obj->package.count; end = element + obj->package.count;
...@@ -635,7 +636,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ...@@ -635,7 +636,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
ret = acpi_bus_get_device(element->reference.handle, ret = acpi_bus_get_device(element->reference.handle,
&device); &device);
if (ret) if (ret)
return -ENODEV; return -EINVAL;
nargs = 0; nargs = 0;
element++; element++;
...@@ -649,11 +650,11 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ...@@ -649,11 +650,11 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
else if (type == ACPI_TYPE_LOCAL_REFERENCE) else if (type == ACPI_TYPE_LOCAL_REFERENCE)
break; break;
else else
return -EPROTO; return -EINVAL;
} }
if (nargs > MAX_ACPI_REFERENCE_ARGS) if (nargs > MAX_ACPI_REFERENCE_ARGS)
return -EPROTO; return -EINVAL;
if (idx == index) { if (idx == index) {
args->adev = device; args->adev = device;
...@@ -670,13 +671,13 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ...@@ -670,13 +671,13 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
return -ENOENT; return -ENOENT;
element++; element++;
} else { } else {
return -EPROTO; return -EINVAL;
} }
idx++; idx++;
} }
return -ENODATA; return -ENOENT;
} }
EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference); EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/phy.h> #include <linux/phy.h>
struct property_set { struct property_set {
struct device *dev;
struct fwnode_handle fwnode; struct fwnode_handle fwnode;
const struct property_entry *properties; const struct property_entry *properties;
}; };
...@@ -682,6 +683,10 @@ EXPORT_SYMBOL_GPL(fwnode_property_match_string); ...@@ -682,6 +683,10 @@ EXPORT_SYMBOL_GPL(fwnode_property_match_string);
* Caller is responsible to call fwnode_handle_put() on the returned * Caller is responsible to call fwnode_handle_put() on the returned
* args->fwnode pointer. * args->fwnode pointer.
* *
* Returns: %0 on success
* %-ENOENT when the index is out of bounds, the index has an empty
* reference or the property was not found
* %-EINVAL on parse error
*/ */
int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode, int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
const char *prop, const char *nargs_prop, const char *prop, const char *nargs_prop,
...@@ -891,6 +896,7 @@ static struct property_set *pset_copy_set(const struct property_set *pset) ...@@ -891,6 +896,7 @@ static struct property_set *pset_copy_set(const struct property_set *pset)
void device_remove_properties(struct device *dev) void device_remove_properties(struct device *dev)
{ {
struct fwnode_handle *fwnode; struct fwnode_handle *fwnode;
struct property_set *pset;
fwnode = dev_fwnode(dev); fwnode = dev_fwnode(dev);
if (!fwnode) if (!fwnode)
...@@ -900,16 +906,16 @@ void device_remove_properties(struct device *dev) ...@@ -900,16 +906,16 @@ void device_remove_properties(struct device *dev)
* the pset. If there is no real firmware node (ACPI/DT) primary * the pset. If there is no real firmware node (ACPI/DT) primary
* will hold the pset. * will hold the pset.
*/ */
if (is_pset_node(fwnode)) { pset = to_pset_node(fwnode);
if (pset) {
set_primary_fwnode(dev, NULL); set_primary_fwnode(dev, NULL);
pset_free_set(to_pset_node(fwnode));
} else { } else {
fwnode = fwnode->secondary; pset = to_pset_node(fwnode->secondary);
if (!IS_ERR(fwnode) && is_pset_node(fwnode)) { if (pset && dev == pset->dev)
set_secondary_fwnode(dev, NULL); set_secondary_fwnode(dev, NULL);
pset_free_set(to_pset_node(fwnode));
}
} }
if (pset && dev == pset->dev)
pset_free_set(pset);
} }
EXPORT_SYMBOL_GPL(device_remove_properties); EXPORT_SYMBOL_GPL(device_remove_properties);
...@@ -938,6 +944,7 @@ int device_add_properties(struct device *dev, ...@@ -938,6 +944,7 @@ int device_add_properties(struct device *dev,
p->fwnode.ops = &pset_fwnode_ops; p->fwnode.ops = &pset_fwnode_ops;
set_secondary_fwnode(dev, &p->fwnode); set_secondary_fwnode(dev, &p->fwnode);
p->dev = dev;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(device_add_properties); EXPORT_SYMBOL_GPL(device_add_properties);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment