Re: [PATCH] ACPI: utils: Make acpi_handle_list dynamically allocated

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Mar 30, 2023 at 5:13 AM Vicki Pfau <vi@xxxxxxxxxxx> wrote:
>
> This fixes a long-standing "TBD" comment in the ACPI headers regarding making
> the acpi_handle_list struct's size dynamic. The number 10, which along with the
> comment dates back to 2.4.23, seems like it may have been arbitrarily chosen,
> and isn't sufficient in all cases. This patch finally makes the size dynamic
> and updates its users to handle the modified API.
>
> Signed-off-by: Vicki Pfau <vi@xxxxxxxxxxx>
> ---
>  drivers/acpi/acpi_lpss.c                      |  9 ++--
>  drivers/acpi/scan.c                           |  9 ++--
>  drivers/acpi/thermal.c                        | 54 +++++++++++--------
>  drivers/acpi/utils.c                          | 14 ++---
>  .../platform/surface/surface_acpi_notify.c    |  9 ++--
>  include/acpi/acpi_bus.h                       | 18 +++++--
>  6 files changed, 71 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
> index f08ffa75f4a7..5aebd338943f 100644
> --- a/drivers/acpi/acpi_lpss.c
> +++ b/drivers/acpi/acpi_lpss.c
> @@ -561,7 +561,7 @@ static struct device *acpi_lpss_find_device(const char *hid, const char *uid)
>
>  static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle)
>  {
> -       struct acpi_handle_list dep_devices;
> +       struct acpi_handle_list *dep_devices;
>         acpi_status status;
>         int i;
>
> @@ -575,11 +575,14 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle)
>                 return false;
>         }
>
> -       for (i = 0; i < dep_devices.count; i++) {
> -               if (dep_devices.handles[i] == handle)
> +       for (i = 0; i < dep_devices->count; i++) {
> +               if (dep_devices->handles[i] == handle) {
> +                       kfree(dep_devices);
>                         return true;
> +               }
>         }
>
> +       kfree(dep_devices);
>         return false;
>  }
>
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 0c6f06abe3f4..167423b68f83 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1972,7 +1972,7 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev)
>
>  static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
>  {
> -       struct acpi_handle_list dep_devices;
> +       struct acpi_handle_list *dep_devices;
>         acpi_status status;
>         u32 count;
>         int i;
> @@ -1993,12 +1993,12 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
>                 return 0;
>         }
>
> -       for (count = 0, i = 0; i < dep_devices.count; i++) {
> +       for (count = 0, i = 0; i < dep_devices->count; i++) {
>                 struct acpi_device_info *info;
>                 struct acpi_dep_data *dep;
>                 bool skip, honor_dep;
>
> -               status = acpi_get_object_info(dep_devices.handles[i], &info);
> +               status = acpi_get_object_info(dep_devices->handles[i], &info);
>                 if (ACPI_FAILURE(status)) {
>                         acpi_handle_debug(handle, "Error reading _DEP device info\n");
>                         continue;
> @@ -2017,7 +2017,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
>
>                 count++;
>
> -               dep->supplier = dep_devices.handles[i];
> +               dep->supplier = dep_devices->handles[i];
>                 dep->consumer = handle;
>                 dep->honor_dep = honor_dep;
>
> @@ -2026,6 +2026,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
>                 mutex_unlock(&acpi_dep_list_lock);
>         }
>
> +       kfree(dep_devices);
>         return count;
>  }
>
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index 0b4b844f9d4c..132b206cd4e6 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -135,13 +135,13 @@ struct acpi_thermal_passive {
>         unsigned long tc1;
>         unsigned long tc2;
>         unsigned long tsp;
> -       struct acpi_handle_list devices;
> +       struct acpi_handle_list *devices;
>  };
>
>  struct acpi_thermal_active {
>         struct acpi_thermal_state_flags flags;
>         unsigned long temperature;
> -       struct acpi_handle_list devices;
> +       struct acpi_handle_list *devices;
>  };
>
>  struct acpi_thermal_trips {
> @@ -167,7 +167,7 @@ struct acpi_thermal {
>         struct acpi_thermal_flags flags;
>         struct acpi_thermal_state state;
>         struct acpi_thermal_trips trips;
> -       struct acpi_handle_list devices;
> +       struct acpi_handle_list *devices;
>         struct thermal_zone_device *thermal_zone;
>         int kelvin_offset;      /* in millidegrees */
>         struct work_struct thermal_check_work;
> @@ -264,7 +264,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
>  {
>         acpi_status status;
>         unsigned long long tmp;
> -       struct acpi_handle_list devices;
> +       struct acpi_handle_list *devices;
>         int valid = 0;
>         int i;
>
> @@ -368,7 +368,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
>                 }
>         }
>         if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
> -               memset(&devices, 0, sizeof(struct acpi_handle_list));
> +               devices = NULL;
>                 status = acpi_evaluate_reference(tz->device->handle, "_PSL",
>                                                  NULL, &devices);
>                 if (ACPI_FAILURE(status)) {
> @@ -379,11 +379,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
>                         tz->trips.passive.flags.valid = 1;
>                 }
>
> -               if (memcmp(&tz->trips.passive.devices, &devices,
> -                          sizeof(struct acpi_handle_list))) {
> -                       memcpy(&tz->trips.passive.devices, &devices,
> -                              sizeof(struct acpi_handle_list));
> +               if (!acpi_handle_list_equal(tz->trips.passive.devices, devices)) {
> +                       kfree(tz->trips.passive.devices);
> +                       tz->trips.passive.devices = devices;
>                         ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
> +               } else if (devices) {
> +                       kfree(devices);
>                 }
>         }
>         if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
> @@ -433,7 +434,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
>
>                 name[2] = 'L';
>                 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid) {
> -                       memset(&devices, 0, sizeof(struct acpi_handle_list));
> +                       devices = NULL;
>                         status = acpi_evaluate_reference(tz->device->handle,
>                                                          name, NULL, &devices);
>                         if (ACPI_FAILURE(status)) {
> @@ -444,11 +445,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
>                                 tz->trips.active[i].flags.valid = 1;
>                         }
>
> -                       if (memcmp(&tz->trips.active[i].devices, &devices,
> -                                  sizeof(struct acpi_handle_list))) {
> -                               memcpy(&tz->trips.active[i].devices, &devices,
> -                                      sizeof(struct acpi_handle_list));
> +                       if (!acpi_handle_list_equal(tz->trips.active[i].devices, devices)) {
> +                               kfree(tz->trips.active[i].devices);
> +                               tz->trips.active[i].devices = devices;
>                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
> +                       } else if (devices) {
> +                               kfree(devices);
>                         }
>                 }
>                 if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
> @@ -460,13 +462,16 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
>         }
>
>         if (flag & ACPI_TRIPS_DEVICES) {
> -               memset(&devices, 0, sizeof(devices));
> +               devices = NULL;
>                 status = acpi_evaluate_reference(tz->device->handle, "_TZD",
>                                                  NULL, &devices);
>                 if (ACPI_SUCCESS(status) &&
> -                   memcmp(&tz->devices, &devices, sizeof(devices))) {
> +                   !acpi_handle_list_equal(tz->devices, devices)) {
> +                       kfree(tz->devices);
>                         tz->devices = devices;
>                         ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
> +               } else if (devices) {
> +                       kfree(devices);
>                 }
>         }
>
> @@ -709,8 +714,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
>
>         if (tz->trips.passive.flags.valid) {
>                 trip++;
> -               for (i = 0; i < tz->trips.passive.devices.count; i++) {
> -                       handle = tz->trips.passive.devices.handles[i];
> +               for (i = 0; i < tz->trips.passive.devices->count; i++) {
> +                       handle = tz->trips.passive.devices->handles[i];
>                         dev = acpi_fetch_acpi_dev(handle);
>                         if (dev != device)
>                                 continue;
> @@ -736,8 +741,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
>                         break;
>
>                 trip++;
> -               for (j = 0; j < tz->trips.active[i].devices.count; j++) {
> -                       handle = tz->trips.active[i].devices.handles[j];
> +               for (j = 0; j < tz->trips.active[i].devices->count; j++) {
> +                       handle = tz->trips.active[i].devices->handles[j];
>                         dev = acpi_fetch_acpi_dev(handle);
>                         if (dev != device)
>                                 continue;
> @@ -1062,6 +1067,7 @@ static int acpi_thermal_add(struct acpi_device *device)
>  static void acpi_thermal_remove(struct acpi_device *device)
>  {
>         struct acpi_thermal *tz;
> +       int i;
>
>         if (!device || !acpi_driver_data(device))
>                 return;
> @@ -1070,6 +1076,10 @@ static void acpi_thermal_remove(struct acpi_device *device)
>         tz = acpi_driver_data(device);
>
>         acpi_thermal_unregister_thermal_zone(tz);
> +       kfree(tz->trips.passive.devices);
> +       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
> +               kfree(tz->trips.active[i].devices);
> +       kfree(tz->devices);
>         kfree(tz);
>  }
>
> @@ -1098,9 +1108,9 @@ static int acpi_thermal_resume(struct device *dev)
>                         break;
>
>                 tz->trips.active[i].flags.enabled = 1;
> -               for (j = 0; j < tz->trips.active[i].devices.count; j++) {
> +               for (j = 0; j < tz->trips.active[i].devices->count; j++) {
>                         result = acpi_bus_update_power(
> -                                       tz->trips.active[i].devices.handles[j],
> +                                       tz->trips.active[i].devices->handles[j],
>                                         &power_state);
>                         if (result || (power_state != ACPI_STATE_D0)) {
>                                 tz->trips.active[i].flags.enabled = 0;
> diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
> index 2ea14648a661..dd76389ede96 100644
> --- a/drivers/acpi/utils.c
> +++ b/drivers/acpi/utils.c
> @@ -333,16 +333,17 @@ acpi_status
>  acpi_evaluate_reference(acpi_handle handle,
>                         acpi_string pathname,
>                         struct acpi_object_list *arguments,
> -                       struct acpi_handle_list *list)
> +                       struct acpi_handle_list **out)
>  {
>         acpi_status status = AE_OK;
> +       struct acpi_handle_list *list = NULL;
>         union acpi_object *package = NULL;
>         union acpi_object *element = NULL;
>         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>         u32 i = 0;
>
>
> -       if (!list) {
> +       if (!out) {
>                 return AE_BAD_PARAMETER;
>         }
>
> @@ -370,7 +371,8 @@ acpi_evaluate_reference(acpi_handle handle,
>                 goto end;
>         }
>
> -       if (package->package.count > ACPI_MAX_HANDLES) {
> +       list = kmalloc(package->package.count * sizeof(list->handles[0]) + sizeof(*list), GFP_KERNEL);
> +       if (!list) {
>                 kfree(package);
>                 return AE_NO_MEMORY;
>         }
> @@ -400,12 +402,12 @@ acpi_evaluate_reference(acpi_handle handle,
>         }
>
>        end:
> -       if (ACPI_FAILURE(status)) {
> -               list->count = 0;
> -               //kfree(list->handles);
> +       if (ACPI_FAILURE(status) && list) {
> +               kfree(list);
>         }
>
>         kfree(buffer.pointer);
> +       *out = list;
>
>         return status;
>  }
> diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c
> index 897cdd9c3aae..c6ead68cefc9 100644
> --- a/drivers/platform/surface/surface_acpi_notify.c
> +++ b/drivers/platform/surface/surface_acpi_notify.c
> @@ -738,7 +738,7 @@ do {                                                                                \
>
>  static bool is_san_consumer(struct platform_device *pdev, acpi_handle handle)
>  {
> -       struct acpi_handle_list dep_devices;
> +       struct acpi_handle_list *dep_devices;
>         acpi_handle supplier = ACPI_HANDLE(&pdev->dev);
>         acpi_status status;
>         int i;
> @@ -752,11 +752,14 @@ static bool is_san_consumer(struct platform_device *pdev, acpi_handle handle)
>                 return false;
>         }
>
> -       for (i = 0; i < dep_devices.count; i++) {
> -               if (dep_devices.handles[i] == supplier)
> +       for (i = 0; i < dep_devices->count; i++) {
> +               if (dep_devices->handles[i] == supplier) {
> +                       kfree(dep_devices);
>                         return true;
> +               }
>         }
>
> +       kfree(dep_devices);
>         return false;
>  }
>
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index 57acb895c038..8684efcf0e17 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -12,11 +12,9 @@
>  #include <linux/device.h>
>  #include <linux/property.h>
>
> -/* TBD: Make dynamic */
> -#define ACPI_MAX_HANDLES       10
>  struct acpi_handle_list {
>         u32 count;
> -       acpi_handle handles[ACPI_MAX_HANDLES];
> +       acpi_handle handles[];

Can you just use

acpi_handle *handles;

here, in which case you won't need to change all of the struct
acpi_handle_list variables into pointers?

>  };
>
>  /* acpi_utils.h */
> @@ -31,7 +29,7 @@ acpi_status
>  acpi_evaluate_reference(acpi_handle handle,
>                         acpi_string pathname,
>                         struct acpi_object_list *arguments,
> -                       struct acpi_handle_list *list);
> +                       struct acpi_handle_list **list);
>  acpi_status
>  acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code,
>                   struct acpi_buffer *status_buf);
> @@ -69,6 +67,18 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev,
>         return obj;
>  }
>
> +static inline bool
> +acpi_handle_list_equal(struct acpi_handle_list *a, struct acpi_handle_list *b)
> +{
> +       if (!a || !b)
> +               return false;
> +
> +       if (a->count != b->count)
> +               return false;
> +
> +       return !memcmp(a->handles, b->handles, a->count * sizeof(acpi_handle));
> +}
> +
>  #define        ACPI_INIT_DSM_ARGV4(cnt, eles)                  \
>         {                                               \
>           .package.type = ACPI_TYPE_PACKAGE,            \
> --
> 2.40.0
>



[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]
  Powered by Linux