@@ -309,8 +309,6 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
309309static struct calling_interface_buffer * buffer ;
310310static DEFINE_MUTEX (buffer_mutex );
311311
312- static int hwswitch_state ;
313-
314312static void clear_buffer (void )
315313{
316314 memset (buffer , 0 , sizeof (struct calling_interface_buffer ));
@@ -553,20 +551,30 @@ static int dell_rfkill_set(void *data, bool blocked)
553551 int disable = blocked ? 1 : 0 ;
554552 unsigned long radio = (unsigned long )data ;
555553 int hwswitch_bit = (unsigned long )data - 1 ;
554+ int hwswitch ;
555+ int status ;
556556 int ret ;
557557
558558 get_buffer ();
559559
560560 dell_send_request (buffer , 17 , 11 );
561561 ret = buffer -> output [0 ];
562+ status = buffer -> output [1 ];
562563
563564 if (ret != 0 )
564565 goto out ;
565566
567+ clear_buffer ();
568+
569+ buffer -> input [0 ] = 0x2 ;
570+ dell_send_request (buffer , 17 , 11 );
571+ ret = buffer -> output [0 ];
572+ hwswitch = buffer -> output [1 ];
573+
566574 /* If the hardware switch controls this radio, and the hardware
567575 switch is disabled, always disable the radio */
568- if (( hwswitch_state & BIT (hwswitch_bit )) &&
569- !( buffer -> output [ 1 ] & BIT (16 )))
576+ if (ret == 0 && ( hwswitch & BIT (hwswitch_bit )) &&
577+ ( status & BIT ( 0 )) && !( status & BIT (16 )))
570578 disable = 1 ;
571579
572580 clear_buffer ();
@@ -597,27 +605,43 @@ static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
597605}
598606
599607static void dell_rfkill_update_hw_state (struct rfkill * rfkill , int radio ,
600- int status )
608+ int status , int hwswitch )
601609{
602- if (hwswitch_state & (BIT (radio - 1 )))
610+ if (hwswitch & (BIT (radio - 1 )))
603611 rfkill_set_hw_state (rfkill , !(status & BIT (16 )));
604612}
605613
606614static void dell_rfkill_query (struct rfkill * rfkill , void * data )
607615{
616+ int radio = ((unsigned long )data & 0xF );
617+ int hwswitch ;
608618 int status ;
609619 int ret ;
610620
611621 get_buffer ();
622+
612623 dell_send_request (buffer , 17 , 11 );
613624 ret = buffer -> output [0 ];
614625 status = buffer -> output [1 ];
626+
627+ if (ret != 0 || !(status & BIT (0 ))) {
628+ release_buffer ();
629+ return ;
630+ }
631+
632+ clear_buffer ();
633+
634+ buffer -> input [0 ] = 0x2 ;
635+ dell_send_request (buffer , 17 , 11 );
636+ ret = buffer -> output [0 ];
637+ hwswitch = buffer -> output [1 ];
638+
615639 release_buffer ();
616640
617641 if (ret != 0 )
618642 return ;
619643
620- dell_rfkill_update_hw_state (rfkill , ( unsigned long ) data , status );
644+ dell_rfkill_update_hw_state (rfkill , radio , status , hwswitch );
621645}
622646
623647static const struct rfkill_ops dell_rfkill_ops = {
@@ -629,13 +653,24 @@ static struct dentry *dell_laptop_dir;
629653
630654static int dell_debugfs_show (struct seq_file * s , void * data )
631655{
656+ int hwswitch_state ;
657+ int hwswitch_ret ;
632658 int status ;
633659 int ret ;
634660
635661 get_buffer ();
662+
636663 dell_send_request (buffer , 17 , 11 );
637664 ret = buffer -> output [0 ];
638665 status = buffer -> output [1 ];
666+
667+ clear_buffer ();
668+
669+ buffer -> input [0 ] = 0x2 ;
670+ dell_send_request (buffer , 17 , 11 );
671+ hwswitch_ret = buffer -> output [0 ];
672+ hwswitch_state = buffer -> output [1 ];
673+
639674 release_buffer ();
640675
641676 seq_printf (s , "return:\t%d\n" , ret );
@@ -680,7 +715,8 @@ static int dell_debugfs_show(struct seq_file *s, void *data)
680715 seq_printf (s , "Bit 21: WiGig is blocked: %lu\n" ,
681716 (status & BIT (21 )) >> 21 );
682717
683- seq_printf (s , "\nhwswitch_state:\t0x%X\n" , hwswitch_state );
718+ seq_printf (s , "\nhwswitch_return:\t%d\n" , hwswitch_ret );
719+ seq_printf (s , "hwswitch_state:\t0x%X\n" , hwswitch_state );
684720 seq_printf (s , "Bit 0 : Wifi controlled by switch: %lu\n" ,
685721 hwswitch_state & BIT (0 ));
686722 seq_printf (s , "Bit 1 : Bluetooth controlled by switch: %lu\n" ,
@@ -716,6 +752,7 @@ static const struct file_operations dell_debugfs_fops = {
716752
717753static void dell_update_rfkill (struct work_struct * ignored )
718754{
755+ int hwswitch = 0 ;
719756 int status ;
720757 int ret ;
721758
@@ -728,16 +765,26 @@ static void dell_update_rfkill(struct work_struct *ignored)
728765 if (ret != 0 )
729766 goto out ;
730767
768+ clear_buffer ();
769+
770+ buffer -> input [0 ] = 0x2 ;
771+ dell_send_request (buffer , 17 , 11 );
772+ ret = buffer -> output [0 ];
773+
774+ if (ret == 0 && (status & BIT (0 )))
775+ hwswitch = buffer -> output [1 ];
776+
731777 if (wifi_rfkill ) {
732- dell_rfkill_update_hw_state (wifi_rfkill , 1 , status );
778+ dell_rfkill_update_hw_state (wifi_rfkill , 1 , status , hwswitch );
733779 dell_rfkill_update_sw_state (wifi_rfkill , 1 , status );
734780 }
735781 if (bluetooth_rfkill ) {
736- dell_rfkill_update_hw_state (bluetooth_rfkill , 2 , status );
782+ dell_rfkill_update_hw_state (bluetooth_rfkill , 2 , status ,
783+ hwswitch );
737784 dell_rfkill_update_sw_state (bluetooth_rfkill , 2 , status );
738785 }
739786 if (wwan_rfkill ) {
740- dell_rfkill_update_hw_state (wwan_rfkill , 3 , status );
787+ dell_rfkill_update_hw_state (wwan_rfkill , 3 , status , hwswitch );
741788 dell_rfkill_update_sw_state (wwan_rfkill , 3 , status );
742789 }
743790
@@ -805,25 +852,15 @@ static int __init dell_setup_rfkill(void)
805852 dell_send_request (buffer , 17 , 11 );
806853 ret = buffer -> output [0 ];
807854 status = buffer -> output [1 ];
808- clear_buffer ();
809- buffer -> input [0 ] = 0x2 ;
810- dell_send_request (buffer , 17 , 11 );
811- hwswitch_state = buffer -> output [1 ];
812855 release_buffer ();
813856
814857 /* dell wireless info smbios call is not supported */
815858 if (ret != 0 )
816859 return 0 ;
817860
818- if (!(status & BIT (0 ))) {
819- if (force_rfkill ) {
820- /* No hwsitch, clear all hw-controlled bits */
821- hwswitch_state &= ~7 ;
822- } else {
823- /* rfkill is only tested on laptops with a hwswitch */
824- return 0 ;
825- }
826- }
861+ /* rfkill is only tested on laptops with a hwswitch */
862+ if (!(status & BIT (0 )) && !force_rfkill )
863+ return 0 ;
827864
828865 if ((status & (1 <<2 |1 <<8 )) == (1 <<2 |1 <<8 )) {
829866 wifi_rfkill = rfkill_alloc ("dell-wifi" , & platform_device -> dev ,
0 commit comments