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 <[email protected]> 
--- 

--- 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to