Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Input: ili210x - switch to using cleanup functions in firmware code

Start using __free() attributes to simplify the code and error handling.

Link: https://lore.kernel.org/r/20240609234757.610273-2-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+78 -75
+78 -75
drivers/input/touchscreen/ili210x.c
··· 582 582 } 583 583 static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate); 584 584 585 - static int ili251x_firmware_to_buffer(const struct firmware *fw, 586 - u8 **buf, u16 *ac_end, u16 *df_end) 585 + static const u8 *ili251x_firmware_to_buffer(const struct firmware *fw, 586 + u16 *ac_end, u16 *df_end) 587 587 { 588 588 const struct ihex_binrec *rec; 589 589 u32 fw_addr, fw_last_addr = 0; 590 590 u16 fw_len; 591 - u8 *fw_buf; 592 - int error; 593 591 594 592 /* 595 593 * The firmware ihex blob can never be bigger than 64 kiB, so make this ··· 595 597 * once, copy them all into this buffer at the right locations, and then 596 598 * do all operations on this linear buffer. 597 599 */ 598 - fw_buf = kvmalloc(SZ_64K, GFP_KERNEL); 600 + u8* fw_buf __free(kvfree) = kvmalloc(SZ_64K, GFP_KERNEL); 599 601 if (!fw_buf) 600 - return -ENOMEM; 602 + return ERR_PTR(-ENOMEM); 601 603 602 604 rec = (const struct ihex_binrec *)fw->data; 603 605 while (rec) { ··· 605 607 fw_len = be16_to_cpu(rec->len); 606 608 607 609 /* The last 32 Byte firmware block can be 0xffe0 */ 608 - if (fw_addr + fw_len > SZ_64K || fw_addr > SZ_64K - 32) { 609 - error = -EFBIG; 610 - goto err_big; 611 - } 610 + if (fw_addr + fw_len > SZ_64K || fw_addr > SZ_64K - 32) 611 + return ERR_PTR(-EFBIG); 612 612 613 613 /* Find the last address before DF start address, that is AC end */ 614 614 if (fw_addr == 0xf000) ··· 619 623 620 624 /* DF end address is the last address in the firmware blob */ 621 625 *df_end = fw_addr + fw_len; 622 - *buf = fw_buf; 623 - return 0; 624 626 625 - err_big: 626 - kvfree(fw_buf); 627 - return error; 627 + return_ptr(fw_buf); 628 628 } 629 629 630 630 /* Switch mode between Application and BootLoader */ ··· 683 691 return 0; 684 692 } 685 693 686 - static int ili251x_firmware_write_to_ic(struct device *dev, u8 *fwbuf, 694 + static int ili251x_firmware_write_to_ic(struct device *dev, const u8 *fwbuf, 687 695 u16 start, u16 end, u8 dataflash) 688 696 { 689 697 struct i2c_client *client = to_i2c_client(dev); ··· 768 776 msleep(300); 769 777 } 770 778 779 + static int ili210x_do_firmware_update(struct ili210x *priv, 780 + const u8 *fwbuf, u16 ac_end, u16 df_end) 781 + { 782 + struct i2c_client *client = priv->client; 783 + struct device *dev = &client->dev; 784 + int error; 785 + int i; 786 + 787 + error = ili251x_firmware_reset(client); 788 + if (error) 789 + return error; 790 + 791 + /* This may not succeed on first try, so re-try a few times. */ 792 + for (i = 0; i < 5; i++) { 793 + error = ili251x_switch_ic_mode(client, REG_SET_MODE_BL); 794 + if (!error) 795 + break; 796 + } 797 + 798 + if (error) 799 + return error; 800 + 801 + dev_dbg(dev, "IC is now in BootLoader mode\n"); 802 + 803 + msleep(200); /* The bootloader seems to need some time too. */ 804 + 805 + error = ili251x_firmware_write_to_ic(dev, fwbuf, 0xf000, df_end, 1); 806 + if (error) { 807 + dev_err(dev, "DF firmware update failed, error=%d\n", error); 808 + return error; 809 + } 810 + 811 + dev_dbg(dev, "DataFlash firmware written\n"); 812 + 813 + error = ili251x_firmware_write_to_ic(dev, fwbuf, 0x2000, ac_end, 0); 814 + if (error) { 815 + dev_err(dev, "AC firmware update failed, error=%d\n", error); 816 + return error; 817 + } 818 + 819 + dev_dbg(dev, "Application firmware written\n"); 820 + 821 + /* This may not succeed on first try, so re-try a few times. */ 822 + for (i = 0; i < 5; i++) { 823 + error = ili251x_switch_ic_mode(client, REG_SET_MODE_AP); 824 + if (!error) 825 + break; 826 + } 827 + 828 + if (error) 829 + return error; 830 + 831 + dev_dbg(dev, "IC is now in Application mode\n"); 832 + 833 + error = ili251x_firmware_update_cached_state(dev); 834 + if (error) 835 + return error; 836 + 837 + return 0; 838 + } 839 + 771 840 static ssize_t ili210x_firmware_update_store(struct device *dev, 772 841 struct device_attribute *attr, 773 842 const char *buf, size_t count) ··· 836 783 struct i2c_client *client = to_i2c_client(dev); 837 784 struct ili210x *priv = i2c_get_clientdata(client); 838 785 const char *fwname = ILI251X_FW_FILENAME; 839 - const struct firmware *fw; 840 786 u16 ac_end, df_end; 841 - u8 *fwbuf; 842 787 int error; 843 - int i; 844 788 789 + const struct firmware *fw __free(firmware) = NULL; 845 790 error = request_ihex_firmware(&fw, fwname, dev); 846 791 if (error) { 847 792 dev_err(dev, "Failed to request firmware %s, error=%d\n", ··· 847 796 return error; 848 797 } 849 798 850 - error = ili251x_firmware_to_buffer(fw, &fwbuf, &ac_end, &df_end); 851 - release_firmware(fw); 799 + const u8* fwbuf __free(kvfree) = 800 + ili251x_firmware_to_buffer(fw, &ac_end, &df_end); 801 + error = PTR_ERR_OR_ZERO(fwbuf); 852 802 if (error) 853 803 return error; 854 804 ··· 866 814 867 815 ili210x_hardware_reset(priv->reset_gpio); 868 816 869 - error = ili251x_firmware_reset(client); 870 - if (error) 871 - goto exit; 817 + error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end); 872 818 873 - /* This may not succeed on first try, so re-try a few times. */ 874 - for (i = 0; i < 5; i++) { 875 - error = ili251x_switch_ic_mode(client, REG_SET_MODE_BL); 876 - if (!error) 877 - break; 878 - } 879 - 880 - if (error) 881 - goto exit; 882 - 883 - dev_dbg(dev, "IC is now in BootLoader mode\n"); 884 - 885 - msleep(200); /* The bootloader seems to need some time too. */ 886 - 887 - error = ili251x_firmware_write_to_ic(dev, fwbuf, 0xf000, df_end, 1); 888 - if (error) { 889 - dev_err(dev, "DF firmware update failed, error=%d\n", error); 890 - goto exit; 891 - } 892 - 893 - dev_dbg(dev, "DataFlash firmware written\n"); 894 - 895 - error = ili251x_firmware_write_to_ic(dev, fwbuf, 0x2000, ac_end, 0); 896 - if (error) { 897 - dev_err(dev, "AC firmware update failed, error=%d\n", error); 898 - goto exit; 899 - } 900 - 901 - dev_dbg(dev, "Application firmware written\n"); 902 - 903 - /* This may not succeed on first try, so re-try a few times. */ 904 - for (i = 0; i < 5; i++) { 905 - error = ili251x_switch_ic_mode(client, REG_SET_MODE_AP); 906 - if (!error) 907 - break; 908 - } 909 - 910 - if (error) 911 - goto exit; 912 - 913 - dev_dbg(dev, "IC is now in Application mode\n"); 914 - 915 - error = ili251x_firmware_update_cached_state(dev); 916 - if (error) 917 - goto exit; 918 - 919 - error = count; 920 - 921 - exit: 922 819 ili210x_hardware_reset(priv->reset_gpio); 820 + 923 821 dev_dbg(dev, "Firmware update ended, error=%i\n", error); 822 + 924 823 enable_irq(client->irq); 925 - kvfree(fwbuf); 926 - return error; 824 + 825 + return error ?: count; 927 826 } 928 827 929 828 static DEVICE_ATTR(firmware_update, 0200, NULL, ili210x_firmware_update_store);