Re: [PATCH 01/15] ACPI: thinkpad-acpi: refactor hotkey_get and hotkey_set

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

 



> This patch:

a nit to prove that I read this before dumping it into my test branch...

the "perfect patch" never refers to itself as a patch
in its check-in comments -- since by the time it is checked
in, it is sort of self-evident it is a patch:-)

http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt

> 1. Splits hotkey_get/set into hotkey_status_get/set and hotkey_mask_get/set;

Split...

> 2. Caches the status of hot key mask for later driver use;

Cache...

> 3. Makes sure the cache of hot key mask is refreshed when needed;

Make...

> 4. logs a printk notice when the firmware doesn't set the hot key
>    mask to exactly what we asked it to;

Log...


> 5. Do the proper locking on the data structures.

Fix broken locking.

cool, huh?

> Only (4) is user-noticeable, unless (5) fixes some corner-case races.

of course that means that they should ideally be different smaller patches.

but, Henrique, we're waxing about perfection here -- your
patch hygene is already some of the best on the list.

thanks,
-Len

> Signed-off-by: Henrique de Moraes Holschuh <hmh@xxxxxxxxxx>
> ---
>  drivers/misc/thinkpad_acpi.c |  184 +++++++++++++++++++++++++-----------------
>  drivers/misc/thinkpad_acpi.h |    2 -
>  2 files changed, 109 insertions(+), 77 deletions(-)
> 
> diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
> index 8c94307..87ba534 100644
> --- a/drivers/misc/thinkpad_acpi.c
> +++ b/drivers/misc/thinkpad_acpi.c
> @@ -777,6 +777,7 @@ static int hotkey_orig_status;
>  static u32 hotkey_orig_mask;
>  static u32 hotkey_all_mask;
>  static u32 hotkey_reserved_mask;
> +static u32 hotkey_mask;
>  
>  static u16 *hotkey_keycode_map;
>  
> @@ -789,15 +790,76 @@ static int hotkey_get_wlsw(int *status)
>  	return 0;
>  }
>  
> +/*
> + * Call with hotkey_mutex held
> + */
> +static int hotkey_mask_get(void)
> +{
> +	if (tp_features.hotkey_mask) {
> +		if (!acpi_evalf(hkey_handle, &hotkey_mask, "DHKN", "d"))
> +			return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Call with hotkey_mutex held
> + */
> +static int hotkey_mask_set(u32 mask)
> +{
> +	int i;
> +	int rc = 0;
> +
> +	if (tp_features.hotkey_mask) {
> +		for (i = 0; i < 32; i++) {
> +			u32 m = 1 << i;
> +			if (!acpi_evalf(hkey_handle,
> +					NULL, "MHKM", "vdd", i + 1,
> +					!!(mask & m))) {
> +				rc = -EIO;
> +				break;
> +			} else {
> +				hotkey_mask = (hotkey_mask & ~m) | (mask & m);
> +			}
> +		}
> +
> +		/* hotkey_mask_get must be called unconditionally below */
> +		if (!hotkey_mask_get() && !rc && hotkey_mask != mask) {
> +			printk(IBM_NOTICE
> +			       "requested hot key mask 0x%08x, but "
> +			       "firmware forced it to 0x%08x\n",
> +			       mask, hotkey_mask);
> +		}
> +	}
> +
> +	return rc;
> +}
> +
> +static int hotkey_status_get(int *status)
> +{
> +	if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
> +		return -EIO;
> +
> +	return 0;
> +}
> +
> +static int hotkey_status_set(int status)
> +{
> +	if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
> +		return -EIO;
> +
> +	return 0;
> +}
> +
>  /* sysfs hotkey enable ------------------------------------------------- */
>  static ssize_t hotkey_enable_show(struct device *dev,
>  			   struct device_attribute *attr,
>  			   char *buf)
>  {
>  	int res, status;
> -	u32 mask;
>  
> -	res = hotkey_get(&status, &mask);
> +	res = hotkey_status_get(&status);
>  	if (res)
>  		return res;
>  
> @@ -809,15 +871,12 @@ static ssize_t hotkey_enable_store(struct device *dev,
>  			    const char *buf, size_t count)
>  {
>  	unsigned long t;
> -	int res, status;
> -	u32 mask;
> +	int res;
>  
>  	if (parse_strtoul(buf, 1, &t))
>  		return -EINVAL;
>  
> -	res = hotkey_get(&status, &mask);
> -	if (!res)
> -		res = hotkey_set(t, mask);
> +	res = hotkey_status_set(t);
>  
>  	return (res) ? res : count;
>  }
> @@ -831,14 +890,15 @@ static ssize_t hotkey_mask_show(struct device *dev,
>  			   struct device_attribute *attr,
>  			   char *buf)
>  {
> -	int res, status;
> -	u32 mask;
> +	int res;
>  
> -	res = hotkey_get(&status, &mask);
> -	if (res)
> -		return res;
> +	if (mutex_lock_interruptible(&hotkey_mutex))
> +		return -ERESTARTSYS;
> +	res = hotkey_mask_get();
> +	mutex_unlock(&hotkey_mutex);
>  
> -	return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask);
> +	return (res)?
> +		res : snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_mask);
>  }
>  
>  static ssize_t hotkey_mask_store(struct device *dev,
> @@ -846,15 +906,16 @@ static ssize_t hotkey_mask_store(struct device *dev,
>  			    const char *buf, size_t count)
>  {
>  	unsigned long t;
> -	int res, status;
> -	u32 mask;
> +	int res;
>  
>  	if (parse_strtoul(buf, 0xffffffffUL, &t))
>  		return -EINVAL;
>  
> -	res = hotkey_get(&status, &mask);
> -	if (!res)
> -		hotkey_set(status, t);
> +	if (mutex_lock_interruptible(&hotkey_mutex))
> +		return -ERESTARTSYS;
> +
> +	res = hotkey_mask_set(t);
> +	mutex_unlock(&hotkey_mutex);
>  
>  	return (res) ? res : count;
>  }
> @@ -1065,11 +1126,16 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
>  			}
>  		}
>  
> -		res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
> +		res = hotkey_status_get(&hotkey_orig_status);
>  		if (!res && tp_features.hotkey_mask) {
> -			res = add_many_to_attr_set(hotkey_dev_attributes,
> -				hotkey_mask_attributes,
> -				ARRAY_SIZE(hotkey_mask_attributes));
> +			res = hotkey_mask_get();
> +			hotkey_orig_mask = hotkey_mask;
> +			if (!res) {
> +				res = add_many_to_attr_set(
> +					hotkey_dev_attributes,
> +					hotkey_mask_attributes,
> +					ARRAY_SIZE(hotkey_mask_attributes));
> +			}
>  		}
>  
>  		/* Not all thinkpads have a hardware radio switch */
> @@ -1133,7 +1199,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
>  
>  		dbg_printk(TPACPI_DBG_INIT,
>  				"enabling hot key handling\n");
> -		res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)
> +		res = hotkey_status_set(1);
> +		if (res)
> +			return res;
> +		res = hotkey_mask_set((hotkey_all_mask & ~hotkey_reserved_mask)
>  					| hotkey_orig_mask);
>  		if (res)
>  			return res;
> @@ -1149,13 +1218,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
>  
>  static void hotkey_exit(void)
>  {
> -	int res;
> -
>  	if (tp_features.hotkey) {
> -		dbg_printk(TPACPI_DBG_EXIT, "restoring original hotkey mask\n");
> -		res = hotkey_set(hotkey_orig_status, hotkey_orig_mask);
> -		if (res)
> -			printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n");
> +		dbg_printk(TPACPI_DBG_EXIT, "restoring original hot key mask\n");
> +		/* no short-circuit boolean operator below! */
> +		if ((hotkey_mask_set(hotkey_orig_mask) |
> +		     hotkey_status_set(hotkey_orig_status)) != 0)
> +			printk(IBM_ERR "failed to restore hot key mask to BIOS defaults\n");
>  	}
>  
>  	if (hotkey_dev_attributes) {
> @@ -1291,50 +1359,15 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
>  
>  static void hotkey_resume(void)
>  {
> +	if (hotkey_mask_get())
> +		printk(IBM_ERR "error while trying to read hot key mask from firmware\n");
>  	tpacpi_input_send_radiosw();
>  }
>  
> -/*
> - * Call with hotkey_mutex held
> - */
> -static int hotkey_get(int *status, u32 *mask)
> -{
> -	if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
> -		return -EIO;
> -
> -	if (tp_features.hotkey_mask)
> -		if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
> -			return -EIO;
> -
> -	return 0;
> -}
> -
> -/*
> - * Call with hotkey_mutex held
> - */
> -static int hotkey_set(int status, u32 mask)
> -{
> -	int i;
> -
> -	if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
> -		return -EIO;
> -
> -	if (tp_features.hotkey_mask)
> -		for (i = 0; i < 32; i++) {
> -			int bit = ((1 << i) & mask) != 0;
> -			if (!acpi_evalf(hkey_handle,
> -					NULL, "MHKM", "vdd", i + 1, bit))
> -				return -EIO;
> -		}
> -
> -	return 0;
> -}
> -
>  /* procfs -------------------------------------------------------------- */
>  static int hotkey_read(char *p)
>  {
>  	int res, status;
> -	u32 mask;
>  	int len = 0;
>  
>  	if (!tp_features.hotkey) {
> @@ -1344,14 +1377,16 @@ static int hotkey_read(char *p)
>  
>  	if (mutex_lock_interruptible(&hotkey_mutex))
>  		return -ERESTARTSYS;
> -	res = hotkey_get(&status, &mask);
> +	res = hotkey_status_get(&status);
> +	if (!res)
> +		res = hotkey_mask_get();
>  	mutex_unlock(&hotkey_mutex);
>  	if (res)
>  		return res;
>  
>  	len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
>  	if (tp_features.hotkey_mask) {
> -		len += sprintf(p + len, "mask:\t\t0x%08x\n", mask);
> +		len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_mask);
>  		len += sprintf(p + len,
>  			       "commands:\tenable, disable, reset, <mask>\n");
>  	} else {
> @@ -1367,7 +1402,6 @@ static int hotkey_write(char *buf)
>  	int res, status;
>  	u32 mask;
>  	char *cmd;
> -	int do_cmd = 0;
>  
>  	if (!tp_features.hotkey)
>  		return -ENODEV;
> @@ -1375,9 +1409,8 @@ static int hotkey_write(char *buf)
>  	if (mutex_lock_interruptible(&hotkey_mutex))
>  		return -ERESTARTSYS;
>  
> -	res = hotkey_get(&status, &mask);
> -	if (res)
> -		goto errexit;
> +	status = -1;
> +	mask = hotkey_mask;
>  
>  	res = 0;
>  	while ((cmd = next_cmd(&buf))) {
> @@ -1396,11 +1429,12 @@ static int hotkey_write(char *buf)
>  			res = -EINVAL;
>  			goto errexit;
>  		}
> -		do_cmd = 1;
>  	}
> +	if (status != -1)
> +		res = hotkey_status_set(status);
>  
> -	if (do_cmd)
> -		res = hotkey_set(status, mask);
> +	if (!res && mask != hotkey_mask)
> +		res = hotkey_mask_set(mask);
>  
>  errexit:
>  	mutex_unlock(&hotkey_mutex);
> diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
> index 8fba2bb..3b03134 100644
> --- a/drivers/misc/thinkpad_acpi.h
> +++ b/drivers/misc/thinkpad_acpi.h
> @@ -461,8 +461,6 @@ static struct mutex hotkey_mutex;
>  
>  static int hotkey_init(struct ibm_init_struct *iibm);
>  static void hotkey_exit(void);
> -static int hotkey_get(int *status, u32 *mask);
> -static int hotkey_set(int status, u32 mask);
>  static void hotkey_notify(struct ibm_struct *ibm, u32 event);
>  static int hotkey_read(char *p);
>  static int hotkey_write(char *buf);
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[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