From: Dmitry Torokhov Date: Tue, 16 Jan 2024 21:52:33 +0000 (-0800) Subject: Input: iqs5xx - switch to using cleanup functions X-Git-Tag: v7.1-rc1~44^2^2~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=582f32aa89e66ab1e16aab157fdd483b5acc86fa;p=thirdparty%2Fkernel%2Flinux.git Input: iqs5xx - switch to using cleanup functions Start using __free() and guard() primitives to simplify the code and error handling. Signed-off-by: Dmitry Torokhov --- diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c index c63819abaf9b..c8cd3f3ca421 100644 --- a/drivers/input/touchscreen/iqs5xx.c +++ b/drivers/input/touchscreen/iqs5xx.c @@ -356,7 +356,7 @@ static int iqs5xx_bl_open(struct i2c_client *client) } static int iqs5xx_bl_write(struct i2c_client *client, - u16 bl_addr, u8 *pmap_data, u16 pmap_len) + u16 bl_addr, const u8 *pmap_data, u16 pmap_len) { struct i2c_msg msg; int ret, i; @@ -395,7 +395,7 @@ msg_fail: } static int iqs5xx_bl_verify(struct i2c_client *client, - u16 bl_addr, u8 *pmap_data, u16 pmap_len) + u16 bl_addr, const u8 *pmap_data, u16 pmap_len) { struct i2c_msg msg; int ret, i; @@ -446,27 +446,21 @@ static int iqs5xx_set_state(struct i2c_client *client, u8 state) if (!iqs5xx->dev_id_info.bl_status) return 0; - mutex_lock(&iqs5xx->lock); + guard(mutex)(&iqs5xx->lock); /* * Addressing the device outside of a communication window prompts it * to assert the RDY output, so disable the interrupt line to prevent * the handler from servicing a false interrupt. */ - disable_irq(client->irq); + guard(disable_irq)(&client->irq); error1 = iqs5xx_write_byte(client, IQS5XX_SYS_CTRL1, state); error2 = iqs5xx_write_byte(client, IQS5XX_END_COMM, 0); usleep_range(50, 100); - enable_irq(client->irq); - mutex_unlock(&iqs5xx->lock); - - if (error1) - return error1; - - return error2; + return error1 ?: error2; } static int iqs5xx_open(struct input_dev *input) @@ -703,7 +697,6 @@ static irqreturn_t iqs5xx_irq(int irq, void *data) static int iqs5xx_fw_file_parse(struct i2c_client *client, const char *fw_file, u8 *pmap) { - const struct firmware *fw; struct iqs5xx_ihex_rec *rec; size_t pos = 0; int error, i; @@ -722,6 +715,7 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client, * Because the ihex2fw tool tolerates neither (1) nor (2), the slightly * nonstandard ihex firmware is parsed directly by the driver. */ + const struct firmware *fw __free(firmware) = NULL; error = request_firmware(&fw, fw_file, &client->dev); if (error) { dev_err(&client->dev, "Failed to request firmware %s: %d\n", @@ -732,8 +726,7 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client, do { if (pos + sizeof(*rec) > fw->size) { dev_err(&client->dev, "Insufficient firmware size\n"); - error = -EINVAL; - break; + return -EINVAL; } rec = (struct iqs5xx_ihex_rec *)(fw->data + pos); pos += sizeof(*rec); @@ -741,15 +734,14 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client, if (rec->start != ':') { dev_err(&client->dev, "Invalid start at record %u\n", rec_num); - error = -EINVAL; - break; + return -EINVAL; } error = hex2bin(rec_hdr, rec->len, sizeof(rec_hdr)); if (error) { dev_err(&client->dev, "Invalid header at record %u\n", rec_num); - break; + return error; } rec_len = *rec_hdr; @@ -758,8 +750,7 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client, if (pos + rec_len * 2 > fw->size) { dev_err(&client->dev, "Insufficient firmware size\n"); - error = -EINVAL; - break; + return -EINVAL; } pos += (rec_len * 2); @@ -767,7 +758,7 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client, if (error) { dev_err(&client->dev, "Invalid data at record %u\n", rec_num); - break; + return error; } error = hex2bin(&rec_chksm, @@ -775,7 +766,7 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client, if (error) { dev_err(&client->dev, "Invalid checksum at record %u\n", rec_num); - break; + return error; } chksm = 0; @@ -800,23 +791,22 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client, dev_err(&client->dev, "Invalid address at record %u\n", rec_num); - error = -EINVAL; - } else { - memcpy(pmap + rec_addr - IQS5XX_CHKSM, - rec_data, rec_len); + return -EINVAL; } + + memcpy(pmap + rec_addr - IQS5XX_CHKSM, + rec_data, rec_len); break; + case IQS5XX_REC_TYPE_EOF: break; + default: dev_err(&client->dev, "Invalid type at record %u\n", rec_num); - error = -EINVAL; + return -EINVAL; } - if (error) - break; - rec_num++; while (pos < fw->size) { if (*(fw->data + pos) == ':') @@ -825,33 +815,13 @@ static int iqs5xx_fw_file_parse(struct i2c_client *client, } } while (rec_type != IQS5XX_REC_TYPE_EOF); - release_firmware(fw); - - return error; + return 0; } -static int iqs5xx_fw_file_write(struct i2c_client *client, const char *fw_file) +static int iqs5xx_update_firmware(struct iqs5xx_private *iqs5xx, const u8 *pmap) { - struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client); - int error, error_init = 0; - u8 *pmap; - - pmap = kzalloc(IQS5XX_PMAP_LEN, GFP_KERNEL); - if (!pmap) - return -ENOMEM; - - error = iqs5xx_fw_file_parse(client, fw_file, pmap); - if (error) - goto err_kfree; - - mutex_lock(&iqs5xx->lock); - - /* - * Disable the interrupt line in case the first attempt(s) to enter the - * bootloader don't happen quickly enough, in which case the device may - * assert the RDY output until the next attempt. - */ - disable_irq(client->irq); + struct i2c_client *client = iqs5xx->client; + int error; iqs5xx->dev_id_info.bl_status = 0; @@ -859,22 +829,50 @@ static int iqs5xx_fw_file_write(struct i2c_client *client, const char *fw_file) if (error) { error = iqs5xx_bl_open(client); if (error) - goto err_reset; + return error; } error = iqs5xx_bl_write(client, IQS5XX_CHKSM, pmap, IQS5XX_PMAP_LEN); if (error) - goto err_reset; + return error; error = iqs5xx_bl_cmd(client, IQS5XX_BL_CMD_CRC, 0); if (error) - goto err_reset; + return error; error = iqs5xx_bl_verify(client, IQS5XX_CSTM, pmap + IQS5XX_CHKSM_LEN + IQS5XX_APP_LEN, IQS5XX_CSTM_LEN); + if (error) + return error; + + return 0; +} + +static int iqs5xx_fw_file_write(struct i2c_client *client, const char *fw_file) +{ + struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client); + int error, error_init = 0; + + u8 *pmap __free(kfree) = kzalloc(IQS5XX_PMAP_LEN, GFP_KERNEL); + if (!pmap) + return -ENOMEM; + + error = iqs5xx_fw_file_parse(client, fw_file, pmap); + if (error) + return error; + + guard(mutex)(&iqs5xx->lock); + + /* + * Disable the interrupt line in case the first attempt(s) to enter the + * bootloader don't happen quickly enough, in which case the device may + * assert the RDY output until the next attempt. + */ + guard(disable_irq)(&client->irq); + + error = iqs5xx_update_firmware(iqs5xx, pmap); -err_reset: iqs5xx_reset(client); usleep_range(15000, 15100); @@ -882,14 +880,7 @@ err_reset: if (!iqs5xx->dev_id_info.bl_status) error_init = error_init ? : -EINVAL; - enable_irq(client->irq); - - mutex_unlock(&iqs5xx->lock); - -err_kfree: - kfree(pmap); - - return error ? : error_init; + return error ?: error_init; } static ssize_t fw_file_store(struct device *dev, @@ -985,38 +976,30 @@ static int iqs5xx_suspend(struct device *dev) { struct iqs5xx_private *iqs5xx = dev_get_drvdata(dev); struct input_dev *input = iqs5xx->input; - int error = 0; if (!input || device_may_wakeup(dev)) - return error; - - mutex_lock(&input->mutex); + return 0; + guard(mutex)(&input->mutex); if (input_device_enabled(input)) - error = iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND); - - mutex_unlock(&input->mutex); + return iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND); - return error; + return 0; } static int iqs5xx_resume(struct device *dev) { struct iqs5xx_private *iqs5xx = dev_get_drvdata(dev); struct input_dev *input = iqs5xx->input; - int error = 0; if (!input || device_may_wakeup(dev)) - return error; - - mutex_lock(&input->mutex); + return 0; + guard(mutex)(&input->mutex); if (input_device_enabled(input)) - error = iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME); - - mutex_unlock(&input->mutex); + return iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME); - return error; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(iqs5xx_pm, iqs5xx_suspend, iqs5xx_resume);