From patchwork Tue Mar 19 18:07:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Guinot X-Patchwork-Id: 2303691 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 0E3C23FD8C for ; Tue, 19 Mar 2013 18:09:34 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UI0wB-0005Nu-UE; Tue, 19 Mar 2013 18:07:04 +0000 Received: from vm1.sequanux.org ([188.165.36.56]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UI0vj-0005Fy-KP for linux-arm-kernel@lists.infradead.org; Tue, 19 Mar 2013 18:06:36 +0000 Received: from localhost (unknown [37.161.170.107]) by vm1.sequanux.org (Postfix) with ESMTPSA id B3F1A1081C9; Tue, 19 Mar 2013 19:06:34 +0100 (CET) From: Simon Guinot To: Bryan Wu , Richard Purdie , Jason Cooper , Andrew Lunn Subject: [PATCH 1/4] leds: leds-ns2: fix oops at module removal Date: Tue, 19 Mar 2013 19:07:29 +0100 Message-Id: <1363716452-18870-2-git-send-email-simon.guinot@sequanux.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1363716452-18870-1-git-send-email-simon.guinot@sequanux.org> References: <1363716452-18870-1-git-send-email-simon.guinot@sequanux.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130319_140635_751389_D186F23B X-CRM114-Status: GOOD ( 14.30 ) X-Spam-Score: -4.4 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.5 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This patch fixes a regression introduced by commit 72052fcc10 ("leds: leds-ns2: add device tree binding"). When the driver is initialized with device tree data, platform_data pointer is NULL. This causes a kernel oops at removal. To fix this bug, num_leds is moved into driver_data and platform_data is not longer used from ns2_led_remove(). Signed-off-by: Simon Guinot --- drivers/leds/leds-ns2.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index d978171..81af8e9 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -306,10 +306,21 @@ static const struct of_device_id of_ns2_leds_match[] = { }; #endif /* CONFIG_OF_GPIO */ +struct ns2_led_priv { + int num_leds; + struct ns2_led_data leds_data[]; +}; + +static inline int sizeof_ns2_led_priv(int num_leds) +{ + return sizeof(struct ns2_led_priv) + + (sizeof(struct ns2_led_data) * num_leds); +} + static int ns2_led_probe(struct platform_device *pdev) { struct ns2_led_platform_data *pdata = pdev->dev.platform_data; - struct ns2_led_data *leds_data; + struct ns2_led_priv *priv; int i; int ret; @@ -330,21 +341,23 @@ static int ns2_led_probe(struct platform_device *pdev) return -EINVAL; #endif /* CONFIG_OF_GPIO */ - leds_data = devm_kzalloc(&pdev->dev, sizeof(struct ns2_led_data) * - pdata->num_leds, GFP_KERNEL); - if (!leds_data) + priv = devm_kzalloc(&pdev->dev, + sizeof_ns2_led_priv(pdata->num_leds), GFP_KERNEL); + if (!priv) return -ENOMEM; + priv->num_leds = pdata->num_leds; - for (i = 0; i < pdata->num_leds; i++) { - ret = create_ns2_led(pdev, &leds_data[i], &pdata->leds[i]); + for (i = 0; i < priv->num_leds; i++) { + ret = create_ns2_led(pdev, &priv->leds_data[i], + &pdata->leds[i]); if (ret < 0) { for (i = i - 1; i >= 0; i--) - delete_ns2_led(&leds_data[i]); + delete_ns2_led(&priv->leds_data[i]); return ret; } } - platform_set_drvdata(pdev, leds_data); + platform_set_drvdata(pdev, priv); return 0; } @@ -352,13 +365,12 @@ static int ns2_led_probe(struct platform_device *pdev) static int ns2_led_remove(struct platform_device *pdev) { int i; - struct ns2_led_platform_data *pdata = pdev->dev.platform_data; - struct ns2_led_data *leds_data; + struct ns2_led_priv *priv; - leds_data = platform_get_drvdata(pdev); + priv = platform_get_drvdata(pdev); - for (i = 0; i < pdata->num_leds; i++) - delete_ns2_led(&leds_data[i]); + for (i = 0; i < priv->num_leds; i++) + delete_ns2_led(&priv->leds_data[i]); platform_set_drvdata(pdev, NULL);