gpio_sim_make_line_names() returns NULL or ERR_PTR() so we must not use __free(kfree) on the returned address. Split this function into two, one that determines the size of the "gpio-line-names" array to allocate and one that actually sets the names at correct offsets. The allocation and assignment of the managed pointer happens in between.
Unified · Split
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/irq.h> |
| 20 | 20 | #include <linux/irq_sim.h> |
| 21 | 21 | #include <linux/list.h> |
| 22 | +#include <linux/minmax.h> | |
| 22 | 23 | #include <linux/mod_devicetable.h> |
| 23 | 24 | #include <linux/module.h> |
| 24 | 25 | #include <linux/mutex.h> |
| @@ -685,52 +686,32 @@ gpio_sim_device_config_live_show(struct config_item *item, char *page) · 660 unmodified lines | ||
| 685 | 686 | return sprintf(page, "%c\n", live ? '1' : '0'); |
| 686 | 687 | } |
| 687 | 688 | |
| 688 | −static char **gpio_sim_make_line_names(struct gpio_sim_bank *bank, | |
| 689 | − unsigned int *line_names_size) | |
| 689 | +static unsigned int gpio_sim_get_line_names_size(struct gpio_sim_bank *bank) | |
| 690 | 690 | { |
| 691 | − unsigned int max_offset = 0; | |
| 692 | − bool has_line_names = false; | |
| 693 | 691 | struct gpio_sim_line *line; |
| 694 | − char **line_names; | |
| 692 | + unsigned int size = 0; | |
| 695 | 693 | |
| 696 | 694 | list_for_each_entry(line, &bank->line_list, siblings) { |
| 697 | − if (line->offset >= bank->num_lines) | |
| 695 | + if (!line->name || (line->offset >= bank->num_lines)) | |
| 698 | 696 | continue; |
| 699 | 697 | |
| 700 | − if (line->name) { | |
| 701 | − if (line->offset > max_offset) | |
| 702 | − max_offset = line->offset; | |
| 703 | − | |
| 704 | − /* | |
| 705 | − * max_offset can stay at 0 so it's not an indicator | |
| 706 | − * of whether line names were configured at all. | |
| 707 | − */ | |
| 708 | − has_line_names = true; | |
| 709 | − } | |
| 698 | + size = max(size, line->offset + 1); | |
| 710 | 699 | } |
| 711 | 700 | |
| 712 | − if (!has_line_names) | |
| 713 | − /* | |
| 714 | − * This is not an error - NULL means, there are no line | |
| 715 | − * names configured. | |
| 716 | − */ | |
| 717 | − return NULL; | |
| 718 | − | |
| 719 | − *line_names_size = max_offset + 1; | |
| 701 | + return size; | |
| 702 | +} | |
| 720 | 703 | |
| 721 | − line_names = kcalloc(*line_names_size, sizeof(*line_names), GFP_KERNEL); | |
| 722 | − if (!line_names) | |
| 723 | − return ERR_PTR(-ENOMEM); | |
| 704 | +static void | |
| 705 | +gpio_sim_set_line_names(struct gpio_sim_bank *bank, char **line_names) | |
| 706 | +{ | |
| 707 | + struct gpio_sim_line *line; | |
| 724 | 708 | |
| 725 | 709 | list_for_each_entry(line, &bank->line_list, siblings) { |
| 726 | − if (line->offset >= bank->num_lines) | |
| 710 | + if (!line->name || (line->offset >= bank->num_lines)) | |
| 727 | 711 | continue; |
| 728 | 712 | |
| 729 | − if (line->name && (line->offset <= max_offset)) | |
| 730 | − line_names[line->offset] = line->name; | |
| 713 | + line_names[line->offset] = line->name; | |
| 731 | 714 | } |
| 732 | − | |
| 733 | − return line_names; | |
| 734 | 715 | } |
| 735 | 716 | |
| 736 | 717 | static void gpio_sim_remove_hogs(struct gpio_sim_device *dev) |
| @@ -834,7 +815,7 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank, · 97 unmodified lines | ||
| 834 | 815 | struct fwnode_handle *parent) |
| 835 | 816 | { |
| 836 | 817 | struct property_entry properties[GPIO_SIM_PROP_MAX]; |
| 837 | − unsigned int prop_idx = 0, line_names_size = 0; | |
| 818 | + unsigned int prop_idx = 0, line_names_size; | |
| 838 | 819 | char **line_names __free(kfree) = NULL; |
| 839 | 820 | |
| 840 | 821 | memset(properties, 0, sizeof(properties)); |
| @@ -845,14 +826,19 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank, · 4 unmodified lines | ||
| 845 | 826 | properties[prop_idx++] = PROPERTY_ENTRY_STRING("gpio-sim,label", |
| 846 | 827 | bank->label); |
| 847 | 828 | |
| 848 | − line_names = gpio_sim_make_line_names(bank, &line_names_size); | |
| 849 | − if (IS_ERR(line_names)) | |
| 850 | − return ERR_CAST(line_names); | |
| 829 | + line_names_size = gpio_sim_get_line_names_size(bank); | |
| 830 | + if (line_names_size) { | |
| 831 | + line_names = kcalloc(line_names_size, sizeof(*line_names), | |
| 832 | + GFP_KERNEL); | |
| 833 | + if (!line_names) | |
| 834 | + return ERR_PTR(-ENOMEM); | |
| 835 | + | |
| 836 | + gpio_sim_set_line_names(bank, line_names); | |
| 851 | 837 | |
| 852 | − if (line_names) | |
| 853 | 838 | properties[prop_idx++] = PROPERTY_ENTRY_STRING_ARRAY_LEN( |
| 854 | 839 | "gpio-line-names", |
| 855 | 840 | line_names, line_names_size); |
| 841 | + } | |
| 856 | 842 | |
| 857 | 843 | return fwnode_create_software_node(properties, parent); |
| 858 | 844 | } |