Przeglądaj źródła

Merge branches 'bugzilla-15807', 'bugzilla-15979-v2' and 'bugzilla-19162' into release

Len Brown 14 lat temu
rodzic
commit
38add9b4ba

+ 1 - 0
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c

@@ -701,6 +701,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 		per_cpu(acfreq_data, policy->cpu) = NULL;
 		per_cpu(acfreq_data, policy->cpu) = NULL;
 		acpi_processor_unregister_performance(data->acpi_data,
 		acpi_processor_unregister_performance(data->acpi_data,
 						      policy->cpu);
 						      policy->cpu);
+		kfree(data->freq_table);
 		kfree(data);
 		kfree(data);
 	}
 	}
 
 

+ 37 - 1
drivers/acpi/battery.c

@@ -95,6 +95,7 @@ enum {
 	 * due to bad math.
 	 * due to bad math.
 	 */
 	 */
 	ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
 	ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
+	ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
 };
 };
 
 
 struct acpi_battery {
 struct acpi_battery {
@@ -405,6 +406,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
 		result = extract_package(battery, buffer.pointer,
 		result = extract_package(battery, buffer.pointer,
 				info_offsets, ARRAY_SIZE(info_offsets));
 				info_offsets, ARRAY_SIZE(info_offsets));
 	kfree(buffer.pointer);
 	kfree(buffer.pointer);
+	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
+		battery->full_charge_capacity = battery->design_capacity;
 	return result;
 	return result;
 }
 }
 
 
@@ -441,6 +444,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
 	    battery->rate_now != -1)
 	    battery->rate_now != -1)
 		battery->rate_now = abs((s16)battery->rate_now);
 		battery->rate_now = abs((s16)battery->rate_now);
 
 
+	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
+	    && battery->capacity_now >= 0 && battery->capacity_now <= 100)
+		battery->capacity_now = (battery->capacity_now *
+				battery->full_charge_capacity) / 100;
 	return result;
 	return result;
 }
 }
 
 
@@ -552,6 +559,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
 	}
 	}
 }
 }
 
 
+/*
+ * According to the ACPI spec, some kinds of primary batteries can
+ * report percentage battery remaining capacity directly to OS.
+ * In this case, it reports the Last Full Charged Capacity == 100
+ * and BatteryPresentRate == 0xFFFFFFFF.
+ *
+ * Now we found some battery reports percentage remaining capacity
+ * even if it's rechargeable.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=15979
+ *
+ * Handle this correctly so that they won't break userspace.
+ */
+static void acpi_battery_quirks2(struct acpi_battery *battery)
+{
+	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
+		return ;
+
+        if (battery->full_charge_capacity == 100 &&
+            battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
+            battery->capacity_now >=0 && battery->capacity_now <= 100) {
+		set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
+		battery->full_charge_capacity = battery->design_capacity;
+		battery->capacity_now = (battery->capacity_now *
+				battery->full_charge_capacity) / 100;
+	}
+}
+
 static int acpi_battery_update(struct acpi_battery *battery)
 static int acpi_battery_update(struct acpi_battery *battery)
 {
 {
 	int result, old_present = acpi_battery_present(battery);
 	int result, old_present = acpi_battery_present(battery);
@@ -573,7 +607,9 @@ static int acpi_battery_update(struct acpi_battery *battery)
 	}
 	}
 	if (!battery->bat.dev)
 	if (!battery->bat.dev)
 		sysfs_add_battery(battery);
 		sysfs_add_battery(battery);
-	return acpi_battery_get_state(battery);
+	result = acpi_battery_get_state(battery);
+	acpi_battery_quirks2(battery);
+	return result;
 }
 }
 
 
 /* --------------------------------------------------------------------------
 /* --------------------------------------------------------------------------

+ 2 - 2
drivers/acpi/button.c

@@ -338,7 +338,8 @@ static int acpi_button_add(struct acpi_device *device)
 {
 {
 	struct acpi_button *button;
 	struct acpi_button *button;
 	struct input_dev *input;
 	struct input_dev *input;
-	char *hid, *name, *class;
+	const char *hid = acpi_device_hid(device);
+	char *name, *class;
 	int error;
 	int error;
 
 
 	button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
 	button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
@@ -353,7 +354,6 @@ static int acpi_button_add(struct acpi_device *device)
 		goto err_free_button;
 		goto err_free_button;
 	}
 	}
 
 
-	hid = acpi_device_hid(device);
 	name = acpi_device_name(device);
 	name = acpi_device_name(device);
 	class = acpi_device_class(device);
 	class = acpi_device_class(device);
 
 

+ 20 - 17
drivers/acpi/scan.c

@@ -26,6 +26,8 @@ extern struct acpi_device *acpi_root;
 
 
 #define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
 #define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
 
 
+static const char *dummy_hid = "device";
+
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 static LIST_HEAD(acpi_bus_id_list);
 DEFINE_MUTEX(acpi_device_lock);
 DEFINE_MUTEX(acpi_device_lock);
@@ -49,6 +51,9 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
 	int count;
 	int count;
 	struct acpi_hardware_id *id;
 	struct acpi_hardware_id *id;
 
 
+	if (list_empty(&acpi_dev->pnp.ids))
+		return 0;
+
 	len = snprintf(modalias, size, "acpi:");
 	len = snprintf(modalias, size, "acpi:");
 	size -= len;
 	size -= len;
 
 
@@ -202,13 +207,15 @@ static int acpi_device_setup_files(struct acpi_device *dev)
 			goto end;
 			goto end;
 	}
 	}
 
 
-	result = device_create_file(&dev->dev, &dev_attr_hid);
-	if (result)
-		goto end;
+	if (!list_empty(&dev->pnp.ids)) {
+		result = device_create_file(&dev->dev, &dev_attr_hid);
+		if (result)
+			goto end;
 
 
-	result = device_create_file(&dev->dev, &dev_attr_modalias);
-	if (result)
-		goto end;
+		result = device_create_file(&dev->dev, &dev_attr_modalias);
+		if (result)
+			goto end;
+	}
 
 
         /*
         /*
          * If device has _EJ0, 'eject' file is created that is used to trigger
          * If device has _EJ0, 'eject' file is created that is used to trigger
@@ -316,6 +323,9 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	int len;
 	int len;
 
 
+	if (list_empty(&acpi_dev->pnp.ids))
+		return 0;
+
 	if (add_uevent_var(env, "MODALIAS="))
 	if (add_uevent_var(env, "MODALIAS="))
 		return -ENOMEM;
 		return -ENOMEM;
 	len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
 	len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
@@ -1010,10 +1020,13 @@ static int acpi_dock_match(struct acpi_device *device)
 	return acpi_get_handle(device->handle, "_DCK", &tmp);
 	return acpi_get_handle(device->handle, "_DCK", &tmp);
 }
 }
 
 
-char *acpi_device_hid(struct acpi_device *device)
+const char *acpi_device_hid(struct acpi_device *device)
 {
 {
 	struct acpi_hardware_id *hid;
 	struct acpi_hardware_id *hid;
 
 
+	if (list_empty(&device->pnp.ids))
+		return dummy_hid;
+
 	hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
 	hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
 	return hid->id;
 	return hid->id;
 }
 }
@@ -1142,16 +1155,6 @@ static void acpi_device_set_id(struct acpi_device *device)
 		acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
 		acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
 		break;
 		break;
 	}
 	}
-
-	/*
-	 * We build acpi_devices for some objects that don't have _HID or _CID,
-	 * e.g., PCI bridges and slots.  Drivers can't bind to these objects,
-	 * but we do use them indirectly by traversing the acpi_device tree.
-	 * This generic ID isn't useful for driver binding, but it provides
-	 * the useful property that "every acpi_device has an ID."
-	 */
-	if (list_empty(&device->pnp.ids))
-		acpi_add_id(device, "device");
 }
 }
 
 
 static int acpi_device_set_context(struct acpi_device *device)
 static int acpi_device_set_context(struct acpi_device *device)

+ 3 - 2
drivers/pnp/base.h

@@ -12,11 +12,12 @@ void pnp_unregister_protocol(struct pnp_protocol *protocol);
 
 
 #define PNP_EISA_ID_MASK 0x7fffffff
 #define PNP_EISA_ID_MASK 0x7fffffff
 void pnp_eisa_id_to_string(u32 id, char *str);
 void pnp_eisa_id_to_string(u32 id, char *str);
-struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid);
+struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id,
+			      const char *pnpid);
 struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
 struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
 
 
 int pnp_add_device(struct pnp_dev *dev);
 int pnp_add_device(struct pnp_dev *dev);
-struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
+struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id);
 
 
 int pnp_add_card(struct pnp_card *card);
 int pnp_add_card(struct pnp_card *card);
 void pnp_remove_card(struct pnp_card *card);
 void pnp_remove_card(struct pnp_card *card);

+ 2 - 1
drivers/pnp/core.c

@@ -124,7 +124,8 @@ static void pnp_release_device(struct device *dmdev)
 	kfree(dev);
 	kfree(dev);
 }
 }
 
 
-struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid)
+struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id,
+			      const char *pnpid)
 {
 {
 	struct pnp_dev *dev;
 	struct pnp_dev *dev;
 	struct pnp_id *dev_id;
 	struct pnp_id *dev_id;

+ 1 - 1
drivers/pnp/driver.c

@@ -236,7 +236,7 @@ void pnp_unregister_driver(struct pnp_driver *drv)
  * @dev: pointer to the desired device
  * @dev: pointer to the desired device
  * @id: pointer to an EISA id string
  * @id: pointer to an EISA id string
  */
  */
-struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id)
+struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id)
 {
 {
 	struct pnp_id *dev_id, *ptr;
 	struct pnp_id *dev_id, *ptr;
 
 

+ 1 - 1
drivers/pnp/pnpacpi/core.c

@@ -59,7 +59,7 @@ static inline int __init is_exclusive_device(struct acpi_device *dev)
 #define TEST_ALPHA(c) \
 #define TEST_ALPHA(c) \
 	if (!('@' <= (c) || (c) <= 'Z')) \
 	if (!('@' <= (c) || (c) <= 'Z')) \
 		return 0
 		return 0
-static int __init ispnpidacpi(char *id)
+static int __init ispnpidacpi(const char *id)
 {
 {
 	TEST_ALPHA(id[0]);
 	TEST_ALPHA(id[0]);
 	TEST_ALPHA(id[1]);
 	TEST_ALPHA(id[1]);

+ 1 - 1
include/acpi/acpi_bus.h

@@ -184,7 +184,7 @@ struct acpi_device_pnp {
 
 
 #define acpi_device_bid(d)	((d)->pnp.bus_id)
 #define acpi_device_bid(d)	((d)->pnp.bus_id)
 #define acpi_device_adr(d)	((d)->pnp.bus_address)
 #define acpi_device_adr(d)	((d)->pnp.bus_address)
-char *acpi_device_hid(struct acpi_device *device);
+const char *acpi_device_hid(struct acpi_device *device);
 #define acpi_device_name(d)	((d)->pnp.device_name)
 #define acpi_device_name(d)	((d)->pnp.device_name)
 #define acpi_device_class(d)	((d)->pnp.device_class)
 #define acpi_device_class(d)	((d)->pnp.device_class)