| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 
|---|
| 2 | /* | 
|---|
| 3 | *  battery.c - ACPI Battery Driver (Revision: 2.0) | 
|---|
| 4 | * | 
|---|
| 5 | *  Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de> | 
|---|
| 6 | *  Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com> | 
|---|
| 7 | *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 
|---|
| 8 | *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 
|---|
| 9 | */ | 
|---|
| 10 |  | 
|---|
| 11 | #define pr_fmt(fmt) "ACPI: battery: " fmt | 
|---|
| 12 |  | 
|---|
| 13 | #include <linux/delay.h> | 
|---|
| 14 | #include <linux/dmi.h> | 
|---|
| 15 | #include <linux/jiffies.h> | 
|---|
| 16 | #include <linux/kernel.h> | 
|---|
| 17 | #include <linux/list.h> | 
|---|
| 18 | #include <linux/module.h> | 
|---|
| 19 | #include <linux/mutex.h> | 
|---|
| 20 | #include <linux/slab.h> | 
|---|
| 21 | #include <linux/suspend.h> | 
|---|
| 22 | #include <linux/types.h> | 
|---|
| 23 |  | 
|---|
| 24 | #include <linux/unaligned.h> | 
|---|
| 25 |  | 
|---|
| 26 | #include <linux/acpi.h> | 
|---|
| 27 | #include <linux/power_supply.h> | 
|---|
| 28 |  | 
|---|
| 29 | #include <acpi/battery.h> | 
|---|
| 30 |  | 
|---|
| 31 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF | 
|---|
| 32 | #define ACPI_BATTERY_CAPACITY_VALID(capacity) \ | 
|---|
| 33 | ((capacity) != 0 && (capacity) != ACPI_BATTERY_VALUE_UNKNOWN) | 
|---|
| 34 |  | 
|---|
| 35 | #define ACPI_BATTERY_DEVICE_NAME	"Battery" | 
|---|
| 36 |  | 
|---|
| 37 | /* Battery power unit: 0 means mW, 1 means mA */ | 
|---|
| 38 | #define ACPI_BATTERY_POWER_UNIT_MA	1 | 
|---|
| 39 |  | 
|---|
| 40 | #define ACPI_BATTERY_STATE_DISCHARGING		0x1 | 
|---|
| 41 | #define ACPI_BATTERY_STATE_CHARGING		0x2 | 
|---|
| 42 | #define ACPI_BATTERY_STATE_CRITICAL		0x4 | 
|---|
| 43 | #define ACPI_BATTERY_STATE_CHARGE_LIMITING	0x8 | 
|---|
| 44 |  | 
|---|
| 45 | #define MAX_STRING_LENGTH	64 | 
|---|
| 46 |  | 
|---|
| 47 | MODULE_AUTHOR( "Paul Diefenbaugh"); | 
|---|
| 48 | MODULE_AUTHOR( "Alexey Starikovskiy <astarikovskiy@suse.de>"); | 
|---|
| 49 | MODULE_DESCRIPTION( "ACPI Battery Driver"); | 
|---|
| 50 | MODULE_LICENSE( "GPL"); | 
|---|
| 51 |  | 
|---|
| 52 | static int battery_bix_broken_package; | 
|---|
| 53 | static int battery_notification_delay_ms; | 
|---|
| 54 | static int battery_ac_is_broken; | 
|---|
| 55 | static unsigned int cache_time = 1000; | 
|---|
| 56 | module_param(cache_time, uint, 0644); | 
|---|
| 57 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); | 
|---|
| 58 |  | 
|---|
| 59 | static const struct acpi_device_id battery_device_ids[] = { | 
|---|
| 60 | { "PNP0C0A", 0}, | 
|---|
| 61 |  | 
|---|
| 62 | /* Microsoft Surface Go 3 */ | 
|---|
| 63 | {.id: "MSHW0146", .driver_data: 0}, | 
|---|
| 64 |  | 
|---|
| 65 | {.id: "", .driver_data: 0}, | 
|---|
| 66 | }; | 
|---|
| 67 |  | 
|---|
| 68 | MODULE_DEVICE_TABLE(acpi, battery_device_ids); | 
|---|
| 69 |  | 
|---|
| 70 | enum { | 
|---|
| 71 | ACPI_BATTERY_ALARM_PRESENT, | 
|---|
| 72 | ACPI_BATTERY_XINFO_PRESENT, | 
|---|
| 73 | ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, | 
|---|
| 74 | /* On Lenovo Thinkpad models from 2010 and 2011, the power unit | 
|---|
| 75 | * switches between mWh and mAh depending on whether the system | 
|---|
| 76 | * is running on battery or not.  When mAh is the unit, most | 
|---|
| 77 | * reported values are incorrect and need to be adjusted by | 
|---|
| 78 | * 10000/design_voltage.  Verified on x201, t410, t410s, and x220. | 
|---|
| 79 | * Pre-2010 and 2012 models appear to always report in mWh and | 
|---|
| 80 | * are thus unaffected (tested with t42, t61, t500, x200, x300, | 
|---|
| 81 | * and x230).  Also, in mid-2012 Lenovo issued a BIOS update for | 
|---|
| 82 | *  the 2011 models that fixes the issue (tested on x220 with a | 
|---|
| 83 | * post-1.29 BIOS), but as of Nov. 2012, no such update is | 
|---|
| 84 | * available for the 2010 models. | 
|---|
| 85 | */ | 
|---|
| 86 | ACPI_BATTERY_QUIRK_THINKPAD_MAH, | 
|---|
| 87 | /* for batteries reporting current capacity with design capacity | 
|---|
| 88 | * on a full charge, but showing degradation in full charge cap. | 
|---|
| 89 | */ | 
|---|
| 90 | ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, | 
|---|
| 91 | }; | 
|---|
| 92 |  | 
|---|
| 93 | struct acpi_battery { | 
|---|
| 94 | struct mutex lock; | 
|---|
| 95 | struct mutex update_lock; | 
|---|
| 96 | struct power_supply *bat; | 
|---|
| 97 | struct power_supply_desc bat_desc; | 
|---|
| 98 | struct acpi_device *device; | 
|---|
| 99 | struct notifier_block pm_nb; | 
|---|
| 100 | struct list_head list; | 
|---|
| 101 | unsigned long update_time; | 
|---|
| 102 | int revision; | 
|---|
| 103 | int rate_now; | 
|---|
| 104 | int capacity_now; | 
|---|
| 105 | int voltage_now; | 
|---|
| 106 | int design_capacity; | 
|---|
| 107 | int full_charge_capacity; | 
|---|
| 108 | int technology; | 
|---|
| 109 | int design_voltage; | 
|---|
| 110 | int design_capacity_warning; | 
|---|
| 111 | int design_capacity_low; | 
|---|
| 112 | int cycle_count; | 
|---|
| 113 | int measurement_accuracy; | 
|---|
| 114 | int max_sampling_time; | 
|---|
| 115 | int min_sampling_time; | 
|---|
| 116 | int max_averaging_interval; | 
|---|
| 117 | int min_averaging_interval; | 
|---|
| 118 | int capacity_granularity_1; | 
|---|
| 119 | int capacity_granularity_2; | 
|---|
| 120 | int alarm; | 
|---|
| 121 | char model_number[MAX_STRING_LENGTH]; | 
|---|
| 122 | char serial_number[MAX_STRING_LENGTH]; | 
|---|
| 123 | char type[MAX_STRING_LENGTH]; | 
|---|
| 124 | char oem_info[MAX_STRING_LENGTH]; | 
|---|
| 125 | int state; | 
|---|
| 126 | int power_unit; | 
|---|
| 127 | unsigned long flags; | 
|---|
| 128 | }; | 
|---|
| 129 |  | 
|---|
| 130 | #define to_acpi_battery(x) power_supply_get_drvdata(x) | 
|---|
| 131 |  | 
|---|
| 132 | static inline int acpi_battery_present(struct acpi_battery *battery) | 
|---|
| 133 | { | 
|---|
| 134 | return battery->device->status.battery_present; | 
|---|
| 135 | } | 
|---|
| 136 |  | 
|---|
| 137 | static int acpi_battery_technology(struct acpi_battery *battery) | 
|---|
| 138 | { | 
|---|
| 139 | if (!strcasecmp(s1: "NiCd", s2: battery->type)) | 
|---|
| 140 | return POWER_SUPPLY_TECHNOLOGY_NiCd; | 
|---|
| 141 | if (!strcasecmp(s1: "NiMH", s2: battery->type)) | 
|---|
| 142 | return POWER_SUPPLY_TECHNOLOGY_NiMH; | 
|---|
| 143 | if (!strcasecmp(s1: "LION", s2: battery->type)) | 
|---|
| 144 | return POWER_SUPPLY_TECHNOLOGY_LION; | 
|---|
| 145 | if (!strncasecmp(s1: "LI-ION", s2: battery->type, n: 6)) | 
|---|
| 146 | return POWER_SUPPLY_TECHNOLOGY_LION; | 
|---|
| 147 | if (!strcasecmp(s1: "LiP", s2: battery->type)) | 
|---|
| 148 | return POWER_SUPPLY_TECHNOLOGY_LIPO; | 
|---|
| 149 | return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; | 
|---|
| 150 | } | 
|---|
| 151 |  | 
|---|
| 152 | static int acpi_battery_get_state(struct acpi_battery *battery); | 
|---|
| 153 |  | 
|---|
| 154 | static int acpi_battery_is_charged(struct acpi_battery *battery) | 
|---|
| 155 | { | 
|---|
| 156 | /* charging, discharging, critical low or charge limited */ | 
|---|
| 157 | if (battery->state != 0) | 
|---|
| 158 | return 0; | 
|---|
| 159 |  | 
|---|
| 160 | /* battery not reporting charge */ | 
|---|
| 161 | if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN || | 
|---|
| 162 | battery->capacity_now == 0) | 
|---|
| 163 | return 0; | 
|---|
| 164 |  | 
|---|
| 165 | /* good batteries update full_charge as the batteries degrade */ | 
|---|
| 166 | if (battery->full_charge_capacity == battery->capacity_now) | 
|---|
| 167 | return 1; | 
|---|
| 168 |  | 
|---|
| 169 | /* fallback to using design values for broken batteries */ | 
|---|
| 170 | if (battery->design_capacity <= battery->capacity_now) | 
|---|
| 171 | return 1; | 
|---|
| 172 |  | 
|---|
| 173 | /* we don't do any sort of metric based on percentages */ | 
|---|
| 174 | return 0; | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | static bool acpi_battery_is_degraded(struct acpi_battery *battery) | 
|---|
| 178 | { | 
|---|
| 179 | return ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) && | 
|---|
| 180 | ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity) && | 
|---|
| 181 | battery->full_charge_capacity < battery->design_capacity; | 
|---|
| 182 | } | 
|---|
| 183 |  | 
|---|
| 184 | static int acpi_battery_handle_discharging(struct acpi_battery *battery) | 
|---|
| 185 | { | 
|---|
| 186 | /* | 
|---|
| 187 | * Some devices wrongly report discharging if the battery's charge level | 
|---|
| 188 | * was above the device's start charging threshold atm the AC adapter | 
|---|
| 189 | * was plugged in and the device thus did not start a new charge cycle. | 
|---|
| 190 | */ | 
|---|
| 191 | if ((battery_ac_is_broken || power_supply_is_system_supplied()) && | 
|---|
| 192 | battery->rate_now == 0) | 
|---|
| 193 | return POWER_SUPPLY_STATUS_NOT_CHARGING; | 
|---|
| 194 |  | 
|---|
| 195 | return POWER_SUPPLY_STATUS_DISCHARGING; | 
|---|
| 196 | } | 
|---|
| 197 |  | 
|---|
| 198 | static int acpi_battery_get_property(struct power_supply *psy, | 
|---|
| 199 | enum power_supply_property psp, | 
|---|
| 200 | union power_supply_propval *val) | 
|---|
| 201 | { | 
|---|
| 202 | int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0; | 
|---|
| 203 | struct acpi_battery *battery = to_acpi_battery(psy); | 
|---|
| 204 |  | 
|---|
| 205 | if (acpi_battery_present(battery)) { | 
|---|
| 206 | /* run battery update only if it is present */ | 
|---|
| 207 | acpi_battery_get_state(battery); | 
|---|
| 208 | } else if (psp != POWER_SUPPLY_PROP_PRESENT) | 
|---|
| 209 | return -ENODEV; | 
|---|
| 210 | switch (psp) { | 
|---|
| 211 | case POWER_SUPPLY_PROP_STATUS: | 
|---|
| 212 | if (battery->state & ACPI_BATTERY_STATE_DISCHARGING) | 
|---|
| 213 | val->intval = acpi_battery_handle_discharging(battery); | 
|---|
| 214 | else if (battery->state & ACPI_BATTERY_STATE_CHARGING) | 
|---|
| 215 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | 
|---|
| 216 | else if (battery->state & ACPI_BATTERY_STATE_CHARGE_LIMITING) | 
|---|
| 217 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | 
|---|
| 218 | else if (acpi_battery_is_charged(battery)) | 
|---|
| 219 | val->intval = POWER_SUPPLY_STATUS_FULL; | 
|---|
| 220 | else | 
|---|
| 221 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | 
|---|
| 222 | break; | 
|---|
| 223 | case POWER_SUPPLY_PROP_PRESENT: | 
|---|
| 224 | val->intval = acpi_battery_present(battery); | 
|---|
| 225 | break; | 
|---|
| 226 | case POWER_SUPPLY_PROP_TECHNOLOGY: | 
|---|
| 227 | val->intval = acpi_battery_technology(battery); | 
|---|
| 228 | break; | 
|---|
| 229 | case POWER_SUPPLY_PROP_CYCLE_COUNT: | 
|---|
| 230 | val->intval = battery->cycle_count; | 
|---|
| 231 | break; | 
|---|
| 232 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | 
|---|
| 233 | if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) | 
|---|
| 234 | ret = -ENODEV; | 
|---|
| 235 | else | 
|---|
| 236 | val->intval = battery->design_voltage * 1000; | 
|---|
| 237 | break; | 
|---|
| 238 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 
|---|
| 239 | if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) | 
|---|
| 240 | ret = -ENODEV; | 
|---|
| 241 | else | 
|---|
| 242 | val->intval = battery->voltage_now * 1000; | 
|---|
| 243 | break; | 
|---|
| 244 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 
|---|
| 245 | case POWER_SUPPLY_PROP_POWER_NOW: | 
|---|
| 246 | if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) | 
|---|
| 247 | ret = -ENODEV; | 
|---|
| 248 | else | 
|---|
| 249 | val->intval = battery->rate_now * 1000; | 
|---|
| 250 | break; | 
|---|
| 251 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | 
|---|
| 252 | case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: | 
|---|
| 253 | if (!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity)) | 
|---|
| 254 | ret = -ENODEV; | 
|---|
| 255 | else | 
|---|
| 256 | val->intval = battery->design_capacity * 1000; | 
|---|
| 257 | break; | 
|---|
| 258 | case POWER_SUPPLY_PROP_CHARGE_FULL: | 
|---|
| 259 | case POWER_SUPPLY_PROP_ENERGY_FULL: | 
|---|
| 260 | if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity)) | 
|---|
| 261 | ret = -ENODEV; | 
|---|
| 262 | else | 
|---|
| 263 | val->intval = battery->full_charge_capacity * 1000; | 
|---|
| 264 | break; | 
|---|
| 265 | case POWER_SUPPLY_PROP_CHARGE_NOW: | 
|---|
| 266 | case POWER_SUPPLY_PROP_ENERGY_NOW: | 
|---|
| 267 | if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) | 
|---|
| 268 | ret = -ENODEV; | 
|---|
| 269 | else | 
|---|
| 270 | val->intval = battery->capacity_now * 1000; | 
|---|
| 271 | break; | 
|---|
| 272 | case POWER_SUPPLY_PROP_CAPACITY: | 
|---|
| 273 | if (ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity)) | 
|---|
| 274 | full_capacity = battery->full_charge_capacity; | 
|---|
| 275 | else if (ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity)) | 
|---|
| 276 | full_capacity = battery->design_capacity; | 
|---|
| 277 |  | 
|---|
| 278 | if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN || | 
|---|
| 279 | full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) | 
|---|
| 280 | ret = -ENODEV; | 
|---|
| 281 | else | 
|---|
| 282 | val->intval = DIV_ROUND_CLOSEST_ULL(battery->capacity_now * 100ULL, | 
|---|
| 283 | full_capacity); | 
|---|
| 284 | break; | 
|---|
| 285 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | 
|---|
| 286 | if (battery->state & ACPI_BATTERY_STATE_CRITICAL) | 
|---|
| 287 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | 
|---|
| 288 | else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && | 
|---|
| 289 | (battery->capacity_now <= battery->alarm)) | 
|---|
| 290 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | 
|---|
| 291 | else if (acpi_battery_is_charged(battery)) | 
|---|
| 292 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | 
|---|
| 293 | else | 
|---|
| 294 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | 
|---|
| 295 | break; | 
|---|
| 296 | case POWER_SUPPLY_PROP_MODEL_NAME: | 
|---|
| 297 | val->strval = battery->model_number; | 
|---|
| 298 | break; | 
|---|
| 299 | case POWER_SUPPLY_PROP_MANUFACTURER: | 
|---|
| 300 | val->strval = battery->oem_info; | 
|---|
| 301 | break; | 
|---|
| 302 | case POWER_SUPPLY_PROP_SERIAL_NUMBER: | 
|---|
| 303 | val->strval = battery->serial_number; | 
|---|
| 304 | break; | 
|---|
| 305 | default: | 
|---|
| 306 | ret = -EINVAL; | 
|---|
| 307 | } | 
|---|
| 308 | return ret; | 
|---|
| 309 | } | 
|---|
| 310 |  | 
|---|
| 311 | static const enum power_supply_property charge_battery_props[] = { | 
|---|
| 312 | POWER_SUPPLY_PROP_STATUS, | 
|---|
| 313 | POWER_SUPPLY_PROP_PRESENT, | 
|---|
| 314 | POWER_SUPPLY_PROP_TECHNOLOGY, | 
|---|
| 315 | POWER_SUPPLY_PROP_CYCLE_COUNT, | 
|---|
| 316 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | 
|---|
| 317 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 
|---|
| 318 | POWER_SUPPLY_PROP_CURRENT_NOW, | 
|---|
| 319 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | 
|---|
| 320 | POWER_SUPPLY_PROP_CHARGE_FULL, | 
|---|
| 321 | POWER_SUPPLY_PROP_CHARGE_NOW, | 
|---|
| 322 | POWER_SUPPLY_PROP_CAPACITY, | 
|---|
| 323 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | 
|---|
| 324 | POWER_SUPPLY_PROP_MODEL_NAME, | 
|---|
| 325 | POWER_SUPPLY_PROP_MANUFACTURER, | 
|---|
| 326 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 
|---|
| 327 | }; | 
|---|
| 328 |  | 
|---|
| 329 | static const enum power_supply_property charge_battery_full_cap_broken_props[] = { | 
|---|
| 330 | POWER_SUPPLY_PROP_STATUS, | 
|---|
| 331 | POWER_SUPPLY_PROP_PRESENT, | 
|---|
| 332 | POWER_SUPPLY_PROP_TECHNOLOGY, | 
|---|
| 333 | POWER_SUPPLY_PROP_CYCLE_COUNT, | 
|---|
| 334 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | 
|---|
| 335 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 
|---|
| 336 | POWER_SUPPLY_PROP_CURRENT_NOW, | 
|---|
| 337 | POWER_SUPPLY_PROP_CHARGE_NOW, | 
|---|
| 338 | POWER_SUPPLY_PROP_MODEL_NAME, | 
|---|
| 339 | POWER_SUPPLY_PROP_MANUFACTURER, | 
|---|
| 340 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 
|---|
| 341 | }; | 
|---|
| 342 |  | 
|---|
| 343 | static const enum power_supply_property energy_battery_props[] = { | 
|---|
| 344 | POWER_SUPPLY_PROP_STATUS, | 
|---|
| 345 | POWER_SUPPLY_PROP_PRESENT, | 
|---|
| 346 | POWER_SUPPLY_PROP_TECHNOLOGY, | 
|---|
| 347 | POWER_SUPPLY_PROP_CYCLE_COUNT, | 
|---|
| 348 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | 
|---|
| 349 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 
|---|
| 350 | POWER_SUPPLY_PROP_POWER_NOW, | 
|---|
| 351 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, | 
|---|
| 352 | POWER_SUPPLY_PROP_ENERGY_FULL, | 
|---|
| 353 | POWER_SUPPLY_PROP_ENERGY_NOW, | 
|---|
| 354 | POWER_SUPPLY_PROP_CAPACITY, | 
|---|
| 355 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | 
|---|
| 356 | POWER_SUPPLY_PROP_MODEL_NAME, | 
|---|
| 357 | POWER_SUPPLY_PROP_MANUFACTURER, | 
|---|
| 358 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 
|---|
| 359 | }; | 
|---|
| 360 |  | 
|---|
| 361 | static const enum power_supply_property energy_battery_full_cap_broken_props[] = { | 
|---|
| 362 | POWER_SUPPLY_PROP_STATUS, | 
|---|
| 363 | POWER_SUPPLY_PROP_PRESENT, | 
|---|
| 364 | POWER_SUPPLY_PROP_TECHNOLOGY, | 
|---|
| 365 | POWER_SUPPLY_PROP_CYCLE_COUNT, | 
|---|
| 366 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | 
|---|
| 367 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 
|---|
| 368 | POWER_SUPPLY_PROP_POWER_NOW, | 
|---|
| 369 | POWER_SUPPLY_PROP_ENERGY_NOW, | 
|---|
| 370 | POWER_SUPPLY_PROP_MODEL_NAME, | 
|---|
| 371 | POWER_SUPPLY_PROP_MANUFACTURER, | 
|---|
| 372 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 
|---|
| 373 | }; | 
|---|
| 374 |  | 
|---|
| 375 | /* Battery Management */ | 
|---|
| 376 | struct acpi_offsets { | 
|---|
| 377 | size_t offset;		/* offset inside struct acpi_sbs_battery */ | 
|---|
| 378 | u8 mode;		/* int or string? */ | 
|---|
| 379 | }; | 
|---|
| 380 |  | 
|---|
| 381 | static const struct acpi_offsets state_offsets[] = { | 
|---|
| 382 | {offsetof(struct acpi_battery, state), 0}, | 
|---|
| 383 | {offsetof(struct acpi_battery, rate_now), 0}, | 
|---|
| 384 | {offsetof(struct acpi_battery, capacity_now), 0}, | 
|---|
| 385 | {offsetof(struct acpi_battery, voltage_now), 0}, | 
|---|
| 386 | }; | 
|---|
| 387 |  | 
|---|
| 388 | static const struct acpi_offsets info_offsets[] = { | 
|---|
| 389 | {offsetof(struct acpi_battery, power_unit), 0}, | 
|---|
| 390 | {offsetof(struct acpi_battery, design_capacity), 0}, | 
|---|
| 391 | {offsetof(struct acpi_battery, full_charge_capacity), 0}, | 
|---|
| 392 | {offsetof(struct acpi_battery, technology), 0}, | 
|---|
| 393 | {offsetof(struct acpi_battery, design_voltage), 0}, | 
|---|
| 394 | {offsetof(struct acpi_battery, design_capacity_warning), 0}, | 
|---|
| 395 | {offsetof(struct acpi_battery, design_capacity_low), 0}, | 
|---|
| 396 | {offsetof(struct acpi_battery, capacity_granularity_1), 0}, | 
|---|
| 397 | {offsetof(struct acpi_battery, capacity_granularity_2), 0}, | 
|---|
| 398 | {offsetof(struct acpi_battery, model_number), 1}, | 
|---|
| 399 | {offsetof(struct acpi_battery, serial_number), 1}, | 
|---|
| 400 | {offsetof(struct acpi_battery, type), 1}, | 
|---|
| 401 | {offsetof(struct acpi_battery, oem_info), 1}, | 
|---|
| 402 | }; | 
|---|
| 403 |  | 
|---|
| 404 | static const struct acpi_offsets extended_info_offsets[] = { | 
|---|
| 405 | {offsetof(struct acpi_battery, revision), 0}, | 
|---|
| 406 | {offsetof(struct acpi_battery, power_unit), 0}, | 
|---|
| 407 | {offsetof(struct acpi_battery, design_capacity), 0}, | 
|---|
| 408 | {offsetof(struct acpi_battery, full_charge_capacity), 0}, | 
|---|
| 409 | {offsetof(struct acpi_battery, technology), 0}, | 
|---|
| 410 | {offsetof(struct acpi_battery, design_voltage), 0}, | 
|---|
| 411 | {offsetof(struct acpi_battery, design_capacity_warning), 0}, | 
|---|
| 412 | {offsetof(struct acpi_battery, design_capacity_low), 0}, | 
|---|
| 413 | {offsetof(struct acpi_battery, cycle_count), 0}, | 
|---|
| 414 | {offsetof(struct acpi_battery, measurement_accuracy), 0}, | 
|---|
| 415 | {offsetof(struct acpi_battery, max_sampling_time), 0}, | 
|---|
| 416 | {offsetof(struct acpi_battery, min_sampling_time), 0}, | 
|---|
| 417 | {offsetof(struct acpi_battery, max_averaging_interval), 0}, | 
|---|
| 418 | {offsetof(struct acpi_battery, min_averaging_interval), 0}, | 
|---|
| 419 | {offsetof(struct acpi_battery, capacity_granularity_1), 0}, | 
|---|
| 420 | {offsetof(struct acpi_battery, capacity_granularity_2), 0}, | 
|---|
| 421 | {offsetof(struct acpi_battery, model_number), 1}, | 
|---|
| 422 | {offsetof(struct acpi_battery, serial_number), 1}, | 
|---|
| 423 | {offsetof(struct acpi_battery, type), 1}, | 
|---|
| 424 | {offsetof(struct acpi_battery, oem_info), 1}, | 
|---|
| 425 | }; | 
|---|
| 426 |  | 
|---|
| 427 | static int (struct acpi_battery *battery, | 
|---|
| 428 | union acpi_object *package, | 
|---|
| 429 | const struct acpi_offsets *offsets, int num) | 
|---|
| 430 | { | 
|---|
| 431 | int i; | 
|---|
| 432 | union acpi_object *element; | 
|---|
| 433 |  | 
|---|
| 434 | if (package->type != ACPI_TYPE_PACKAGE) | 
|---|
| 435 | return -EFAULT; | 
|---|
| 436 | for (i = 0; i < num; ++i) { | 
|---|
| 437 | if (package->package.count <= i) | 
|---|
| 438 | return -EFAULT; | 
|---|
| 439 | element = &package->package.elements[i]; | 
|---|
| 440 | if (offsets[i].mode) { | 
|---|
| 441 | u8 *ptr = (u8 *)battery + offsets[i].offset; | 
|---|
| 442 | u32 len = MAX_STRING_LENGTH; | 
|---|
| 443 |  | 
|---|
| 444 | switch (element->type) { | 
|---|
| 445 | case ACPI_TYPE_BUFFER: | 
|---|
| 446 | if (len > element->buffer.length + 1) | 
|---|
| 447 | len = element->buffer.length + 1; | 
|---|
| 448 |  | 
|---|
| 449 | fallthrough; | 
|---|
| 450 | case ACPI_TYPE_STRING: | 
|---|
| 451 | strscpy(ptr, element->string.pointer, len); | 
|---|
| 452 |  | 
|---|
| 453 | break; | 
|---|
| 454 | case ACPI_TYPE_INTEGER: | 
|---|
| 455 | strscpy(ptr, (u8 *)&element->integer.value, sizeof(u64) + 1); | 
|---|
| 456 |  | 
|---|
| 457 | break; | 
|---|
| 458 | default: | 
|---|
| 459 | *ptr = 0; /* don't have value */ | 
|---|
| 460 | } | 
|---|
| 461 | } else { | 
|---|
| 462 | int *x = (int *)((u8 *)battery + offsets[i].offset); | 
|---|
| 463 | *x = (element->type == ACPI_TYPE_INTEGER) ? | 
|---|
| 464 | element->integer.value : -1; | 
|---|
| 465 | } | 
|---|
| 466 | } | 
|---|
| 467 | return 0; | 
|---|
| 468 | } | 
|---|
| 469 |  | 
|---|
| 470 | static int acpi_battery_get_status(struct acpi_battery *battery) | 
|---|
| 471 | { | 
|---|
| 472 | if (acpi_bus_get_status(device: battery->device)) { | 
|---|
| 473 | acpi_handle_info(battery->device->handle, | 
|---|
| 474 | "_STA evaluation failed\n"); | 
|---|
| 475 | return -ENODEV; | 
|---|
| 476 | } | 
|---|
| 477 | return 0; | 
|---|
| 478 | } | 
|---|
| 479 |  | 
|---|
| 480 |  | 
|---|
| 481 | static int (const int use_bix, | 
|---|
| 482 | struct acpi_battery *battery, | 
|---|
| 483 | const struct acpi_buffer *buffer) | 
|---|
| 484 | { | 
|---|
| 485 | int result = -EFAULT; | 
|---|
| 486 |  | 
|---|
| 487 | if (use_bix && battery_bix_broken_package) | 
|---|
| 488 | result = extract_package(battery, package: buffer->pointer, | 
|---|
| 489 | offsets: extended_info_offsets + 1, | 
|---|
| 490 | ARRAY_SIZE(extended_info_offsets) - 1); | 
|---|
| 491 | else if (use_bix) | 
|---|
| 492 | result = extract_package(battery, package: buffer->pointer, | 
|---|
| 493 | offsets: extended_info_offsets, | 
|---|
| 494 | ARRAY_SIZE(extended_info_offsets)); | 
|---|
| 495 | else | 
|---|
| 496 | result = extract_package(battery, package: buffer->pointer, | 
|---|
| 497 | offsets: info_offsets, ARRAY_SIZE(info_offsets)); | 
|---|
| 498 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | 
|---|
| 499 | battery->full_charge_capacity = battery->design_capacity; | 
|---|
| 500 | if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && | 
|---|
| 501 | battery->power_unit && battery->design_voltage) { | 
|---|
| 502 | battery->design_capacity = battery->design_capacity * | 
|---|
| 503 | 10000 / battery->design_voltage; | 
|---|
| 504 | battery->full_charge_capacity = battery->full_charge_capacity * | 
|---|
| 505 | 10000 / battery->design_voltage; | 
|---|
| 506 | battery->design_capacity_warning = | 
|---|
| 507 | battery->design_capacity_warning * | 
|---|
| 508 | 10000 / battery->design_voltage; | 
|---|
| 509 | /* Curiously, design_capacity_low, unlike the rest of them, | 
|---|
| 510 | *  is correct. | 
|---|
| 511 | */ | 
|---|
| 512 | /* capacity_granularity_* equal 1 on the systems tested, so | 
|---|
| 513 | * it's impossible to tell if they would need an adjustment | 
|---|
| 514 | * or not if their values were higher. | 
|---|
| 515 | */ | 
|---|
| 516 | } | 
|---|
| 517 | if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) && | 
|---|
| 518 | battery->capacity_now > battery->full_charge_capacity) | 
|---|
| 519 | battery->capacity_now = battery->full_charge_capacity; | 
|---|
| 520 |  | 
|---|
| 521 | return result; | 
|---|
| 522 | } | 
|---|
| 523 |  | 
|---|
| 524 | static int acpi_battery_get_info(struct acpi_battery *battery) | 
|---|
| 525 | { | 
|---|
| 526 | const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); | 
|---|
| 527 | int use_bix; | 
|---|
| 528 | int result = -ENODEV; | 
|---|
| 529 |  | 
|---|
| 530 | if (!acpi_battery_present(battery)) | 
|---|
| 531 | return 0; | 
|---|
| 532 |  | 
|---|
| 533 |  | 
|---|
| 534 | for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) { | 
|---|
| 535 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 
|---|
| 536 | acpi_status status = AE_ERROR; | 
|---|
| 537 |  | 
|---|
| 538 | mutex_lock(lock: &battery->lock); | 
|---|
| 539 | status = acpi_evaluate_object(object: battery->device->handle, | 
|---|
| 540 | pathname: use_bix ? "_BIX": "_BIF", | 
|---|
| 541 | NULL, return_object_buffer: &buffer); | 
|---|
| 542 | mutex_unlock(lock: &battery->lock); | 
|---|
| 543 |  | 
|---|
| 544 | if (ACPI_FAILURE(status)) { | 
|---|
| 545 | acpi_handle_info(battery->device->handle, | 
|---|
| 546 | "%s evaluation failed: %s\n", | 
|---|
| 547 | use_bix ? "_BIX": "_BIF", | 
|---|
| 548 | acpi_format_exception(status)); | 
|---|
| 549 | } else { | 
|---|
| 550 | result = extract_battery_info(use_bix, | 
|---|
| 551 | battery, | 
|---|
| 552 | buffer: &buffer); | 
|---|
| 553 |  | 
|---|
| 554 | kfree(objp: buffer.pointer); | 
|---|
| 555 | break; | 
|---|
| 556 | } | 
|---|
| 557 | } | 
|---|
| 558 |  | 
|---|
| 559 | if (!result && !use_bix && xinfo) | 
|---|
| 560 | pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n"); | 
|---|
| 561 |  | 
|---|
| 562 | return result; | 
|---|
| 563 | } | 
|---|
| 564 |  | 
|---|
| 565 | static int acpi_battery_get_state(struct acpi_battery *battery) | 
|---|
| 566 | { | 
|---|
| 567 | int result = 0; | 
|---|
| 568 | acpi_status status = 0; | 
|---|
| 569 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 
|---|
| 570 |  | 
|---|
| 571 | if (!acpi_battery_present(battery)) | 
|---|
| 572 | return 0; | 
|---|
| 573 |  | 
|---|
| 574 | if (battery->update_time && | 
|---|
| 575 | time_before(jiffies, battery->update_time + | 
|---|
| 576 | msecs_to_jiffies(cache_time))) | 
|---|
| 577 | return 0; | 
|---|
| 578 |  | 
|---|
| 579 | mutex_lock(lock: &battery->lock); | 
|---|
| 580 | status = acpi_evaluate_object(object: battery->device->handle, pathname: "_BST", | 
|---|
| 581 | NULL, return_object_buffer: &buffer); | 
|---|
| 582 | mutex_unlock(lock: &battery->lock); | 
|---|
| 583 |  | 
|---|
| 584 | if (ACPI_FAILURE(status)) { | 
|---|
| 585 | acpi_handle_info(battery->device->handle, | 
|---|
| 586 | "_BST evaluation failed: %s", | 
|---|
| 587 | acpi_format_exception(status)); | 
|---|
| 588 | return -ENODEV; | 
|---|
| 589 | } | 
|---|
| 590 |  | 
|---|
| 591 | result = extract_package(battery, package: buffer.pointer, | 
|---|
| 592 | offsets: state_offsets, ARRAY_SIZE(state_offsets)); | 
|---|
| 593 | battery->update_time = jiffies; | 
|---|
| 594 | kfree(objp: buffer.pointer); | 
|---|
| 595 |  | 
|---|
| 596 | /* For buggy DSDTs that report negative 16-bit values for either | 
|---|
| 597 | * charging or discharging current and/or report 0 as 65536 | 
|---|
| 598 | * due to bad math. | 
|---|
| 599 | */ | 
|---|
| 600 | if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA && | 
|---|
| 601 | battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN && | 
|---|
| 602 | (s16)(battery->rate_now) < 0) { | 
|---|
| 603 | battery->rate_now = abs((s16)battery->rate_now); | 
|---|
| 604 | pr_warn_once(FW_BUG "(dis)charge rate invalid.\n"); | 
|---|
| 605 | } | 
|---|
| 606 |  | 
|---|
| 607 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) | 
|---|
| 608 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) | 
|---|
| 609 | battery->capacity_now = (battery->capacity_now * | 
|---|
| 610 | battery->full_charge_capacity) / 100; | 
|---|
| 611 | if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && | 
|---|
| 612 | battery->power_unit && battery->design_voltage) { | 
|---|
| 613 | battery->capacity_now = battery->capacity_now * | 
|---|
| 614 | 10000 / battery->design_voltage; | 
|---|
| 615 | } | 
|---|
| 616 | if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) && | 
|---|
| 617 | battery->capacity_now > battery->full_charge_capacity) | 
|---|
| 618 | battery->capacity_now = battery->full_charge_capacity; | 
|---|
| 619 |  | 
|---|
| 620 | return result; | 
|---|
| 621 | } | 
|---|
| 622 |  | 
|---|
| 623 | static int acpi_battery_set_alarm(struct acpi_battery *battery) | 
|---|
| 624 | { | 
|---|
| 625 | acpi_status status = 0; | 
|---|
| 626 |  | 
|---|
| 627 | if (!acpi_battery_present(battery) || | 
|---|
| 628 | !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags)) | 
|---|
| 629 | return -ENODEV; | 
|---|
| 630 |  | 
|---|
| 631 | mutex_lock(lock: &battery->lock); | 
|---|
| 632 | status = acpi_execute_simple_method(handle: battery->device->handle, method: "_BTP", | 
|---|
| 633 | arg: battery->alarm); | 
|---|
| 634 | mutex_unlock(lock: &battery->lock); | 
|---|
| 635 |  | 
|---|
| 636 | if (ACPI_FAILURE(status)) | 
|---|
| 637 | return -ENODEV; | 
|---|
| 638 |  | 
|---|
| 639 | acpi_handle_debug(battery->device->handle, "Alarm set to %d\n", | 
|---|
| 640 | battery->alarm); | 
|---|
| 641 |  | 
|---|
| 642 | return 0; | 
|---|
| 643 | } | 
|---|
| 644 |  | 
|---|
| 645 | static int acpi_battery_init_alarm(struct acpi_battery *battery) | 
|---|
| 646 | { | 
|---|
| 647 | /* See if alarms are supported, and if so, set default */ | 
|---|
| 648 | if (!acpi_has_method(handle: battery->device->handle, name: "_BTP")) { | 
|---|
| 649 | clear_bit(nr: ACPI_BATTERY_ALARM_PRESENT, addr: &battery->flags); | 
|---|
| 650 | return 0; | 
|---|
| 651 | } | 
|---|
| 652 | set_bit(nr: ACPI_BATTERY_ALARM_PRESENT, addr: &battery->flags); | 
|---|
| 653 | if (!battery->alarm) | 
|---|
| 654 | battery->alarm = battery->design_capacity_warning; | 
|---|
| 655 | return acpi_battery_set_alarm(battery); | 
|---|
| 656 | } | 
|---|
| 657 |  | 
|---|
| 658 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 
|---|
| 659 | struct device_attribute *attr, | 
|---|
| 660 | char *buf) | 
|---|
| 661 | { | 
|---|
| 662 | struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); | 
|---|
| 663 |  | 
|---|
| 664 | return sysfs_emit(buf, fmt: "%d\n", battery->alarm * 1000); | 
|---|
| 665 | } | 
|---|
| 666 |  | 
|---|
| 667 | static ssize_t acpi_battery_alarm_store(struct device *dev, | 
|---|
| 668 | struct device_attribute *attr, | 
|---|
| 669 | const char *buf, size_t count) | 
|---|
| 670 | { | 
|---|
| 671 | unsigned long x; | 
|---|
| 672 | struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); | 
|---|
| 673 |  | 
|---|
| 674 | if (sscanf(buf, "%lu\n", &x) == 1) | 
|---|
| 675 | battery->alarm = x/1000; | 
|---|
| 676 | if (acpi_battery_present(battery)) | 
|---|
| 677 | acpi_battery_set_alarm(battery); | 
|---|
| 678 | return count; | 
|---|
| 679 | } | 
|---|
| 680 |  | 
|---|
| 681 | static struct device_attribute alarm_attr = { | 
|---|
| 682 | .attr = {.name = "alarm", .mode = 0644}, | 
|---|
| 683 | .show = acpi_battery_alarm_show, | 
|---|
| 684 | .store = acpi_battery_alarm_store, | 
|---|
| 685 | }; | 
|---|
| 686 |  | 
|---|
| 687 | static struct attribute *acpi_battery_attrs[] = { | 
|---|
| 688 | &alarm_attr.attr, | 
|---|
| 689 | NULL | 
|---|
| 690 | }; | 
|---|
| 691 | ATTRIBUTE_GROUPS(acpi_battery); | 
|---|
| 692 |  | 
|---|
| 693 | /* | 
|---|
| 694 | * The Battery Hooking API | 
|---|
| 695 | * | 
|---|
| 696 | * This API is used inside other drivers that need to expose | 
|---|
| 697 | * platform-specific behaviour within the generic driver in a | 
|---|
| 698 | * generic way. | 
|---|
| 699 | * | 
|---|
| 700 | */ | 
|---|
| 701 |  | 
|---|
| 702 | static LIST_HEAD(acpi_battery_list); | 
|---|
| 703 | static LIST_HEAD(battery_hook_list); | 
|---|
| 704 | static DEFINE_MUTEX(hook_mutex); | 
|---|
| 705 |  | 
|---|
| 706 | static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook) | 
|---|
| 707 | { | 
|---|
| 708 | struct acpi_battery *battery; | 
|---|
| 709 |  | 
|---|
| 710 | /* | 
|---|
| 711 | * In order to remove a hook, we first need to | 
|---|
| 712 | * de-register all the batteries that are registered. | 
|---|
| 713 | */ | 
|---|
| 714 | list_for_each_entry(battery, &acpi_battery_list, list) { | 
|---|
| 715 | if (!hook->remove_battery(battery->bat, hook)) | 
|---|
| 716 | power_supply_changed(psy: battery->bat); | 
|---|
| 717 | } | 
|---|
| 718 | list_del_init(entry: &hook->list); | 
|---|
| 719 |  | 
|---|
| 720 | pr_info( "hook unregistered: %s\n", hook->name); | 
|---|
| 721 | } | 
|---|
| 722 |  | 
|---|
| 723 | void battery_hook_unregister(struct acpi_battery_hook *hook) | 
|---|
| 724 | { | 
|---|
| 725 | mutex_lock(lock: &hook_mutex); | 
|---|
| 726 | /* | 
|---|
| 727 | * Ignore already unregistered battery hooks. This might happen | 
|---|
| 728 | * if a battery hook was previously unloaded due to an error when | 
|---|
| 729 | * adding a new battery. | 
|---|
| 730 | */ | 
|---|
| 731 | if (!list_empty(head: &hook->list)) | 
|---|
| 732 | battery_hook_unregister_unlocked(hook); | 
|---|
| 733 |  | 
|---|
| 734 | mutex_unlock(lock: &hook_mutex); | 
|---|
| 735 | } | 
|---|
| 736 | EXPORT_SYMBOL_GPL(battery_hook_unregister); | 
|---|
| 737 |  | 
|---|
| 738 | void battery_hook_register(struct acpi_battery_hook *hook) | 
|---|
| 739 | { | 
|---|
| 740 | struct acpi_battery *battery; | 
|---|
| 741 |  | 
|---|
| 742 | mutex_lock(lock: &hook_mutex); | 
|---|
| 743 | list_add(new: &hook->list, head: &battery_hook_list); | 
|---|
| 744 | /* | 
|---|
| 745 | * Now that the driver is registered, we need | 
|---|
| 746 | * to notify the hook that a battery is available | 
|---|
| 747 | * for each battery, so that the driver may add | 
|---|
| 748 | * its attributes. | 
|---|
| 749 | */ | 
|---|
| 750 | list_for_each_entry(battery, &acpi_battery_list, list) { | 
|---|
| 751 | if (hook->add_battery(battery->bat, hook)) { | 
|---|
| 752 | /* | 
|---|
| 753 | * If a add-battery returns non-zero, | 
|---|
| 754 | * the registration of the hook has failed, | 
|---|
| 755 | * and we will not add it to the list of loaded | 
|---|
| 756 | * hooks. | 
|---|
| 757 | */ | 
|---|
| 758 | pr_err( "hook failed to load: %s", hook->name); | 
|---|
| 759 | battery_hook_unregister_unlocked(hook); | 
|---|
| 760 | goto end; | 
|---|
| 761 | } | 
|---|
| 762 |  | 
|---|
| 763 | power_supply_changed(psy: battery->bat); | 
|---|
| 764 | } | 
|---|
| 765 | pr_info( "new hook: %s\n", hook->name); | 
|---|
| 766 | end: | 
|---|
| 767 | mutex_unlock(lock: &hook_mutex); | 
|---|
| 768 | } | 
|---|
| 769 | EXPORT_SYMBOL_GPL(battery_hook_register); | 
|---|
| 770 |  | 
|---|
| 771 | static void devm_battery_hook_unregister(void *data) | 
|---|
| 772 | { | 
|---|
| 773 | struct acpi_battery_hook *hook = data; | 
|---|
| 774 |  | 
|---|
| 775 | battery_hook_unregister(hook); | 
|---|
| 776 | } | 
|---|
| 777 |  | 
|---|
| 778 | int devm_battery_hook_register(struct device *dev, struct acpi_battery_hook *hook) | 
|---|
| 779 | { | 
|---|
| 780 | battery_hook_register(hook); | 
|---|
| 781 |  | 
|---|
| 782 | return devm_add_action_or_reset(dev, devm_battery_hook_unregister, hook); | 
|---|
| 783 | } | 
|---|
| 784 | EXPORT_SYMBOL_GPL(devm_battery_hook_register); | 
|---|
| 785 |  | 
|---|
| 786 | /* | 
|---|
| 787 | * This function gets called right after the battery sysfs | 
|---|
| 788 | * attributes have been added, so that the drivers that | 
|---|
| 789 | * define custom sysfs attributes can add their own. | 
|---|
| 790 | */ | 
|---|
| 791 | static void battery_hook_add_battery(struct acpi_battery *battery) | 
|---|
| 792 | { | 
|---|
| 793 | struct acpi_battery_hook *hook_node, *tmp; | 
|---|
| 794 |  | 
|---|
| 795 | mutex_lock(lock: &hook_mutex); | 
|---|
| 796 | INIT_LIST_HEAD(list: &battery->list); | 
|---|
| 797 | list_add(new: &battery->list, head: &acpi_battery_list); | 
|---|
| 798 | /* | 
|---|
| 799 | * Since we added a new battery to the list, we need to | 
|---|
| 800 | * iterate over the hooks and call add_battery for each | 
|---|
| 801 | * hook that was registered. This usually happens | 
|---|
| 802 | * when a battery gets hotplugged or initialized | 
|---|
| 803 | * during the battery module initialization. | 
|---|
| 804 | */ | 
|---|
| 805 | list_for_each_entry_safe(hook_node, tmp, &battery_hook_list, list) { | 
|---|
| 806 | if (hook_node->add_battery(battery->bat, hook_node)) { | 
|---|
| 807 | /* | 
|---|
| 808 | * The notification of the hook has failed, to | 
|---|
| 809 | * prevent further errors we will unload the hook. | 
|---|
| 810 | */ | 
|---|
| 811 | pr_err( "error in hook, unloading: %s", | 
|---|
| 812 | hook_node->name); | 
|---|
| 813 | battery_hook_unregister_unlocked(hook: hook_node); | 
|---|
| 814 | } | 
|---|
| 815 | } | 
|---|
| 816 | mutex_unlock(lock: &hook_mutex); | 
|---|
| 817 | } | 
|---|
| 818 |  | 
|---|
| 819 | static void battery_hook_remove_battery(struct acpi_battery *battery) | 
|---|
| 820 | { | 
|---|
| 821 | struct acpi_battery_hook *hook; | 
|---|
| 822 |  | 
|---|
| 823 | mutex_lock(lock: &hook_mutex); | 
|---|
| 824 | /* | 
|---|
| 825 | * Before removing the hook, we need to remove all | 
|---|
| 826 | * custom attributes from the battery. | 
|---|
| 827 | */ | 
|---|
| 828 | list_for_each_entry(hook, &battery_hook_list, list) { | 
|---|
| 829 | hook->remove_battery(battery->bat, hook); | 
|---|
| 830 | } | 
|---|
| 831 | /* Then, just remove the battery from the list */ | 
|---|
| 832 | list_del(entry: &battery->list); | 
|---|
| 833 | mutex_unlock(lock: &hook_mutex); | 
|---|
| 834 | } | 
|---|
| 835 |  | 
|---|
| 836 | static void __exit battery_hook_exit(void) | 
|---|
| 837 | { | 
|---|
| 838 | struct acpi_battery_hook *hook; | 
|---|
| 839 | struct acpi_battery_hook *ptr; | 
|---|
| 840 | /* | 
|---|
| 841 | * At this point, the acpi_bus_unregister_driver() | 
|---|
| 842 | * has called remove for all batteries. We just | 
|---|
| 843 | * need to remove the hooks. | 
|---|
| 844 | */ | 
|---|
| 845 | list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) { | 
|---|
| 846 | battery_hook_unregister(hook); | 
|---|
| 847 | } | 
|---|
| 848 | mutex_destroy(lock: &hook_mutex); | 
|---|
| 849 | } | 
|---|
| 850 |  | 
|---|
| 851 | static int sysfs_add_battery(struct acpi_battery *battery) | 
|---|
| 852 | { | 
|---|
| 853 | struct power_supply_config psy_cfg = { | 
|---|
| 854 | .drv_data = battery, | 
|---|
| 855 | .attr_grp = acpi_battery_groups, | 
|---|
| 856 | .no_wakeup_source = true, | 
|---|
| 857 | }; | 
|---|
| 858 | bool full_cap_broken = false; | 
|---|
| 859 |  | 
|---|
| 860 | if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) && | 
|---|
| 861 | !ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity)) | 
|---|
| 862 | full_cap_broken = true; | 
|---|
| 863 |  | 
|---|
| 864 | if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) { | 
|---|
| 865 | if (full_cap_broken) { | 
|---|
| 866 | battery->bat_desc.properties = | 
|---|
| 867 | charge_battery_full_cap_broken_props; | 
|---|
| 868 | battery->bat_desc.num_properties = | 
|---|
| 869 | ARRAY_SIZE(charge_battery_full_cap_broken_props); | 
|---|
| 870 | } else { | 
|---|
| 871 | battery->bat_desc.properties = charge_battery_props; | 
|---|
| 872 | battery->bat_desc.num_properties = | 
|---|
| 873 | ARRAY_SIZE(charge_battery_props); | 
|---|
| 874 | } | 
|---|
| 875 | } else { | 
|---|
| 876 | if (full_cap_broken) { | 
|---|
| 877 | battery->bat_desc.properties = | 
|---|
| 878 | energy_battery_full_cap_broken_props; | 
|---|
| 879 | battery->bat_desc.num_properties = | 
|---|
| 880 | ARRAY_SIZE(energy_battery_full_cap_broken_props); | 
|---|
| 881 | } else { | 
|---|
| 882 | battery->bat_desc.properties = energy_battery_props; | 
|---|
| 883 | battery->bat_desc.num_properties = | 
|---|
| 884 | ARRAY_SIZE(energy_battery_props); | 
|---|
| 885 | } | 
|---|
| 886 | } | 
|---|
| 887 |  | 
|---|
| 888 | battery->bat_desc.name = acpi_device_bid(battery->device); | 
|---|
| 889 | battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY; | 
|---|
| 890 | battery->bat_desc.get_property = acpi_battery_get_property; | 
|---|
| 891 |  | 
|---|
| 892 | battery->bat = power_supply_register(parent: &battery->device->dev, | 
|---|
| 893 | desc: &battery->bat_desc, cfg: &psy_cfg); | 
|---|
| 894 |  | 
|---|
| 895 | if (IS_ERR(ptr: battery->bat)) { | 
|---|
| 896 | int result = PTR_ERR(ptr: battery->bat); | 
|---|
| 897 |  | 
|---|
| 898 | battery->bat = NULL; | 
|---|
| 899 | return result; | 
|---|
| 900 | } | 
|---|
| 901 | battery_hook_add_battery(battery); | 
|---|
| 902 | return 0; | 
|---|
| 903 | } | 
|---|
| 904 |  | 
|---|
| 905 | static void sysfs_remove_battery(struct acpi_battery *battery) | 
|---|
| 906 | { | 
|---|
| 907 | if (!battery->bat) | 
|---|
| 908 | return; | 
|---|
| 909 |  | 
|---|
| 910 | battery_hook_remove_battery(battery); | 
|---|
| 911 | power_supply_unregister(psy: battery->bat); | 
|---|
| 912 | battery->bat = NULL; | 
|---|
| 913 | } | 
|---|
| 914 |  | 
|---|
| 915 | static void find_battery(const struct dmi_header *dm, void *private) | 
|---|
| 916 | { | 
|---|
| 917 | struct acpi_battery *battery = (struct acpi_battery *)private; | 
|---|
| 918 | /* Note: the hardcoded offsets below have been extracted from | 
|---|
| 919 | * the source code of dmidecode. | 
|---|
| 920 | */ | 
|---|
| 921 | if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) { | 
|---|
| 922 | const u8 *dmi_data = (const u8 *)(dm + 1); | 
|---|
| 923 | int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6)); | 
|---|
| 924 |  | 
|---|
| 925 | if (dm->length >= 18) | 
|---|
| 926 | dmi_capacity *= dmi_data[17]; | 
|---|
| 927 | if (battery->design_capacity * battery->design_voltage / 1000 | 
|---|
| 928 | != dmi_capacity && | 
|---|
| 929 | battery->design_capacity * 10 == dmi_capacity) | 
|---|
| 930 | set_bit(nr: ACPI_BATTERY_QUIRK_THINKPAD_MAH, | 
|---|
| 931 | addr: &battery->flags); | 
|---|
| 932 | } | 
|---|
| 933 | } | 
|---|
| 934 |  | 
|---|
| 935 | /* | 
|---|
| 936 | * According to the ACPI spec, some kinds of primary batteries can | 
|---|
| 937 | * report percentage battery remaining capacity directly to OS. | 
|---|
| 938 | * In this case, it reports the Last Full Charged Capacity == 100 | 
|---|
| 939 | * and BatteryPresentRate == 0xFFFFFFFF. | 
|---|
| 940 | * | 
|---|
| 941 | * Now we found some battery reports percentage remaining capacity | 
|---|
| 942 | * even if it's rechargeable. | 
|---|
| 943 | * https://bugzilla.kernel.org/show_bug.cgi?id=15979 | 
|---|
| 944 | * | 
|---|
| 945 | * Handle this correctly so that they won't break userspace. | 
|---|
| 946 | */ | 
|---|
| 947 | static void acpi_battery_quirks(struct acpi_battery *battery) | 
|---|
| 948 | { | 
|---|
| 949 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | 
|---|
| 950 | return; | 
|---|
| 951 |  | 
|---|
| 952 | if (battery->full_charge_capacity == 100 && | 
|---|
| 953 | battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN && | 
|---|
| 954 | battery->capacity_now >= 0 && battery->capacity_now <= 100) { | 
|---|
| 955 | set_bit(nr: ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, addr: &battery->flags); | 
|---|
| 956 | battery->full_charge_capacity = battery->design_capacity; | 
|---|
| 957 | battery->capacity_now = (battery->capacity_now * | 
|---|
| 958 | battery->full_charge_capacity) / 100; | 
|---|
| 959 | } | 
|---|
| 960 |  | 
|---|
| 961 | if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags)) | 
|---|
| 962 | return; | 
|---|
| 963 |  | 
|---|
| 964 | if (battery->power_unit && dmi_name_in_vendors(str: "LENOVO")) { | 
|---|
| 965 | const char *s; | 
|---|
| 966 |  | 
|---|
| 967 | s = dmi_get_system_info(field: DMI_PRODUCT_VERSION); | 
|---|
| 968 | if (s && !strncasecmp(s1: s, s2: "ThinkPad", n: 8)) { | 
|---|
| 969 | dmi_walk(decode: find_battery, private_data: battery); | 
|---|
| 970 | if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, | 
|---|
| 971 | &battery->flags) && | 
|---|
| 972 | battery->design_voltage) { | 
|---|
| 973 | battery->design_capacity = | 
|---|
| 974 | battery->design_capacity * | 
|---|
| 975 | 10000 / battery->design_voltage; | 
|---|
| 976 | battery->full_charge_capacity = | 
|---|
| 977 | battery->full_charge_capacity * | 
|---|
| 978 | 10000 / battery->design_voltage; | 
|---|
| 979 | battery->design_capacity_warning = | 
|---|
| 980 | battery->design_capacity_warning * | 
|---|
| 981 | 10000 / battery->design_voltage; | 
|---|
| 982 | battery->capacity_now = battery->capacity_now * | 
|---|
| 983 | 10000 / battery->design_voltage; | 
|---|
| 984 | } | 
|---|
| 985 | } | 
|---|
| 986 | } | 
|---|
| 987 |  | 
|---|
| 988 | if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags)) | 
|---|
| 989 | return; | 
|---|
| 990 |  | 
|---|
| 991 | if (acpi_battery_is_degraded(battery) && | 
|---|
| 992 | battery->capacity_now > battery->full_charge_capacity) { | 
|---|
| 993 | set_bit(nr: ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, addr: &battery->flags); | 
|---|
| 994 | battery->capacity_now = battery->full_charge_capacity; | 
|---|
| 995 | } | 
|---|
| 996 | } | 
|---|
| 997 |  | 
|---|
| 998 | static int acpi_battery_update(struct acpi_battery *battery, bool resume) | 
|---|
| 999 | { | 
|---|
| 1000 | int result = acpi_battery_get_status(battery); | 
|---|
| 1001 |  | 
|---|
| 1002 | if (result) | 
|---|
| 1003 | return result; | 
|---|
| 1004 |  | 
|---|
| 1005 | if (!acpi_battery_present(battery)) { | 
|---|
| 1006 | sysfs_remove_battery(battery); | 
|---|
| 1007 | battery->update_time = 0; | 
|---|
| 1008 | return 0; | 
|---|
| 1009 | } | 
|---|
| 1010 |  | 
|---|
| 1011 | if (resume) | 
|---|
| 1012 | return 0; | 
|---|
| 1013 |  | 
|---|
| 1014 | if (!battery->update_time) { | 
|---|
| 1015 | result = acpi_battery_get_info(battery); | 
|---|
| 1016 | if (result) | 
|---|
| 1017 | return result; | 
|---|
| 1018 | acpi_battery_init_alarm(battery); | 
|---|
| 1019 | } | 
|---|
| 1020 |  | 
|---|
| 1021 | result = acpi_battery_get_state(battery); | 
|---|
| 1022 | if (result) | 
|---|
| 1023 | return result; | 
|---|
| 1024 | acpi_battery_quirks(battery); | 
|---|
| 1025 |  | 
|---|
| 1026 | if (!battery->bat) { | 
|---|
| 1027 | result = sysfs_add_battery(battery); | 
|---|
| 1028 | if (result) | 
|---|
| 1029 | return result; | 
|---|
| 1030 | } | 
|---|
| 1031 |  | 
|---|
| 1032 | /* | 
|---|
| 1033 | * Wakeup the system if battery is critical low | 
|---|
| 1034 | * or lower than the alarm level | 
|---|
| 1035 | */ | 
|---|
| 1036 | if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) || | 
|---|
| 1037 | (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && | 
|---|
| 1038 | (battery->capacity_now <= battery->alarm))) | 
|---|
| 1039 | acpi_pm_wakeup_event(dev: &battery->device->dev); | 
|---|
| 1040 |  | 
|---|
| 1041 | return result; | 
|---|
| 1042 | } | 
|---|
| 1043 |  | 
|---|
| 1044 | static void acpi_battery_refresh(struct acpi_battery *battery) | 
|---|
| 1045 | { | 
|---|
| 1046 | int power_unit; | 
|---|
| 1047 |  | 
|---|
| 1048 | if (!battery->bat) | 
|---|
| 1049 | return; | 
|---|
| 1050 |  | 
|---|
| 1051 | power_unit = battery->power_unit; | 
|---|
| 1052 |  | 
|---|
| 1053 | acpi_battery_get_info(battery); | 
|---|
| 1054 |  | 
|---|
| 1055 | if (power_unit == battery->power_unit) | 
|---|
| 1056 | return; | 
|---|
| 1057 |  | 
|---|
| 1058 | /* The battery has changed its reporting units. */ | 
|---|
| 1059 | sysfs_remove_battery(battery); | 
|---|
| 1060 | sysfs_add_battery(battery); | 
|---|
| 1061 | } | 
|---|
| 1062 |  | 
|---|
| 1063 | /* Driver Interface */ | 
|---|
| 1064 | static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | 
|---|
| 1065 | { | 
|---|
| 1066 | struct acpi_device *device = data; | 
|---|
| 1067 | struct acpi_battery *battery = acpi_driver_data(d: device); | 
|---|
| 1068 | struct power_supply *old; | 
|---|
| 1069 |  | 
|---|
| 1070 | if (!battery) | 
|---|
| 1071 | return; | 
|---|
| 1072 |  | 
|---|
| 1073 | guard(mutex)(T: &battery->update_lock); | 
|---|
| 1074 |  | 
|---|
| 1075 | old = battery->bat; | 
|---|
| 1076 | /* | 
|---|
| 1077 | * On Acer Aspire V5-573G notifications are sometimes triggered too | 
|---|
| 1078 | * early. For example, when AC is unplugged and notification is | 
|---|
| 1079 | * triggered, battery state is still reported as "Full", and changes to | 
|---|
| 1080 | * "Discharging" only after short delay, without any notification. | 
|---|
| 1081 | */ | 
|---|
| 1082 | if (battery_notification_delay_ms > 0) | 
|---|
| 1083 | msleep(msecs: battery_notification_delay_ms); | 
|---|
| 1084 | if (event == ACPI_BATTERY_NOTIFY_INFO) | 
|---|
| 1085 | acpi_battery_refresh(battery); | 
|---|
| 1086 | acpi_battery_update(battery, resume: false); | 
|---|
| 1087 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 
|---|
| 1088 | dev_name(dev: &device->dev), event, | 
|---|
| 1089 | acpi_battery_present(battery)); | 
|---|
| 1090 | acpi_notifier_call_chain(device, event, acpi_battery_present(battery)); | 
|---|
| 1091 | /* acpi_battery_update could remove power_supply object */ | 
|---|
| 1092 | if (old && battery->bat) | 
|---|
| 1093 | power_supply_changed(psy: battery->bat); | 
|---|
| 1094 | } | 
|---|
| 1095 |  | 
|---|
| 1096 | static int battery_notify(struct notifier_block *nb, | 
|---|
| 1097 | unsigned long mode, void *_unused) | 
|---|
| 1098 | { | 
|---|
| 1099 | struct acpi_battery *battery = container_of(nb, struct acpi_battery, | 
|---|
| 1100 | pm_nb); | 
|---|
| 1101 |  | 
|---|
| 1102 | if (mode == PM_POST_SUSPEND || mode == PM_POST_HIBERNATION) { | 
|---|
| 1103 | guard(mutex)(T: &battery->update_lock); | 
|---|
| 1104 |  | 
|---|
| 1105 | if (!acpi_battery_present(battery)) | 
|---|
| 1106 | return 0; | 
|---|
| 1107 |  | 
|---|
| 1108 | if (battery->bat) { | 
|---|
| 1109 | acpi_battery_refresh(battery); | 
|---|
| 1110 | } else { | 
|---|
| 1111 | int result; | 
|---|
| 1112 |  | 
|---|
| 1113 | result = acpi_battery_get_info(battery); | 
|---|
| 1114 | if (result) | 
|---|
| 1115 | return result; | 
|---|
| 1116 |  | 
|---|
| 1117 | result = sysfs_add_battery(battery); | 
|---|
| 1118 | if (result) | 
|---|
| 1119 | return result; | 
|---|
| 1120 | } | 
|---|
| 1121 |  | 
|---|
| 1122 | acpi_battery_init_alarm(battery); | 
|---|
| 1123 | acpi_battery_get_state(battery); | 
|---|
| 1124 | } | 
|---|
| 1125 |  | 
|---|
| 1126 | return 0; | 
|---|
| 1127 | } | 
|---|
| 1128 |  | 
|---|
| 1129 | static int __init | 
|---|
| 1130 | battery_bix_broken_package_quirk(const struct dmi_system_id *d) | 
|---|
| 1131 | { | 
|---|
| 1132 | battery_bix_broken_package = 1; | 
|---|
| 1133 | return 0; | 
|---|
| 1134 | } | 
|---|
| 1135 |  | 
|---|
| 1136 | static int __init | 
|---|
| 1137 | battery_notification_delay_quirk(const struct dmi_system_id *d) | 
|---|
| 1138 | { | 
|---|
| 1139 | battery_notification_delay_ms = 1000; | 
|---|
| 1140 | return 0; | 
|---|
| 1141 | } | 
|---|
| 1142 |  | 
|---|
| 1143 | static int __init | 
|---|
| 1144 | battery_ac_is_broken_quirk(const struct dmi_system_id *d) | 
|---|
| 1145 | { | 
|---|
| 1146 | battery_ac_is_broken = 1; | 
|---|
| 1147 | return 0; | 
|---|
| 1148 | } | 
|---|
| 1149 |  | 
|---|
| 1150 | static const struct dmi_system_id bat_dmi_table[] __initconst = { | 
|---|
| 1151 | { | 
|---|
| 1152 | /* NEC LZ750/LS */ | 
|---|
| 1153 | .callback = battery_bix_broken_package_quirk, | 
|---|
| 1154 | .matches = { | 
|---|
| 1155 | DMI_MATCH(DMI_SYS_VENDOR, "NEC"), | 
|---|
| 1156 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"), | 
|---|
| 1157 | }, | 
|---|
| 1158 | }, | 
|---|
| 1159 | { | 
|---|
| 1160 | /* Acer Aspire V5-573G */ | 
|---|
| 1161 | .callback = battery_notification_delay_quirk, | 
|---|
| 1162 | .matches = { | 
|---|
| 1163 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 
|---|
| 1164 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"), | 
|---|
| 1165 | }, | 
|---|
| 1166 | }, | 
|---|
| 1167 | { | 
|---|
| 1168 | /* Point of View mobii wintab p800w */ | 
|---|
| 1169 | .callback = battery_ac_is_broken_quirk, | 
|---|
| 1170 | .matches = { | 
|---|
| 1171 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | 
|---|
| 1172 | DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), | 
|---|
| 1173 | DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"), | 
|---|
| 1174 | /* Above matches are too generic, add bios-date match */ | 
|---|
| 1175 | DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), | 
|---|
| 1176 | }, | 
|---|
| 1177 | }, | 
|---|
| 1178 | { | 
|---|
| 1179 | /* Microsoft Surface Go 3 */ | 
|---|
| 1180 | .callback = battery_notification_delay_quirk, | 
|---|
| 1181 | .matches = { | 
|---|
| 1182 | DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), | 
|---|
| 1183 | DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"), | 
|---|
| 1184 | }, | 
|---|
| 1185 | }, | 
|---|
| 1186 | {}, | 
|---|
| 1187 | }; | 
|---|
| 1188 |  | 
|---|
| 1189 | /* | 
|---|
| 1190 | * Some machines'(E,G Lenovo Z480) ECs are not stable | 
|---|
| 1191 | * during boot up and this causes battery driver fails to be | 
|---|
| 1192 | * probed due to failure of getting battery information | 
|---|
| 1193 | * from EC sometimes. After several retries, the operation | 
|---|
| 1194 | * may work. So add retry code here and 20ms sleep between | 
|---|
| 1195 | * every retries. | 
|---|
| 1196 | */ | 
|---|
| 1197 | static int acpi_battery_update_retry(struct acpi_battery *battery) | 
|---|
| 1198 | { | 
|---|
| 1199 | int retry, ret; | 
|---|
| 1200 |  | 
|---|
| 1201 | guard(mutex)(T: &battery->update_lock); | 
|---|
| 1202 |  | 
|---|
| 1203 | for (retry = 5; retry; retry--) { | 
|---|
| 1204 | ret = acpi_battery_update(battery, resume: false); | 
|---|
| 1205 | if (!ret) | 
|---|
| 1206 | break; | 
|---|
| 1207 |  | 
|---|
| 1208 | msleep(msecs: 20); | 
|---|
| 1209 | } | 
|---|
| 1210 | return ret; | 
|---|
| 1211 | } | 
|---|
| 1212 |  | 
|---|
| 1213 | static void sysfs_battery_cleanup(struct acpi_battery *battery) | 
|---|
| 1214 | { | 
|---|
| 1215 | guard(mutex)(T: &battery->update_lock); | 
|---|
| 1216 |  | 
|---|
| 1217 | sysfs_remove_battery(battery); | 
|---|
| 1218 | } | 
|---|
| 1219 |  | 
|---|
| 1220 | static int acpi_battery_add(struct acpi_device *device) | 
|---|
| 1221 | { | 
|---|
| 1222 | int result = 0; | 
|---|
| 1223 | struct acpi_battery *battery; | 
|---|
| 1224 |  | 
|---|
| 1225 | if (!device) | 
|---|
| 1226 | return -EINVAL; | 
|---|
| 1227 |  | 
|---|
| 1228 | if (device->dep_unmet) | 
|---|
| 1229 | return -EPROBE_DEFER; | 
|---|
| 1230 |  | 
|---|
| 1231 | battery = devm_kzalloc(dev: &device->dev, size: sizeof(*battery), GFP_KERNEL); | 
|---|
| 1232 | if (!battery) | 
|---|
| 1233 | return -ENOMEM; | 
|---|
| 1234 | battery->device = device; | 
|---|
| 1235 | strscpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); | 
|---|
| 1236 | strscpy(acpi_device_class(device), ACPI_BATTERY_CLASS); | 
|---|
| 1237 | device->driver_data = battery; | 
|---|
| 1238 | result = devm_mutex_init(&device->dev, &battery->lock); | 
|---|
| 1239 | if (result) | 
|---|
| 1240 | return result; | 
|---|
| 1241 |  | 
|---|
| 1242 | result = devm_mutex_init(&device->dev, &battery->update_lock); | 
|---|
| 1243 | if (result) | 
|---|
| 1244 | return result; | 
|---|
| 1245 |  | 
|---|
| 1246 | if (acpi_has_method(handle: battery->device->handle, name: "_BIX")) | 
|---|
| 1247 | set_bit(nr: ACPI_BATTERY_XINFO_PRESENT, addr: &battery->flags); | 
|---|
| 1248 |  | 
|---|
| 1249 | result = acpi_battery_update_retry(battery); | 
|---|
| 1250 | if (result) | 
|---|
| 1251 | goto fail; | 
|---|
| 1252 |  | 
|---|
| 1253 | pr_info( "Slot [%s] (battery %s)\n", acpi_device_bid(device), | 
|---|
| 1254 | device->status.battery_present ? "present": "absent"); | 
|---|
| 1255 |  | 
|---|
| 1256 | battery->pm_nb.notifier_call = battery_notify; | 
|---|
| 1257 | result = register_pm_notifier(nb: &battery->pm_nb); | 
|---|
| 1258 | if (result) | 
|---|
| 1259 | goto fail; | 
|---|
| 1260 |  | 
|---|
| 1261 | device_init_wakeup(dev: &device->dev, enable: 1); | 
|---|
| 1262 |  | 
|---|
| 1263 | result = acpi_dev_install_notify_handler(adev: device, ACPI_ALL_NOTIFY, | 
|---|
| 1264 | handler: acpi_battery_notify, context: device); | 
|---|
| 1265 | if (result) | 
|---|
| 1266 | goto fail_pm; | 
|---|
| 1267 |  | 
|---|
| 1268 | return 0; | 
|---|
| 1269 |  | 
|---|
| 1270 | fail_pm: | 
|---|
| 1271 | device_init_wakeup(dev: &device->dev, enable: 0); | 
|---|
| 1272 | unregister_pm_notifier(nb: &battery->pm_nb); | 
|---|
| 1273 | fail: | 
|---|
| 1274 | sysfs_battery_cleanup(battery); | 
|---|
| 1275 |  | 
|---|
| 1276 | return result; | 
|---|
| 1277 | } | 
|---|
| 1278 |  | 
|---|
| 1279 | static void acpi_battery_remove(struct acpi_device *device) | 
|---|
| 1280 | { | 
|---|
| 1281 | struct acpi_battery *battery; | 
|---|
| 1282 |  | 
|---|
| 1283 | if (!device || !acpi_driver_data(d: device)) | 
|---|
| 1284 | return; | 
|---|
| 1285 |  | 
|---|
| 1286 | battery = acpi_driver_data(d: device); | 
|---|
| 1287 |  | 
|---|
| 1288 | acpi_dev_remove_notify_handler(adev: device, ACPI_ALL_NOTIFY, | 
|---|
| 1289 | handler: acpi_battery_notify); | 
|---|
| 1290 |  | 
|---|
| 1291 | device_init_wakeup(dev: &device->dev, enable: 0); | 
|---|
| 1292 | unregister_pm_notifier(nb: &battery->pm_nb); | 
|---|
| 1293 |  | 
|---|
| 1294 | guard(mutex)(T: &battery->update_lock); | 
|---|
| 1295 |  | 
|---|
| 1296 | sysfs_remove_battery(battery); | 
|---|
| 1297 | } | 
|---|
| 1298 |  | 
|---|
| 1299 | /* this is needed to learn about changes made in suspended state */ | 
|---|
| 1300 | static int acpi_battery_resume(struct device *dev) | 
|---|
| 1301 | { | 
|---|
| 1302 | struct acpi_battery *battery; | 
|---|
| 1303 |  | 
|---|
| 1304 | if (!dev) | 
|---|
| 1305 | return -EINVAL; | 
|---|
| 1306 |  | 
|---|
| 1307 | battery = acpi_driver_data(to_acpi_device(dev)); | 
|---|
| 1308 | if (!battery) | 
|---|
| 1309 | return -EINVAL; | 
|---|
| 1310 |  | 
|---|
| 1311 | battery->update_time = 0; | 
|---|
| 1312 |  | 
|---|
| 1313 | guard(mutex)(T: &battery->update_lock); | 
|---|
| 1314 |  | 
|---|
| 1315 | acpi_battery_update(battery, resume: true); | 
|---|
| 1316 | return 0; | 
|---|
| 1317 | } | 
|---|
| 1318 |  | 
|---|
| 1319 | static DEFINE_SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume); | 
|---|
| 1320 |  | 
|---|
| 1321 | static struct acpi_driver acpi_battery_driver = { | 
|---|
| 1322 | .name = "battery", | 
|---|
| 1323 | .class = ACPI_BATTERY_CLASS, | 
|---|
| 1324 | .ids = battery_device_ids, | 
|---|
| 1325 | .ops = { | 
|---|
| 1326 | .add = acpi_battery_add, | 
|---|
| 1327 | .remove = acpi_battery_remove, | 
|---|
| 1328 | }, | 
|---|
| 1329 | .drv.pm = pm_sleep_ptr(&acpi_battery_pm), | 
|---|
| 1330 | .drv.probe_type = PROBE_PREFER_ASYNCHRONOUS, | 
|---|
| 1331 | }; | 
|---|
| 1332 |  | 
|---|
| 1333 | static int __init acpi_battery_init(void) | 
|---|
| 1334 | { | 
|---|
| 1335 | if (acpi_disabled || acpi_quirk_skip_acpi_ac_and_battery()) | 
|---|
| 1336 | return -ENODEV; | 
|---|
| 1337 |  | 
|---|
| 1338 | dmi_check_system(list: bat_dmi_table); | 
|---|
| 1339 |  | 
|---|
| 1340 | return acpi_bus_register_driver(&acpi_battery_driver); | 
|---|
| 1341 | } | 
|---|
| 1342 |  | 
|---|
| 1343 | static void __exit acpi_battery_exit(void) | 
|---|
| 1344 | { | 
|---|
| 1345 | acpi_bus_unregister_driver(driver: &acpi_battery_driver); | 
|---|
| 1346 | battery_hook_exit(); | 
|---|
| 1347 | } | 
|---|
| 1348 |  | 
|---|
| 1349 | module_init(acpi_battery_init); | 
|---|
| 1350 | module_exit(acpi_battery_exit); | 
|---|
| 1351 |  | 
|---|