[PATCH V2 12/14] sony-laptop: rfkill improvements

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

 



This patch introduces some rfkill improvements in terms of both code
cleaning and support extension. More precisely:

- removed any handle autodetection inside the setup function as it's now
provided by the caller
- rfkill type now persistent, using the hardware capability of storing
the wireless devices power state
- added support for newer WWAN modules
- removed some global variables now included in a few struct for a
cleaner code. These structs have been placed close to the rfkill
functions for better readability
- minor code improvements

Signed-off-by: Marco Chiappero <marco@xxxxxxxxxx> 
--- 

--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -141,19 +141,6 @@ MODULE_PARM_DESC(kbd_backlight_timeout,
 		 "(default: 0)");
 
 
-enum sony_nc_rfkill {
-	SONY_WIFI,
-	SONY_BLUETOOTH,
-	SONY_WWAN,
-	SONY_WIMAX,
-	N_SONY_RFKILL,
-};
-
-static unsigned int sony_rfkill_handle;
-static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
-static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700,
0x900};
-static void sony_nc_rfkill_update(void);
-
 /*********** Input Devices ***********/
 
 #define SONY_LAPTOP_BUF_SIZE	128
@@ -1204,30 +1191,51 @@ static int sony_nc_hotkeys_decode(unsign
 	return ret;
 }
 
+enum sony_nc_rfkill {
+	SONY_WIFI,
+	SONY_BLUETOOTH,
+	SONY_WWAN,
+	SONY_WIMAX,
+	N_SONY_RFKILL,
+};
+struct snc_rfkill_data {
+	unsigned int handle;
+	struct rfkill *devices[N_SONY_RFKILL];
+	const unsigned int address[N_SONY_RFKILL];
+};
+static struct snc_rfkill_data snc_rfkill = {
+	0, {NULL}, {0x300, 0x500, 0x700, 0x900}
+};
+
 static void sony_nc_rfkill_cleanup(void)
 {
 	int i;
 
 	for (i = 0; i < N_SONY_RFKILL; i++) {
-		if (sony_rfkill_devices[i]) {
-			rfkill_unregister(sony_rfkill_devices[i]);
-			rfkill_destroy(sony_rfkill_devices[i]);
+		if (snc_rfkill.devices[i]) {
+			rfkill_unregister(snc_rfkill.devices[i]);
+			rfkill_destroy(snc_rfkill.devices[i]);
 		}
 	}
 }
 
 static int sony_nc_rfkill_set(void *data, bool blocked)
 {
-	unsigned int result;
-	unsigned int argument = sony_rfkill_address[(long) data] + 0x100;
+	unsigned int result, argument = snc_rfkill.address[(long) data];
 
+	/* do not force an already set state */
+	sony_call_snc_handle(snc_rfkill.handle, argument, &result);
+	if ((result & 0x1) == !blocked)
+		return 0;
+
+	argument += 0x100;
 	if (!blocked)
 		argument |= 0xff0000;
 
-	return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
+	return sony_call_snc_handle(snc_rfkill.handle, argument, &result);
 }
 
-static const struct rfkill_ops sony_rfkill_ops = {
+static const struct rfkill_ops snc_rfkill_ops = {
 	.set_block = sony_nc_rfkill_set,
 };
 
@@ -1239,7 +1247,7 @@ static int sony_nc_setup_rfkill(struct a
 	enum rfkill_type type;
 	const char *name;
 	unsigned int result;
-	bool hwblock;
+	bool hwblock, swblock;
 
 	switch (nc_type) {
 	case SONY_WIFI:
@@ -1263,12 +1271,19 @@ static int sony_nc_setup_rfkill(struct a
 	}
 
 	rfk = rfkill_alloc(name, &device->dev, type,
-			   &sony_rfkill_ops, (void *)nc_type);
+			   &snc_rfkill_ops, (void *)nc_type);
 	if (!rfk)
 		return -ENOMEM;
 
-	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
+	sony_call_snc_handle(snc_rfkill.handle, 0x200, &result);
 	hwblock = !(result & 0x1);
+
+	result = 0;
+	sony_call_snc_handle(snc_rfkill.handle, snc_rfkill.address[nc_type],
+				&result);
+	swblock = !(result & 0x2);
+
+	rfkill_init_sw_state(rfk, swblock);
 	rfkill_set_hw_state(rfk, hwblock);
 
 	err = rfkill_register(rfk);
@@ -1276,7 +1291,7 @@ static int sony_nc_setup_rfkill(struct a
 		rfkill_destroy(rfk);
 		return err;
 	}
-	sony_rfkill_devices[nc_type] = rfk;
+	snc_rfkill.devices[nc_type] = rfk;
 	return err;
 }
 
@@ -1284,51 +1299,35 @@ static void sony_nc_rfkill_update(void)
 {
 	enum sony_nc_rfkill i;
 	unsigned int result;
-	bool hwblock;
+	bool hwblock, swblock;
 
-	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
+	sony_call_snc_handle(snc_rfkill.handle, 0x200, &result);
 	hwblock = !(result & 0x1);
 
 	for (i = 0; i < N_SONY_RFKILL; i++) {
-		unsigned int argument = sony_rfkill_address[i];
+		unsigned int argument = snc_rfkill.address[i];
 
-		if (!sony_rfkill_devices[i])
+		if (!snc_rfkill.devices[i])
 			continue;
 
-		if (hwblock) {
-			if (rfkill_set_hw_state(sony_rfkill_devices[i], true))
-				/* we already know we're blocked */ ;
-
-			continue;
-		}
+		sony_call_snc_handle(snc_rfkill.handle, argument, &result);
+		swblock = !(result & 0x2);
 
-		sony_call_snc_handle(sony_rfkill_handle, argument, &result);
-		rfkill_set_states(sony_rfkill_devices[i],
-				  !(result & 0xf), false);
+		rfkill_set_states(snc_rfkill.devices[i], swblock, hwblock);
 	}
 }
 
-static int sony_nc_rfkill_setup(struct acpi_device *device)
+static int sony_nc_rfkill_setup(struct acpi_device *device, unsigned
int handle)
 {
 #define	RFKILL_BUFF_SIZE 8
 	u8 dev_code, i, buff[RFKILL_BUFF_SIZE] = { 0 };
-	int offset;
 
-	offset = sony_find_snc_handle(0x124);
-	if (offset == -1) {
-		offset = sony_find_snc_handle(0x135);
-		if (offset == -1)
-			return 0;
-		else
-			sony_rfkill_handle = 0x135;
-	} else
-		sony_rfkill_handle = 0x124;
-	dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
+	snc_rfkill.handle = handle;
 
 	/* need to read the whole buffer returned by the acpi call to SN06
 	 * here otherwise we may miss some features
 	 */
-	if (sony_call_snc_handle_buffer(sony_rfkill_handle, 0x000,
+	if (sony_call_snc_handle_buffer(snc_rfkill.handle, 0x000,
 					buff, RFKILL_BUFF_SIZE) < 0)
 		return -EIO;
 
@@ -1341,19 +1340,38 @@ static int sony_nc_rfkill_setup(struct a
 		if (dev_code == 0xff)
 			break;
 
+		/*
+		   known codes:
+
+		   0x00	WLAN
+		   0x10 BLUETOOTH
+		   0x20 WWAN GPRS-EDGE
+		   0x21 WWAN HSDPA
+		   0x22 WWAN EV-DO
+		   0x23 WWAN GPS
+		   0x25	Gobi WWAN no GPS
+		   0x26 Gobi WWAN + GPS
+		   0x28	Gobi WWAN no GPS
+		   0x29 Gobi WWAN + GPS
+		   0x50	Gobi WWAN no GPS
+		   0x51 Gobi WWAN + GPS
+		   0x30	WIMAX
+		   0x70 no SIM card slot
+		   0x71 SIM card slot
+		*/
 		dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
 
-		if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
+		if (dev_code == 0 && !snc_rfkill.devices[SONY_WIFI])
 			sony_nc_setup_rfkill(device, SONY_WIFI);
 
-		if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
+		if (dev_code == 0x10 && !snc_rfkill.devices[SONY_BLUETOOTH])
 			sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
 
-		if ((0xf0 & dev_code) == 0x20 &&
-				!sony_rfkill_devices[SONY_WWAN])
+		if (((0xf0 & dev_code) == 0x20 || (0xf0 & dev_code) == 0x50) &&
+				!snc_rfkill.devices[SONY_WWAN])
 			sony_nc_setup_rfkill(device, SONY_WWAN);
 
-		if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
+		if (dev_code == 0x30 && !snc_rfkill.devices[SONY_WIMAX])
 			sony_nc_setup_rfkill(device, SONY_WIMAX);
 	}
 
@@ -1717,7 +1735,7 @@ static int sony_nc_handles_setup(struct 
 			ret = sony_nc_kbd_backlight_setup(pd, handle);
 		case 0x0124:
 		case 0x0135:
-			ret = sony_nc_rfkill_setup(sony_nc_acpi_device);
+			ret = sony_nc_rfkill_setup(sony_nc_acpi_device, handle);
 			break;
 		default:
 			continue;

--
To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux