From patchwork Thu Feb 2 14:53:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 9552101 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D4D49604A7 for ; Thu, 2 Feb 2017 14:53:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C708227DF9 for ; Thu, 2 Feb 2017 14:53:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B9A5928477; Thu, 2 Feb 2017 14:53:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.4 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2D37C27DF9 for ; Thu, 2 Feb 2017 14:53:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751849AbdBBOxv (ORCPT ); Thu, 2 Feb 2017 09:53:51 -0500 Received: from mout.kundenserver.de ([212.227.126.187]:63477 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751500AbdBBOxu (ORCPT ); Thu, 2 Feb 2017 09:53:50 -0500 Received: from wuerfel.lan ([78.42.17.5]) by mrelayeu.kundenserver.de (mreue001 [212.227.15.129]) with ESMTPA (Nemesis) id 0M323z-1cI2Qg1wON-00stqd; Thu, 02 Feb 2017 15:53:29 +0100 From: Arnd Bergmann To: Mauro Carvalho Chehab Cc: Arnd Bergmann , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/4] [media] em28xx: reduce stack usage in probe functions Date: Thu, 2 Feb 2017 15:53:05 +0100 Message-Id: <20170202145318.3803805-2-arnd@arndb.de> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20170202145318.3803805-1-arnd@arndb.de> References: <20170202145318.3803805-1-arnd@arndb.de> X-Provags-ID: V03:K0:l1BFNTJ65Z6C3tVhrmDnExQ7TVsA52g+GuOpHK8+DRaQOdkcy+Q C30l+4IiFgNEEu0DXwsYR8m4T9//287XRVyGHj39Y0h6FT213+2ickAZbJR5SB4DcVn/L1f CovnsPiLhCIoWuRuoEpZHIZiC0VRiO05x8bB4k1Yyr9O4cGs20AyVYGNQAk3NJughEvkqlM Aqkl8EAHZktozODoa4Uyg== X-UI-Out-Filterresults: notjunk:1; V01:K0:r4C5c0kC4yY=:s8CPw192dcGvm+fr65/vNS 5WdT15HpCcTGf7DvU0YGYNbC6Q6Vs9JBUVStVcHEJU+R0wzmboSxzdP8ZswbG5cWhYCA85dwk 7qWQWbYuR2h0Fjkux0BybLAUYEJ5OsNd7lEWSzpdy5mTIkYBxG1BCw7PpSolhNa3w8tfPaA/J jPEchKhSKMgdHHpXZJYDE5+HjG7bKEt1TjpNo8RgCes3lHkP8ei25/PUT2G6QnL/hTJO8tWne qbe11yeltpdGHljthjO/McdwYn4qjo5NNRTuLZJNQT0padoub9/yE+TnzhBEYiVo4KouzQlXA +SupbbePzoyWULfztZvf1HC7pp3cr5JV5GpiuydicvcpMPsJMrxoUVM8OiDZUM1EZfKMHVJ4p vTzhFuVqH8Y5/qcnxROw+yuOZrufrEsQ6sdtvAiamQ3OpqnVM0RW3nI1JNFKut63IsCjS5jn1 R/bQ0ipijedGP5VmOZsK+V1Az3pO+xk46GAXdwyyssQmr7031dKzlL6PMxuQGqCLbRWKIP9ae Ya9RUi3hEQY//k3harCl7b5XghU9C9wVMw6ILTEbCfYWhD69fK0bQHqDeKNpTAts3i8k4Q5te /O5LqS/G9+I25R2hqZau/JmBVl7li1Fr5Rdggos5/uEOxyBnsJ9Fusq9Mieb4zw1gORG0cqIp 4rxTV2KI9EzTmrM34QAl/pwuDo0deXF+axKXuhmm6qDAe3IRMrrfLVLQY1eGK3gw9v3I= Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The two i2c probe functions use a lot of stack since they put an i2c_client structure in a local variable: drivers/media/usb/em28xx/em28xx-camera.c: In function 'em28xx_probe_sensor_micron': drivers/media/usb/em28xx/em28xx-camera.c:205:1: error: the frame size of 1256 bytes is larger than 1152 bytes [-Werror=frame-larger-than=] drivers/media/usb/em28xx/em28xx-camera.c: In function 'em28xx_probe_sensor_omnivision': drivers/media/usb/em28xx/em28xx-camera.c:317:1: error: the frame size of 1248 bytes is larger than 1152 bytes [-Werror=frame-larger-than=] This cleans up both of the above by removing the need for those structures, calling the lower-level i2c function directly. Signed-off-by: Arnd Bergmann --- drivers/media/usb/em28xx/em28xx-camera.c | 87 ++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 89c890ba7dd6..e64940f95a91 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -99,6 +99,25 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev) return 0; } +/* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ +static int em28xx_i2c_read_chip_id(struct em28xx *dev, u16 addr, u8 reg, void *buf) +{ + struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; + struct i2c_msg msg[2]; + + msg[0].addr = addr; + msg[0].flags = client->flags & I2C_M_TEN; + msg[0].len = 1; + msg[0].buf = ® + msg[1].addr = addr; + msg[1].flags = client->flags & I2C_M_TEN; + msg[1].flags |= I2C_M_RD; + msg[1].len = 2; + msg[1].buf = buf; + + return i2c_transfer(client->adapter, msg, 2); +} + /* * Probes Micron sensors with 8 bit address and 16 bit register width */ @@ -106,48 +125,29 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) { int ret, i; char *name; - u8 reg; __be16 id_be; + u16 addr; u16 id; - struct i2c_client client = dev->i2c_client[dev->def_i2c_bus]; - dev->em28xx_sensor = EM28XX_NOSENSOR; for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { - client.addr = micron_sensor_addrs[i]; - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ + addr = micron_sensor_addrs[i]; /* Read chip ID from register 0x00 */ - reg = 0x00; - ret = i2c_master_send(&client, ®, 1); + ret = em28xx_i2c_read_chip_id(dev, addr, 0x00, &id_be); if (ret < 0) { if (ret != -ENXIO) dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); - continue; - } - ret = i2c_master_recv(&client, (u8 *)&id_be, 2); - if (ret < 0) { - dev_err(&dev->intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + addr << 1, ret); continue; } id = be16_to_cpu(id_be); /* Read chip ID from register 0xff */ - reg = 0xff; - ret = i2c_master_send(&client, ®, 1); + ret = em28xx_i2c_read_chip_id(dev, addr, 0xff, &id_be); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); - continue; - } - ret = i2c_master_recv(&client, (u8 *)&id_be, 2); - if (ret < 0) { - dev_err(&dev->intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + addr << 1, ret); continue; } /* Validate chip ID to be sure we have a Micron device */ @@ -197,13 +197,26 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) dev_info(&dev->intf->dev, "sensor %s detected\n", name); - dev->i2c_client[dev->def_i2c_bus].addr = client.addr; + dev->i2c_client[dev->def_i2c_bus].addr = addr; return 0; } return -ENODEV; } +/* like i2c_smbus_read_byte_data, but allows passing an addr */ +static int em28xx_smbus_read_byte(struct em28xx *dev, u16 addr, u8 command) +{ + struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; + union i2c_smbus_data data; + int status; + + status = i2c_smbus_xfer(client->adapter, addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data); + return (status < 0) ? status : data.byte; +} + /* * Probes Omnivision sensors with 8 bit address and register width */ @@ -212,31 +225,31 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev) int ret, i; char *name; u8 reg; + u16 addr; u16 id; - struct i2c_client client = dev->i2c_client[dev->def_i2c_bus]; dev->em28xx_sensor = EM28XX_NOSENSOR; /* NOTE: these devices have the register auto incrementation disabled * by default, so we have to use single byte reads ! */ for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) { - client.addr = omnivision_sensor_addrs[i]; + addr = omnivision_sensor_addrs[i]; /* Read manufacturer ID from registers 0x1c-0x1d (BE) */ reg = 0x1c; - ret = i2c_smbus_read_byte_data(&client, reg); + ret = em28xx_smbus_read_byte(dev, addr, reg); if (ret < 0) { if (ret != -ENXIO) dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + addr << 1, ret); continue; } id = ret << 8; reg = 0x1d; - ret = i2c_smbus_read_byte_data(&client, reg); + ret = em28xx_smbus_read_byte(dev, addr, reg); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + addr << 1, ret); continue; } id += ret; @@ -245,20 +258,20 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev) continue; /* Read product ID from registers 0x0a-0x0b (BE) */ reg = 0x0a; - ret = i2c_smbus_read_byte_data(&client, reg); + ret = em28xx_smbus_read_byte(dev, addr, reg); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + addr << 1, ret); continue; } id = ret << 8; reg = 0x0b; - ret = i2c_smbus_read_byte_data(&client, reg); + ret = em28xx_smbus_read_byte(dev, addr, reg); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + addr << 1, ret); continue; } id += ret; @@ -309,7 +322,7 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev) dev_info(&dev->intf->dev, "sensor %s detected\n", name); - dev->i2c_client[dev->def_i2c_bus].addr = client.addr; + dev->i2c_client[dev->def_i2c_bus].addr = addr; return 0; }