--- zzzz-none-000/linux-3.10.107/drivers/acpi/sbs.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/acpi/sbs.c 2021-02-04 17:41:59.000000000 +0000 @@ -17,10 +17,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -30,25 +26,20 @@ #include #include -#ifdef CONFIG_ACPI_PROCFS_POWER -#include -#include -#include -#endif - #include #include #include #include #include +#include #include "sbshc.h" +#include "battery.h" #define PREFIX "ACPI: " #define ACPI_SBS_CLASS "sbs" #define ACPI_AC_CLASS "ac_adapter" -#define ACPI_BATTERY_CLASS "battery" #define ACPI_SBS_DEVICE_NAME "Smart Battery System" #define ACPI_SBS_FILE_INFO "info" #define ACPI_SBS_FILE_STATE "state" @@ -67,10 +58,7 @@ module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -extern struct proc_dir_entry *acpi_lock_ac_dir(void); -extern struct proc_dir_entry *acpi_lock_battery_dir(void); -extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); -extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); +static bool sbs_manager_broken; #define MAX_SBS_BAT 4 #define ACPI_SBS_BLOCK_MAX 32 @@ -82,11 +70,9 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids); struct acpi_battery { - struct power_supply bat; + struct power_supply *bat; + struct power_supply_desc bat_desc; struct acpi_sbs *sbs; -#ifdef CONFIG_ACPI_PROCFS_POWER - struct proc_dir_entry *proc_entry; -#endif unsigned long update_time; char name[8]; char manufacturer_name[ACPI_SBS_BLOCK_MAX]; @@ -112,23 +98,21 @@ u8 have_sysfs_alarm:1; }; -#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat) +#define to_acpi_battery(x) power_supply_get_drvdata(x) struct acpi_sbs { - struct power_supply charger; + struct power_supply *charger; struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex lock; -#ifdef CONFIG_ACPI_PROCFS_POWER - struct proc_dir_entry *charger_entry; -#endif struct acpi_battery battery[MAX_SBS_BAT]; u8 batteries_supported:4; u8 manager_present:1; u8 charger_present:1; + u8 charger_exists:1; }; -#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) +#define to_acpi_sbs(x) power_supply_get_drvdata(x) static int acpi_sbs_remove(struct acpi_device *device); static int acpi_battery_get_state(struct acpi_battery *battery); @@ -316,6 +300,13 @@ POWER_SUPPLY_PROP_MANUFACTURER, }; +static const struct power_supply_desc acpi_sbs_charger_desc = { + .name = "sbs-charger", + .type = POWER_SUPPLY_TYPE_MAINS, + .properties = sbs_ac_props, + .num_properties = ARRAY_SIZE(sbs_ac_props), + .get_property = sbs_get_ac_property, +}; /* -------------------------------------------------------------------------- Smart Battery System Management @@ -446,9 +437,19 @@ result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, 0x13, (u8 *) & status); - if (!result) - sbs->charger_present = (status >> 15) & 0x1; - return result; + + if (result) + return result; + + /* + * The spec requires that bit 4 always be 1. If it's not set, assume + * that the implementation doesn't support an SBS charger + */ + if (!((status >> 4) & 0x1)) + return -ENODEV; + + sbs->charger_present = (status >> 15) & 0x1; + return 0; } static ssize_t acpi_battery_alarm_show(struct device *dev, @@ -467,7 +468,7 @@ { unsigned long x; struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); - if (sscanf(buf, "%ld\n", &x) == 1) + if (sscanf(buf, "%lu\n", &x) == 1) battery->alarm_capacity = x / (1000 * acpi_battery_scale(battery)); if (battery->present) @@ -482,261 +483,6 @@ }; /* -------------------------------------------------------------------------- - FS Interface (/proc/acpi) - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_PROCFS_POWER -/* Generic Routines */ -static int -acpi_sbs_add_fs(struct proc_dir_entry **dir, - struct proc_dir_entry *parent_dir, - char *dir_name, - const struct file_operations *info_fops, - const struct file_operations *state_fops, - const struct file_operations *alarm_fops, void *data) -{ - printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded," - " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); - if (!*dir) { - *dir = proc_mkdir(dir_name, parent_dir); - if (!*dir) { - return -ENODEV; - } - } - - /* 'info' [R] */ - if (info_fops) - proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir, - info_fops, data); - - /* 'state' [R] */ - if (state_fops) - proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir, - state_fops, data); - - /* 'alarm' [R/W] */ - if (alarm_fops) - proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir, - alarm_fops, data); - return 0; -} - -/* Smart Battery Interface */ -static struct proc_dir_entry *acpi_battery_dir = NULL; - -static inline char *acpi_battery_units(struct acpi_battery *battery) -{ - return acpi_battery_mode(battery) ? " mW" : " mA"; -} - - -static int acpi_battery_read_info(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int result = 0; - - mutex_lock(&sbs->lock); - - seq_printf(seq, "present: %s\n", - (battery->present) ? "yes" : "no"); - if (!battery->present) - goto end; - - seq_printf(seq, "design capacity: %i%sh\n", - battery->design_capacity * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "last full capacity: %i%sh\n", - battery->full_charge_capacity * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "battery technology: rechargeable\n"); - seq_printf(seq, "design voltage: %i mV\n", - battery->design_voltage * acpi_battery_vscale(battery)); - seq_printf(seq, "design capacity warning: unknown\n"); - seq_printf(seq, "design capacity low: unknown\n"); - seq_printf(seq, "cycle count: %i\n", battery->cycle_count); - seq_printf(seq, "capacity granularity 1: unknown\n"); - seq_printf(seq, "capacity granularity 2: unknown\n"); - seq_printf(seq, "model number: %s\n", battery->device_name); - seq_printf(seq, "serial number: %i\n", - battery->serial_number); - seq_printf(seq, "battery type: %s\n", - battery->device_chemistry); - seq_printf(seq, "OEM info: %s\n", - battery->manufacturer_name); - end: - mutex_unlock(&sbs->lock); - return result; -} - -static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_info, PDE_DATA(inode)); -} - -static int acpi_battery_read_state(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int rate; - - mutex_lock(&sbs->lock); - seq_printf(seq, "present: %s\n", - (battery->present) ? "yes" : "no"); - if (!battery->present) - goto end; - - acpi_battery_get_state(battery); - seq_printf(seq, "capacity state: %s\n", - (battery->state & 0x0010) ? "critical" : "ok"); - seq_printf(seq, "charging state: %s\n", - (battery->rate_now < 0) ? "discharging" : - ((battery->rate_now > 0) ? "charging" : "charged")); - rate = abs(battery->rate_now) * acpi_battery_ipscale(battery); - rate *= (acpi_battery_mode(battery))?(battery->voltage_now * - acpi_battery_vscale(battery)/1000):1; - seq_printf(seq, "present rate: %d%s\n", rate, - acpi_battery_units(battery)); - seq_printf(seq, "remaining capacity: %i%sh\n", - battery->capacity_now * acpi_battery_scale(battery), - acpi_battery_units(battery)); - seq_printf(seq, "present voltage: %i mV\n", - battery->voltage_now * acpi_battery_vscale(battery)); - - end: - mutex_unlock(&sbs->lock); - return 0; -} - -static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_state, PDE_DATA(inode)); -} - -static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - int result = 0; - - mutex_lock(&sbs->lock); - - if (!battery->present) { - seq_printf(seq, "present: no\n"); - goto end; - } - - acpi_battery_get_alarm(battery); - seq_printf(seq, "alarm: "); - if (battery->alarm_capacity) - seq_printf(seq, "%i%sh\n", - battery->alarm_capacity * - acpi_battery_scale(battery), - acpi_battery_units(battery)); - else - seq_printf(seq, "disabled\n"); - end: - mutex_unlock(&sbs->lock); - return result; -} - -static ssize_t -acpi_battery_write_alarm(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) -{ - struct seq_file *seq = file->private_data; - struct acpi_battery *battery = seq->private; - struct acpi_sbs *sbs = battery->sbs; - char alarm_string[12] = { '\0' }; - int result = 0; - mutex_lock(&sbs->lock); - if (!battery->present) { - result = -ENODEV; - goto end; - } - if (count > sizeof(alarm_string) - 1) { - result = -EINVAL; - goto end; - } - if (copy_from_user(alarm_string, buffer, count)) { - result = -EFAULT; - goto end; - } - alarm_string[count] = 0; - battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) / - acpi_battery_scale(battery); - acpi_battery_set_alarm(battery); - end: - mutex_unlock(&sbs->lock); - if (result) - return result; - return count; -} - -static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_alarm, PDE_DATA(inode)); -} - -static const struct file_operations acpi_battery_info_fops = { - .open = acpi_battery_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations acpi_battery_state_fops = { - .open = acpi_battery_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations acpi_battery_alarm_fops = { - .open = acpi_battery_alarm_open_fs, - .read = seq_read, - .write = acpi_battery_write_alarm, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -/* Legacy AC Adapter Interface */ - -static struct proc_dir_entry *acpi_ac_dir = NULL; - -static int acpi_ac_read_state(struct seq_file *seq, void *offset) -{ - - struct acpi_sbs *sbs = seq->private; - - mutex_lock(&sbs->lock); - - seq_printf(seq, "state: %s\n", - sbs->charger_present ? "on-line" : "off-line"); - - mutex_unlock(&sbs->lock); - return 0; -} - -static int acpi_ac_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_ac_read_state, PDE_DATA(inode)); -} - -static const struct file_operations acpi_ac_state_fops = { - .open = acpi_ac_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -#endif - -/* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ static int acpi_battery_read(struct acpi_battery *battery) @@ -755,16 +501,21 @@ ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); } else if (battery->id == 0) battery->present = 1; + if (result || !battery->present) return result; if (saved_present != battery->present) { battery->update_time = 0; result = acpi_battery_get_info(battery); - if (result) + if (result) { + battery->present = 0; return result; + } } result = acpi_battery_get_state(battery); + if (result) + battery->present = 0; return result; } @@ -772,6 +523,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) { struct acpi_battery *battery = &sbs->battery[id]; + struct power_supply_config psy_cfg = { .drv_data = battery, }; int result; battery->id = id; @@ -781,28 +533,27 @@ return result; sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, - battery->name, &acpi_battery_info_fops, - &acpi_battery_state_fops, &acpi_battery_alarm_fops, - battery); -#endif - battery->bat.name = battery->name; - battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; + battery->bat_desc.name = battery->name; + battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY; if (!acpi_battery_mode(battery)) { - battery->bat.properties = sbs_charge_battery_props; - battery->bat.num_properties = + battery->bat_desc.properties = sbs_charge_battery_props; + battery->bat_desc.num_properties = ARRAY_SIZE(sbs_charge_battery_props); } else { - battery->bat.properties = sbs_energy_battery_props; - battery->bat.num_properties = + battery->bat_desc.properties = sbs_energy_battery_props; + battery->bat_desc.num_properties = ARRAY_SIZE(sbs_energy_battery_props); } - battery->bat.get_property = acpi_sbs_battery_get_property; - result = power_supply_register(&sbs->device->dev, &battery->bat); - if (result) + battery->bat_desc.get_property = acpi_sbs_battery_get_property; + battery->bat = power_supply_register(&sbs->device->dev, + &battery->bat_desc, &psy_cfg); + if (IS_ERR(battery->bat)) { + result = PTR_ERR(battery->bat); + battery->bat = NULL; goto end; - result = device_create_file(battery->bat.dev, &alarm_attr); + } + + result = device_create_file(&battery->bat->dev, &alarm_attr); if (result) goto end; battery->have_sysfs_alarm = 1; @@ -817,37 +568,29 @@ { struct acpi_battery *battery = &sbs->battery[id]; - if (battery->bat.dev) { + if (battery->bat) { if (battery->have_sysfs_alarm) - device_remove_file(battery->bat.dev, &alarm_attr); - power_supply_unregister(&battery->bat); + device_remove_file(&battery->bat->dev, &alarm_attr); + power_supply_unregister(battery->bat); } -#ifdef CONFIG_ACPI_PROCFS_POWER - proc_remove(battery->proc_entry); - battery->proc_entry = NULL; -#endif } static int acpi_charger_add(struct acpi_sbs *sbs) { int result; + struct power_supply_config psy_cfg = { .drv_data = sbs, }; result = acpi_ac_get_present(sbs); if (result) goto end; -#ifdef CONFIG_ACPI_PROCFS_POWER - result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, - ACPI_AC_DIR_NAME, NULL, - &acpi_ac_state_fops, NULL, sbs); - if (result) - goto end; -#endif - sbs->charger.name = "sbs-charger"; - sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; - sbs->charger.properties = sbs_ac_props; - sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); - sbs->charger.get_property = sbs_get_ac_property; - power_supply_register(&sbs->device->dev, &sbs->charger); + + sbs->charger_exists = 1; + sbs->charger = power_supply_register(&sbs->device->dev, + &acpi_sbs_charger_desc, &psy_cfg); + if (IS_ERR(sbs->charger)) { + result = PTR_ERR(sbs->charger); + sbs->charger = NULL; + } printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); @@ -857,12 +600,8 @@ static void acpi_charger_remove(struct acpi_sbs *sbs) { - if (sbs->charger.dev) - power_supply_unregister(&sbs->charger); -#ifdef CONFIG_ACPI_PROCFS_POWER - proc_remove(sbs->charger_entry); - sbs->charger_entry = NULL; -#endif + if (sbs->charger) + power_supply_unregister(sbs->charger); } static void acpi_sbs_callback(void *context) @@ -872,15 +611,13 @@ struct acpi_battery *bat; u8 saved_charger_state = sbs->charger_present; u8 saved_battery_state; - acpi_ac_get_present(sbs); - if (sbs->charger_present != saved_charger_state) { -#ifdef CONFIG_ACPI_PROC_EVENT - acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, - ACPI_SBS_NOTIFY_STATUS, - sbs->charger_present); -#endif - kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); + + if (sbs->charger_exists) { + acpi_ac_get_present(sbs); + if (sbs->charger_present != saved_charger_state) + kobject_uevent(&sbs->charger->dev.kobj, KOBJ_CHANGE); } + if (sbs->manager_present) { for (id = 0; id < MAX_SBS_BAT; ++id) { if (!(sbs->batteries_supported & (1 << id))) @@ -890,23 +627,36 @@ acpi_battery_read(bat); if (saved_battery_state == bat->present) continue; -#ifdef CONFIG_ACPI_PROC_EVENT - acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, - bat->name, - ACPI_SBS_NOTIFY_STATUS, - bat->present); -#endif - kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); + kobject_uevent(&bat->bat->dev.kobj, KOBJ_CHANGE); } } } +static int disable_sbs_manager(const struct dmi_system_id *d) +{ + sbs_manager_broken = true; + return 0; +} + +static struct dmi_system_id acpi_sbs_dmi_table[] = { + { + .callback = disable_sbs_manager, + .ident = "Apple", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc.") + }, + }, + { }, +}; + static int acpi_sbs_add(struct acpi_device *device) { struct acpi_sbs *sbs; int result = 0; int id; + dmi_check_system(acpi_sbs_dmi_table); + sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); if (!sbs) { result = -ENOMEM; @@ -922,17 +672,24 @@ device->driver_data = sbs; result = acpi_charger_add(sbs); - if (result) + if (result && result != -ENODEV) goto end; - result = acpi_manager_get_info(sbs); - if (!result) { - sbs->manager_present = 1; - for (id = 0; id < MAX_SBS_BAT; ++id) - if ((sbs->batteries_supported & (1 << id))) - acpi_battery_add(sbs, id); - } else + result = 0; + + if (!sbs_manager_broken) { + result = acpi_manager_get_info(sbs); + if (!result) { + sbs->manager_present = 1; + for (id = 0; id < MAX_SBS_BAT; ++id) + if ((sbs->batteries_supported & (1 << id))) + acpi_battery_add(sbs, id); + } + } + + if (!sbs->manager_present) acpi_battery_add(sbs, 0); + acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); end: if (result) @@ -961,20 +718,6 @@ return 0; } -static void acpi_sbs_rmdirs(void) -{ -#ifdef CONFIG_ACPI_PROCFS_POWER - if (acpi_ac_dir) { - acpi_unlock_ac_dir(acpi_ac_dir); - acpi_ac_dir = NULL; - } - if (acpi_battery_dir) { - acpi_unlock_battery_dir(acpi_battery_dir); - acpi_battery_dir = NULL; - } -#endif -} - #ifdef CONFIG_PM_SLEEP static int acpi_sbs_resume(struct device *dev) { @@ -985,6 +728,8 @@ acpi_sbs_callback(sbs); return 0; } +#else +#define acpi_sbs_resume NULL #endif static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume); @@ -1006,28 +751,17 @@ if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS_POWER - acpi_ac_dir = acpi_lock_ac_dir(); - if (!acpi_ac_dir) - return -ENODEV; - acpi_battery_dir = acpi_lock_battery_dir(); - if (!acpi_battery_dir) { - acpi_sbs_rmdirs(); - return -ENODEV; - } -#endif + result = acpi_bus_register_driver(&acpi_sbs_driver); - if (result < 0) { - acpi_sbs_rmdirs(); + if (result < 0) return -ENODEV; - } + return 0; } static void __exit acpi_sbs_exit(void) { acpi_bus_unregister_driver(&acpi_sbs_driver); - acpi_sbs_rmdirs(); return; }