Dear Samuel,

Please find the following flow after an analysis on the different behavior of 
the netbook, which removed the pci-E wifi device when rfkill key pressed down. 
It is different from common rfkill operation implemented on other netbooks.

When RFKILL button pressed down to power off RF device...

     ...
  remove_device()
      |
      V
  __connman_device_disable() 
      |
      |
   Call __connman_technology_disable_device() : 1st calling Since err == 
-EINPROGRESS   
      |                            
      V                            
   device->driver->disable()       
      |                            
      V                            
   wifi_disable()                  
      |                            
      V                            
   supplicant_stop()               
      |                            
      V                            
   remove_interface()              
      |                            
      V                            
   SEND CMD -> SUPPLICANT          
      |                            
      V                            
   Register the callback                      
   remove_interface_reply() ___....   --> Exit from here: wifi_disable() return 
err INPROGRESS
                 |                 |
                 |                 |
                 |                 |
                 |                 V
                 |             __connman_technology_disable_device() (NOT RUN)
                 .                 |
                 .                 V
                 .               __connman_notifier_disable() (NOT RUN)
                 |                 
                 |                 
                 |                 
         remove_interface_reply(): The callback is invoked by supplicant after 
some time ...
                 |
                 V
         connman_device_set_powered(): Here the device->powered value is still 
TRUE(should be FALSE)
                 |
                 V
         __connman_device_disable(): Return EOPNOTSUPP since driver->disable is 
not available now
                 |
                 V
         __connman_technology_disable_device(): 2nd calling
                 |                 
                 V                 
         __connman_notifier_disable(): It should NOT be here anyway...


The __connman_notifier_disable() function is called twice, and the last time it 
was called when supplicant replies to connman, and tries to power down the wifi 
device in function connman_device_set_powered(). But at that time, the device 
is already down.

I created a new patch for this bug which is more clear than last one, although 
the last one contains less code to modify.
The new patch is attached (also commited request sent to stable tree).

Please help review it.

Thanks.
Best regards,
DengYingAn



> -----Original Message-----
> From: Samuel Ortiz [mailto:[email protected]]
> Sent: Wednesday, October 27, 2010 10:56 PM
> To: Deng, Ying An
> Cc: [email protected]
> Subject: Re: [PATCH] Fix BMC 8074 fail to enable technology after
> rfkill
> 
> Hi Ying,
> 
> On Thu, Oct 28, 2010 at 04:10:26PM +0800, [email protected] wrote:
> > From: DengYingAn <[email protected]>
> >
> > Fix the issue cannot enable technologies if devices are rfkilled. The
> unregistered device should not be powered down.
> >
> Could you please elaborate on that ?
> How can a non registered device be powered down ? And how is that
> related to
> not being able to enable technologies ?
> 
> Cheers,
> Samuel.
> 
> --
> Intel Open Source Technology Centre
> http://oss.intel.com/
--- Begin Message ---
From: DengYingAn <[email protected]>

It fails to enable technologies if devices are rfkilled on netbook with the way 
to remove pci-e wifi device when rfkill key pressed. The device is indeed 
removed. The patch sync the power state between supplicant and connman driver 
layer, and prevent the attempt power off operation to an plugged-out device.
---
 include/device.h     |    2 ++
 plugins/supplicant.c |    2 ++
 src/device.c         |   10 ++++++++++
 3 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/include/device.h b/include/device.h
index b4bb297..4bd774f 100644
--- a/include/device.h
+++ b/include/device.h
@@ -75,6 +75,8 @@ void connman_device_set_mode(struct connman_device *device,
                                        enum connman_device_mode mode);
 enum connman_device_mode connman_device_get_mode(struct connman_device 
*device);

+void connman_sync_power_status_in_callback (struct connman_device *device);
+
 int connman_device_set_powered(struct connman_device *device,
                                                connman_bool_t powered);
 int connman_device_set_scanning(struct connman_device *device,
diff --git a/plugins/supplicant.c b/plugins/supplicant.c
index f17edc5..e77a6a5 100644
--- a/plugins/supplicant.c
+++ b/plugins/supplicant.c
@@ -790,6 +790,8 @@ static void remove_interface_reply(DBusPendingCall *call, 
void *user_data)

        reply = dbus_pending_call_steal_reply(call);

+       connman_sync_power_status_in_callback(task->device);
+
        connman_device_set_powered(task->device, FALSE);

        connman_device_unref(task->device);
diff --git a/src/device.c b/src/device.c
index 4ea24d1..a15b19f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -990,6 +990,16 @@ enum connman_device_mode connman_device_get_mode(struct 
connman_device *device)
 }

 /**
+ * sync the power status in callback function
+ */
+void connman_sync_power_status_in_callback (struct connman_device *device)
+{
+        if (device->driver == NULL) {
+                device->powered = FALSE;
+        }
+}
+
+/**
  * connman_device_set_powered:
  * @device: device structure
  * @powered: powered state
--
1.7.2.2


--- End Message ---
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to