Skip to content

Commit

Permalink
Merge tag 'driver-core-4.14-rc1' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/gregkh/driver-core

Pull driver core update from Greg KH:
 "Here is the "big" driver core update for 4.14-rc1.

  It's really not all that big, the largest thing here being some
  firmware tests to help ensure that that crazy api is working properly.

  There's also a new uevent for when a driver is bound or unbound from a
  device, fixing a hole in the driver model that's been there since the
  very beginning. Many thanks to Dmitry for being persistent and
  pointing out how wrong I was about this all along :)

  Patches for the new uevents are already in the systemd tree, if people
  want to play around with them.

  Otherwise just a number of other small api changes and updates here,
  nothing major. All of these patches have been in linux-next for a
  while with no reported issues"

* tag 'driver-core-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (28 commits)
  driver core: bus: Fix a potential double free
  Do not disable driver and bus shutdown hook when class shutdown hook is set.
  base: topology: constify attribute_group structures.
  base: Convert to using %pOF instead of full_name
  kernfs: Clarify lockdep name for kn->count
  fbdev: uvesafb: remove DRIVER_ATTR() usage
  xen: xen-pciback: remove DRIVER_ATTR() usage
  driver core: Document struct device:dma_ops
  mod_devicetable: Remove excess description from structured comment
  test_firmware: add batched firmware tests
  firmware: enable a debug print for batched requests
  firmware: define pr_fmt
  firmware: send -EINTR on signal abort on fallback mechanism
  test_firmware: add test case for SIGCHLD on sync fallback
  initcall_debug: add deferred probe times
  Input: axp20x-pek - switch to using devm_device_add_group()
  Input: synaptics_rmi4 - use devm_device_add_group() for attributes in F01
  Input: gpio_keys - use devm_device_add_group() for attributes
  driver core: add devm_device_add_group() and friends
  driver core: add device_{add|remove}_group() helpers
  ...
  • Loading branch information
torvalds committed Sep 5, 2017
2 parents bf1d6b2 + 0f9b011 commit 44b1671
Show file tree
Hide file tree
Showing 23 changed files with 1,291 additions and 142 deletions.
86 changes: 43 additions & 43 deletions drivers/base/arch_topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ static ssize_t cpu_capacity_show(struct device *dev,
{
struct cpu *cpu = container_of(dev, struct cpu, dev);

return sprintf(buf, "%lu\n",
topology_get_cpu_scale(NULL, cpu->dev.id));
return sprintf(buf, "%lu\n", topology_get_cpu_scale(NULL, cpu->dev.id));
}

static ssize_t cpu_capacity_store(struct device *dev,
Expand Down Expand Up @@ -96,14 +95,21 @@ subsys_initcall(register_cpu_capacity_sysctl);

static u32 capacity_scale;
static u32 *raw_capacity;
static bool cap_parsing_failed;

static int __init free_raw_capacity(void)
{
kfree(raw_capacity);
raw_capacity = NULL;

return 0;
}

void topology_normalize_cpu_scale(void)
{
u64 capacity;
int cpu;

if (!raw_capacity || cap_parsing_failed)
if (!raw_capacity)
return;

pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale);
Expand All @@ -120,16 +126,16 @@ void topology_normalize_cpu_scale(void)
mutex_unlock(&cpu_scale_mutex);
}

int __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
{
int ret = 1;
static bool cap_parsing_failed;
int ret;
u32 cpu_capacity;

if (cap_parsing_failed)
return !ret;
return false;

ret = of_property_read_u32(cpu_node,
"capacity-dmips-mhz",
ret = of_property_read_u32(cpu_node, "capacity-dmips-mhz",
&cpu_capacity);
if (!ret) {
if (!raw_capacity) {
Expand All @@ -139,29 +145,28 @@ int __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
if (!raw_capacity) {
pr_err("cpu_capacity: failed to allocate memory for raw capacities\n");
cap_parsing_failed = true;
return 0;
return false;
}
}
capacity_scale = max(cpu_capacity, capacity_scale);
raw_capacity[cpu] = cpu_capacity;
pr_debug("cpu_capacity: %s cpu_capacity=%u (raw)\n",
cpu_node->full_name, raw_capacity[cpu]);
pr_debug("cpu_capacity: %pOF cpu_capacity=%u (raw)\n",
cpu_node, raw_capacity[cpu]);
} else {
if (raw_capacity) {
pr_err("cpu_capacity: missing %s raw capacity\n",
cpu_node->full_name);
pr_err("cpu_capacity: missing %pOF raw capacity\n",
cpu_node);
pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n");
}
cap_parsing_failed = true;
kfree(raw_capacity);
free_raw_capacity();
}

return !ret;
}

#ifdef CONFIG_CPU_FREQ
static cpumask_var_t cpus_to_visit;
static bool cap_parsing_done;
static void parsing_done_workfn(struct work_struct *work);
static DECLARE_WORK(parsing_done_work, parsing_done_workfn);

Expand All @@ -173,30 +178,31 @@ init_cpu_capacity_callback(struct notifier_block *nb,
struct cpufreq_policy *policy = data;
int cpu;

if (cap_parsing_failed || cap_parsing_done)
if (!raw_capacity)
return 0;

switch (val) {
case CPUFREQ_NOTIFY:
pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n",
cpumask_pr_args(policy->related_cpus),
cpumask_pr_args(cpus_to_visit));
cpumask_andnot(cpus_to_visit,
cpus_to_visit,
policy->related_cpus);
for_each_cpu(cpu, policy->related_cpus) {
raw_capacity[cpu] = topology_get_cpu_scale(NULL, cpu) *
policy->cpuinfo.max_freq / 1000UL;
capacity_scale = max(raw_capacity[cpu], capacity_scale);
}
if (cpumask_empty(cpus_to_visit)) {
topology_normalize_cpu_scale();
kfree(raw_capacity);
pr_debug("cpu_capacity: parsing done\n");
cap_parsing_done = true;
schedule_work(&parsing_done_work);
}
if (val != CPUFREQ_NOTIFY)
return 0;

pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n",
cpumask_pr_args(policy->related_cpus),
cpumask_pr_args(cpus_to_visit));

cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus);

for_each_cpu(cpu, policy->related_cpus) {
raw_capacity[cpu] = topology_get_cpu_scale(NULL, cpu) *
policy->cpuinfo.max_freq / 1000UL;
capacity_scale = max(raw_capacity[cpu], capacity_scale);
}

if (cpumask_empty(cpus_to_visit)) {
topology_normalize_cpu_scale();
free_raw_capacity();
pr_debug("cpu_capacity: parsing done\n");
schedule_work(&parsing_done_work);
}

return 0;
}

Expand Down Expand Up @@ -233,11 +239,5 @@ static void parsing_done_workfn(struct work_struct *work)
}

#else
static int __init free_raw_capacity(void)
{
kfree(raw_capacity);

return 0;
}
core_initcall(free_raw_capacity);
#endif
5 changes: 0 additions & 5 deletions drivers/base/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,6 @@ extern int driver_add_groups(struct device_driver *drv,
extern void driver_remove_groups(struct device_driver *drv,
const struct attribute_group **groups);

extern int device_add_groups(struct device *dev,
const struct attribute_group **groups);
extern void device_remove_groups(struct device *dev,
const struct attribute_group **groups);

extern char *make_class_name(const char *name, struct kobject *kobj);

extern int devres_release_all(struct device *dev);
Expand Down
2 changes: 1 addition & 1 deletion drivers/base/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ int bus_add_driver(struct device_driver *drv)

out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
/* drv->p is freed in driver_release() */
drv->p = NULL;
out_put_bus:
bus_put(bus);
Expand Down
141 changes: 137 additions & 4 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1023,12 +1023,144 @@ int device_add_groups(struct device *dev, const struct attribute_group **groups)
{
return sysfs_create_groups(&dev->kobj, groups);
}
EXPORT_SYMBOL_GPL(device_add_groups);

void device_remove_groups(struct device *dev,
const struct attribute_group **groups)
{
sysfs_remove_groups(&dev->kobj, groups);
}
EXPORT_SYMBOL_GPL(device_remove_groups);

union device_attr_group_devres {
const struct attribute_group *group;
const struct attribute_group **groups;
};

static int devm_attr_group_match(struct device *dev, void *res, void *data)
{
return ((union device_attr_group_devres *)res)->group == data;
}

static void devm_attr_group_remove(struct device *dev, void *res)
{
union device_attr_group_devres *devres = res;
const struct attribute_group *group = devres->group;

dev_dbg(dev, "%s: removing group %p\n", __func__, group);
sysfs_remove_group(&dev->kobj, group);
}

static void devm_attr_groups_remove(struct device *dev, void *res)
{
union device_attr_group_devres *devres = res;
const struct attribute_group **groups = devres->groups;

dev_dbg(dev, "%s: removing groups %p\n", __func__, groups);
sysfs_remove_groups(&dev->kobj, groups);
}

/**
* devm_device_add_group - given a device, create a managed attribute group
* @dev: The device to create the group for
* @grp: The attribute group to create
*
* This function creates a group for the first time. It will explicitly
* warn and error if any of the attribute files being created already exist.
*
* Returns 0 on success or error code on failure.
*/
int devm_device_add_group(struct device *dev, const struct attribute_group *grp)
{
union device_attr_group_devres *devres;
int error;

devres = devres_alloc(devm_attr_group_remove,
sizeof(*devres), GFP_KERNEL);
if (!devres)
return -ENOMEM;

error = sysfs_create_group(&dev->kobj, grp);
if (error) {
devres_free(devres);
return error;
}

devres->group = grp;
devres_add(dev, devres);
return 0;
}
EXPORT_SYMBOL_GPL(devm_device_add_group);

/**
* devm_device_remove_group: remove a managed group from a device
* @dev: device to remove the group from
* @grp: group to remove
*
* This function removes a group of attributes from a device. The attributes
* previously have to have been created for this group, otherwise it will fail.
*/
void devm_device_remove_group(struct device *dev,
const struct attribute_group *grp)
{
WARN_ON(devres_release(dev, devm_attr_group_remove,
devm_attr_group_match,
/* cast away const */ (void *)grp));
}
EXPORT_SYMBOL_GPL(devm_device_remove_group);

/**
* devm_device_add_groups - create a bunch of managed attribute groups
* @dev: The device to create the group for
* @groups: The attribute groups to create, NULL terminated
*
* This function creates a bunch of managed attribute groups. If an error
* occurs when creating a group, all previously created groups will be
* removed, unwinding everything back to the original state when this
* function was called. It will explicitly warn and error if any of the
* attribute files being created already exist.
*
* Returns 0 on success or error code from sysfs_create_group on failure.
*/
int devm_device_add_groups(struct device *dev,
const struct attribute_group **groups)
{
union device_attr_group_devres *devres;
int error;

devres = devres_alloc(devm_attr_groups_remove,
sizeof(*devres), GFP_KERNEL);
if (!devres)
return -ENOMEM;

error = sysfs_create_groups(&dev->kobj, groups);
if (error) {
devres_free(devres);
return error;
}

devres->groups = groups;
devres_add(dev, devres);
return 0;
}
EXPORT_SYMBOL_GPL(devm_device_add_groups);

/**
* devm_device_remove_groups - remove a list of managed groups
*
* @dev: The device for the groups to be removed from
* @groups: NULL terminated list of groups to be removed
*
* If groups is not NULL, remove the specified groups from the device.
*/
void devm_device_remove_groups(struct device *dev,
const struct attribute_group **groups)
{
WARN_ON(devres_release(dev, devm_attr_groups_remove,
devm_attr_group_match,
/* cast away const */ (void *)groups));
}
EXPORT_SYMBOL_GPL(devm_device_remove_groups);

static int device_add_attrs(struct device *dev)
{
Expand Down Expand Up @@ -2664,11 +2796,12 @@ void device_shutdown(void)
pm_runtime_get_noresume(dev);
pm_runtime_barrier(dev);

if (dev->class && dev->class->shutdown) {
if (dev->class && dev->class->shutdown_pre) {
if (initcall_debug)
dev_info(dev, "shutdown\n");
dev->class->shutdown(dev);
} else if (dev->bus && dev->bus->shutdown) {
dev_info(dev, "shutdown_pre\n");
dev->class->shutdown_pre(dev);
}
if (dev->bus && dev->bus->shutdown) {
if (initcall_debug)
dev_info(dev, "shutdown\n");
dev->bus->shutdown(dev);
Expand Down
Loading

0 comments on commit 44b1671

Please sign in to comment.