--- drivers/base/power/qos.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) Index: linux-pm/drivers/base/power/qos.c =================================================================== --- linux-pm.orig/drivers/base/power/qos.c +++ linux-pm/drivers/base/power/qos.c @@ -186,26 +186,21 @@ static int apply_constraint(struct dev_p /* * dev_pm_qos_constraints_allocate - * @dev: device to allocate data for * * Called at the first call to add_request, for constraint data allocation * Must be called with the dev_pm_qos_mtx mutex held */ -static int dev_pm_qos_constraints_allocate(struct device *dev) +static struct dev_pm_qos *dev_pm_qos_constraints_allocate(void) { struct dev_pm_qos *qos; struct pm_qos_constraints *c; struct blocking_notifier_head *n; - qos = kzalloc(sizeof(*qos), GFP_KERNEL); + qos = kzalloc(sizeof(*qos) + kzalloc(3 * sizeof(*n), GFP_KERNEL); if (!qos) - return -ENOMEM; + return NULL; - n = kzalloc(3 * sizeof(*n), GFP_KERNEL); - if (!n) { - kfree(qos); - return -ENOMEM; - } + n = (struct blocking_notifier_head *)(qos + 1); c = &qos->resume_latency; plist_head_init(&c->list); @@ -227,6 +222,20 @@ static int dev_pm_qos_constraints_alloca INIT_LIST_HEAD(&qos->flags.list); + return qos; +} + +static int dev_pm_qos_constraints_add(struct device *dev, + struct dev_pm_qos *qos) +{ + if (!qos) + return -ENOMEM; + + if (!IS_ERR_OR_NULL(dev->power.qos)) { + kfree(qos); + return -ENODEV; + } + spin_lock_irq(&dev->power.lock); dev->power.qos = qos; spin_unlock_irq(&dev->power.lock); @@ -326,6 +335,7 @@ static bool dev_pm_qos_invalid_req_type( } static int __dev_pm_qos_add_request(struct device *dev, + struct dev_pm_qos *qos, struct dev_pm_qos_request *req, enum dev_pm_qos_req_type type, s32 value) { @@ -340,8 +350,10 @@ static int __dev_pm_qos_add_request(stru if (IS_ERR(dev->power.qos)) ret = -ENODEV; - else if (!dev->power.qos) - ret = dev_pm_qos_constraints_allocate(dev); + else if (dev->power.qos) + kfree(qos); + else + ret = dev_pm_qos_constraints_add(dev); trace_dev_pm_qos_add_request(dev_name(dev), type, value); if (ret) @@ -388,10 +400,11 @@ static int __dev_pm_qos_add_request(stru int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, enum dev_pm_qos_req_type type, s32 value) { + struct dev_pm_qos *qos = dev_pm_qos_constraints_allocate(); int ret; mutex_lock(&dev_pm_qos_mtx); - ret = __dev_pm_qos_add_request(dev, req, type, value); + ret = __dev_pm_qos_add_request(dev, qos, req, type, value); mutex_unlock(&dev_pm_qos_mtx); return ret; }