| @@ -19,6 +19,7 @@ · 18 unmodified lines |
| 19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
| 20 | #include <linux/irq_sim.h> | 20 | #include <linux/irq_sim.h> |
| 21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
| | 22 | #include <linux/minmax.h> |
| 22 | #include <linux/mod_devicetable.h> | 23 | #include <linux/mod_devicetable.h> |
| 23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 24 | #include <linux/mutex.h> | 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 | return sprintf(page, "%c\n", live ? '1' : '0'); | 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 | static unsigned int gpio_sim_get_line_names_size(struct gpio_sim_bank *bank) |
| 689 | unsigned int *line_names_size) | | |
| 690 | { | 690 | { |
| 691 | unsigned int max_offset = 0; | | |
| 692 | bool has_line_names = false; | | |
| 693 | struct gpio_sim_line *line; | 691 | struct gpio_sim_line *line; |
| 694 | char **line_names; | 692 | unsigned int size = 0; |
| 695 | | 693 | |
| 696 | list_for_each_entry(line, &bank->line_list, siblings) { | 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 | continue; | 696 | continue; |
| 699 | | 697 | |
| 700 | if (line->name) { | 698 | size = max(size, line->offset + 1); |
| 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 | } | | |
| 710 | } | 699 | } |
| 711 | | 700 | |
| 712 | if (!has_line_names) | 701 | return size; |
| 713 | /* | 702 | } |
| 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; | | |
| 720 | | 703 | |
| 721 | line_names = kcalloc(*line_names_size, sizeof(*line_names), GFP_KERNEL); | 704 | static void |
| 722 | if (!line_names) | 705 | gpio_sim_set_line_names(struct gpio_sim_bank *bank, char **line_names) |
| 723 | return ERR_PTR(-ENOMEM); | 706 | { |
| | 707 | struct gpio_sim_line *line; |
| 724 | | 708 | |
| 725 | list_for_each_entry(line, &bank->line_list, siblings) { | 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 | continue; | 711 | continue; |
| 728 | | 712 | |
| 729 | if (line->name && (line->offset <= max_offset)) | 713 | line_names[line->offset] = line->name; |
| 730 | line_names[line->offset] = line->name; | | |
| 731 | } | 714 | } |
| 732 | | | |
| 733 | return line_names; | | |
| 734 | } | 715 | } |
| 735 | | 716 | |
| 736 | static void gpio_sim_remove_hogs(struct gpio_sim_device *dev) | 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 | struct fwnode_handle *parent) | 815 | struct fwnode_handle *parent) |
| 835 | { | 816 | { |
| 836 | struct property_entry properties[GPIO_SIM_PROP_MAX]; | 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 | char **line_names __free(kfree) = NULL; | 819 | char **line_names __free(kfree) = NULL; |
| 839 | | 820 | |
| 840 | memset(properties, 0, sizeof(properties)); | 821 | memset(properties, 0, sizeof(properties)); |
| @@ -845,14 +826,19 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank, · 4 unmodified lines |
| 845 | properties[prop_idx++] = PROPERTY_ENTRY_STRING("gpio-sim,label", | 826 | properties[prop_idx++] = PROPERTY_ENTRY_STRING("gpio-sim,label", |
| 846 | bank->label); | 827 | bank->label); |
| 847 | | 828 | |
| 848 | line_names = gpio_sim_make_line_names(bank, &line_names_size); | 829 | line_names_size = gpio_sim_get_line_names_size(bank); |
| 849 | if (IS_ERR(line_names)) | 830 | if (line_names_size) { |
| 850 | return ERR_CAST(line_names); | 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 | properties[prop_idx++] = PROPERTY_ENTRY_STRING_ARRAY_LEN( | 838 | properties[prop_idx++] = PROPERTY_ENTRY_STRING_ARRAY_LEN( |
| 854 | "gpio-line-names", | 839 | "gpio-line-names", |
| 855 | line_names, line_names_size); | 840 | line_names, line_names_size); |
| | 841 | } |
| 856 | | 842 | |
| 857 | return fwnode_create_software_node(properties, parent); | 843 | return fwnode_create_software_node(properties, parent); |
| 858 | } | 844 | } |