From patchwork Tue Oct 16 11:44:45 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongbo Zhang X-Patchwork-Id: 12273 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id BF4A8214A95 for ; Tue, 16 Oct 2012 11:46:24 +0000 (UTC) Received: from mail-ia0-f180.google.com (mail-ia0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 49062A18FB5 for ; Tue, 16 Oct 2012 11:46:24 +0000 (UTC) Received: by mail-ia0-f180.google.com with SMTP id f6so4372658iag.11 for ; Tue, 16 Oct 2012 04:46:24 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=cpHs0uIbMq1+hi/jBtgcD5ZEXQcwxFdUmjkCZrpilAQ=; b=W89MFAYWkdtOLajUIl0fsqz8VI5hBDAZ/SZLqTu3kpLHOM+cM4eFpr0qo1bggKpVVx z4GlxHeXtjSzvzk48iIT9nY76KfP9uQY163YqoJ4ObhUkaPF7I3EKwpyh10Qwds7cYiP fp1i4gzwJbxtfDdGjK3zymBbFkrxSdwSRO+UWfue0vviDYNu7kWeYEL3p1BCAFIZtZwW LCrQ+IWNbU6LCDMMRjzU+y2xqZglGSU4LNzlcr9g9LEgN46BXukVoAtegoKsNXoKB1CP 57LcUldgt2wPUXe4Qt71XswFs2rgw+PG8nz3Qoo2G+BrwRrAQb1rHf67/D1IMg6jKgxz m08A== Received: by 10.50.152.137 with SMTP id uy9mr11482394igb.62.1350387984057; Tue, 16 Oct 2012 04:46:24 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp714052igt; Tue, 16 Oct 2012 04:46:23 -0700 (PDT) Received: by 10.68.217.67 with SMTP id ow3mr46368363pbc.26.1350387983236; Tue, 16 Oct 2012 04:46:23 -0700 (PDT) Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50]) by mx.google.com with ESMTPS id n5si25974491paw.321.2012.10.16.04.46.23 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 16 Oct 2012 04:46:23 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of hongbo.zhang@linaro.org) client-ip=209.85.160.50; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of hongbo.zhang@linaro.org) smtp.mail=hongbo.zhang@linaro.org Received: by mail-pb0-f50.google.com with SMTP id md4so6559100pbc.37 for ; Tue, 16 Oct 2012 04:46:23 -0700 (PDT) Received: by 10.68.189.138 with SMTP id gi10mr45577165pbc.165.1350387982842; Tue, 16 Oct 2012 04:46:22 -0700 (PDT) Received: from stebjsxu0148.bjs.st.com ([124.127.135.94]) by mx.google.com with ESMTPS id pv9sm10667709pbb.67.2012.10.16.04.46.16 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 16 Oct 2012 04:46:22 -0700 (PDT) From: "hongbo.zhang" To: linaro-dev@lists.linaro.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org Cc: patches@linaro.org, linaro-kernel@lists.linaro.org, STEricsson_nomadik_linux@list.st.com, kernel@igloocommunity.org, "hongbo.zhang" Subject: [PATCH 1/5] Thermal: do bind operation after thermal zone or cooling device register returns. Date: Tue, 16 Oct 2012 19:44:45 +0800 Message-Id: <1350387889-15324-2-git-send-email-hongbo.zhang@linaro.com> X-Mailer: git-send-email 1.7.11.3 In-Reply-To: <1350387889-15324-1-git-send-email-hongbo.zhang@linaro.com> References: <1350387889-15324-1-git-send-email-hongbo.zhang@linaro.com> X-Gm-Message-State: ALoCoQn4qL2olIgpSLaW1EG6tMB2jBxQPS1FCG3sJKkvcBAhS7CWC4VT8C1z9KM/JzE2q58aETfG From: "hongbo.zhang" In the previous bind function, cdev->get_max_state(cdev, &max_state) is called before the registration function finishes, but at this moment, the parameter cdev at thermal driver layer isn't ready--it will get ready only after its registration, so the the get_max_state callback cannot tell the max_state according to the cdev input. This problem can be fixed by separating the bind operation out of registration and doing it when registration completely finished. Signed-off-by: hongbo.zhang --- drivers/thermal/thermal_sys.c | 86 +++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 9ee42ca..dd3d024 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -70,6 +70,8 @@ static LIST_HEAD(thermal_tz_list); static LIST_HEAD(thermal_cdev_list); static DEFINE_MUTEX(thermal_list_lock); +static struct work_struct thermal_bind; + static int get_idr(struct idr *idr, struct mutex *lock, int *id) { int err; @@ -777,7 +779,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, dev->lower = lower; dev->target = THERMAL_NO_TARGET; - result = get_idr(&tz->idr, &tz->lock, &dev->id); + result = get_idr(&tz->idr, NULL, &dev->id); if (result) goto free_mem; @@ -796,7 +798,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, if (result) goto remove_symbol_link; - mutex_lock(&tz->lock); + /* tz->lock should have been locked outside this function */ mutex_lock(&cdev->lock); list_for_each_entry(pos, &tz->thermal_instances, tz_node) if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { @@ -808,7 +810,6 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, list_add_tail(&dev->cdev_node, &cdev->thermal_instances); } mutex_unlock(&cdev->lock); - mutex_unlock(&tz->lock); if (!result) return 0; @@ -895,7 +896,6 @@ thermal_cooling_device_register(char *type, void *devdata, const struct thermal_cooling_device_ops *ops) { struct thermal_cooling_device *cdev; - struct thermal_zone_device *pos; int result; if (type && strlen(type) >= THERMAL_NAME_LENGTH) @@ -947,16 +947,10 @@ thermal_cooling_device_register(char *type, void *devdata, mutex_lock(&thermal_list_lock); list_add(&cdev->node, &thermal_cdev_list); - list_for_each_entry(pos, &thermal_tz_list, node) { - if (!pos->ops->bind) - continue; - result = pos->ops->bind(pos, cdev); - if (result) - break; - - } mutex_unlock(&thermal_list_lock); + schedule_work(&thermal_bind); + if (!result) return cdev; @@ -1141,19 +1135,13 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, return; } -/** - * thermal_zone_device_update - force an update of a thermal zone's state - * @ttz: the thermal zone to update - */ -void thermal_zone_device_update(struct thermal_zone_device *tz) +void __thermal_zone_device_update(struct thermal_zone_device *tz) { int count, ret = 0; long temp, trip_temp; enum thermal_trip_type trip_type; - mutex_lock(&tz->lock); - if (tz->ops->get_temp(tz, &temp)) { /* get_temp failed - retry it later */ pr_warn("failed to read out thermal zone %d\n", tz->id); @@ -1206,10 +1194,56 @@ leave: thermal_zone_device_set_polling(tz, tz->polling_delay); else thermal_zone_device_set_polling(tz, 0); +} + +/** + * thermal_zone_device_update - force an update of a thermal zone's state + * @tz: the thermal zone to update + */ +void thermal_zone_device_update(struct thermal_zone_device *tz) +{ + mutex_lock(&tz->lock); + + __thermal_zone_device_update(tz); + mutex_unlock(&tz->lock); } EXPORT_SYMBOL(thermal_zone_device_update); +static void thermal_zone_do_bind_work(struct work_struct *work) +{ + struct thermal_instance *instance; + struct thermal_zone_device *tz; + struct thermal_cooling_device *cdev; + + mutex_lock(&thermal_list_lock); + + list_for_each_entry(tz, &thermal_tz_list, node) + list_for_each_entry(cdev, &thermal_cdev_list, node) { + + mutex_lock(&tz->lock); + + if (list_empty(&tz->thermal_instances) + && tz->ops->bind) { + tz->ops->bind(tz, cdev); + __thermal_zone_device_update(tz); + mutex_unlock(&tz->lock); + break; + } + + list_for_each_entry(instance, &tz->thermal_instances, + tz_node) + if (instance->cdev != cdev && tz->ops->bind) { + tz->ops->bind(tz, cdev); + __thermal_zone_device_update(tz); + } + + mutex_unlock(&tz->lock); + } + + mutex_unlock(&thermal_list_lock); +} + /** * create_trip_attrs - create attributes for trip points * @tz: the thermal zone device @@ -1335,7 +1369,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, int passive_delay, int polling_delay) { struct thermal_zone_device *tz; - struct thermal_cooling_device *pos; enum thermal_trip_type trip_type; int result; int count; @@ -1419,17 +1452,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, mutex_lock(&thermal_list_lock); list_add_tail(&tz->node, &thermal_tz_list); - if (ops->bind) - list_for_each_entry(pos, &thermal_cdev_list, node) { - result = ops->bind(tz, pos); - if (result) - break; - } mutex_unlock(&thermal_list_lock); - INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); + if (ops->bind) + schedule_work(&thermal_bind); - thermal_zone_device_update(tz); + INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); if (!result) return tz; @@ -1588,6 +1616,7 @@ static int __init thermal_init(void) { int result = 0; + INIT_WORK(&thermal_bind, thermal_zone_do_bind_work); result = class_register(&thermal_class); if (result) { idr_destroy(&thermal_tz_idr); @@ -1601,6 +1630,7 @@ static int __init thermal_init(void) static void __exit thermal_exit(void) { + cancel_work_sync(&thermal_bind); class_unregister(&thermal_class); idr_destroy(&thermal_tz_idr); idr_destroy(&thermal_cdev_idr);