8859c0dd9ec89472163021040947a85980033338
[oweals/openwrt.git] /
1 From patchwork Mon Aug 19 11:20:07 2019
2 Content-Type: text/plain; charset="utf-8"
3 MIME-Version: 1.0
4 Content-Transfer-Encoding: 7bit
5 X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
6 X-Patchwork-Id: 11100685
7 X-Patchwork-Delegate: kvalo@adurom.com
8 Return-Path: <linux-wireless-owner@kernel.org>
9 From: Stanislaw Gruszka <sgruszka@redhat.com>
10 To: linux-wireless@vger.kernel.org
11 Subject: [PATCH 5.3] rt2x00: clear IV's on start to fix AP mode regression
12 Date: Mon, 19 Aug 2019 13:20:07 +0200
13 Message-Id: <1566213607-6723-1-git-send-email-sgruszka@redhat.com>
14 Sender: linux-wireless-owner@vger.kernel.org
15 List-ID: <linux-wireless.vger.kernel.org>
16 X-Mailing-List: linux-wireless@vger.kernel.org
17
18 To do not brake HW restart we should keep initialization vectors data.
19 I assumed that on start the data is already initialized to zeros, but
20 that not true on some scenarios and we should clear it. So add
21 additional flag to check if we are under HW restart and clear IV's
22 data if we are not.
23
24 Patch fixes AP mode regression.
25
26 Reported-and-tested-by: Emil Karlson <jekarl@iki.fi>
27 Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data")
28 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
29 ---
30  drivers/net/wireless/ralink/rt2x00/rt2800lib.c |  9 +++++++++
31  drivers/net/wireless/ralink/rt2x00/rt2x00.h    |  1 +
32  drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 13 ++++++++-----
33  3 files changed, 18 insertions(+), 5 deletions(-)
34
35 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
36 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
37 @@ -6095,6 +6095,15 @@ static int rt2800_init_registers(struct
38         }
39  
40         /*
41 +        * Clear encryption initialization vectors on start, but keep them
42 +        * for watchdog reset. Otherwise we will have wrong IVs and not be
43 +        * able to keep connections after reset.
44 +        */
45 +       if (!test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags))
46 +               for (i = 0; i < 256; i++)
47 +                       rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
48 +
49 +       /*
50          * Clear all beacons
51          */
52         for (i = 0; i < 8; i++)
53 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
54 +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
55 @@ -658,6 +658,7 @@ enum rt2x00_state_flags {
56         DEVICE_STATE_ENABLED_RADIO,
57         DEVICE_STATE_SCANNING,
58         DEVICE_STATE_FLUSHING,
59 +       DEVICE_STATE_RESET,
60  
61         /*
62          * Driver configuration
63 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
64 +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
65 @@ -1256,13 +1256,14 @@ static int rt2x00lib_initialize(struct r
66  
67  int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
68  {
69 -       int retval;
70 +       int retval = 0;
71  
72         if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
73                 /*
74                  * This is special case for ieee80211_restart_hw(), otherwise
75                  * mac80211 never call start() two times in row without stop();
76                  */
77 +               set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
78                 rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
79                 rt2x00lib_stop(rt2x00dev);
80         }
81 @@ -1273,14 +1274,14 @@ int rt2x00lib_start(struct rt2x00_dev *r
82          */
83         retval = rt2x00lib_load_firmware(rt2x00dev);
84         if (retval)
85 -               return retval;
86 +               goto out;
87  
88         /*
89          * Initialize the device.
90          */
91         retval = rt2x00lib_initialize(rt2x00dev);
92         if (retval)
93 -               return retval;
94 +               goto out;
95  
96         rt2x00dev->intf_ap_count = 0;
97         rt2x00dev->intf_sta_count = 0;
98 @@ -1289,11 +1290,13 @@ int rt2x00lib_start(struct rt2x00_dev *r
99         /* Enable the radio */
100         retval = rt2x00lib_enable_radio(rt2x00dev);
101         if (retval)
102 -               return retval;
103 +               goto out;
104  
105         set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
106  
107 -       return 0;
108 +out:
109 +       clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
110 +       return retval;
111  }
112  
113  void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)