4b55b0ede78b507f56c544034545028150e2ab38
[openwrt/staging/ansuel.git] /
1 From 69abad618efd17e50bc6f880332ab36b660b0b34 Mon Sep 17 00:00:00 2001
2 From: Martin Kaistra <martin.kaistra@linutronix.de>
3 Date: Fri, 22 Dec 2023 11:14:41 +0100
4 Subject: [PATCH 20/21] wifi: rtl8xxxu: make supporting AP mode only on port 0
5 transparent
6
7 When the driver is used for concurrent mode, both virtual interfaces can
8 be set to station or AP mode, though only one can be in AP mode at the
9 same time.
10
11 In order to keep the code simple, use only hw port 0 for AP mode. When
12 an interface is added in AP mode which would be assigned to port 1, use
13 a switch_port function to transparently swap the mapping between virtual
14 interface and hw port.
15
16 Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
17 Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
18 Signed-off-by: Kalle Valo <kvalo@kernel.org>
19 Link: https://msgid.link/20231222101442.626837-21-martin.kaistra@linutronix.de
20 ---
21 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 91 ++++++++++++++++++-
22 1 file changed, 89 insertions(+), 2 deletions(-)
23
24 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
25 +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
26 @@ -6624,6 +6624,91 @@ error:
27 return ret;
28 }
29
30 +static void rtl8xxxu_switch_ports(struct rtl8xxxu_priv *priv)
31 +{
32 + u8 macid[ETH_ALEN], bssid[ETH_ALEN], macid_1[ETH_ALEN], bssid_1[ETH_ALEN];
33 + u8 msr, bcn_ctrl, bcn_ctrl_1, atimwnd[2], atimwnd_1[2];
34 + struct rtl8xxxu_vif *rtlvif;
35 + struct ieee80211_vif *vif;
36 + u8 tsftr[8], tsftr_1[8];
37 + int i;
38 +
39 + msr = rtl8xxxu_read8(priv, REG_MSR);
40 + bcn_ctrl = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
41 + bcn_ctrl_1 = rtl8xxxu_read8(priv, REG_BEACON_CTRL_1);
42 +
43 + for (i = 0; i < ARRAY_SIZE(atimwnd); i++)
44 + atimwnd[i] = rtl8xxxu_read8(priv, REG_ATIMWND + i);
45 + for (i = 0; i < ARRAY_SIZE(atimwnd_1); i++)
46 + atimwnd_1[i] = rtl8xxxu_read8(priv, REG_ATIMWND_1 + i);
47 +
48 + for (i = 0; i < ARRAY_SIZE(tsftr); i++)
49 + tsftr[i] = rtl8xxxu_read8(priv, REG_TSFTR + i);
50 + for (i = 0; i < ARRAY_SIZE(tsftr); i++)
51 + tsftr_1[i] = rtl8xxxu_read8(priv, REG_TSFTR1 + i);
52 +
53 + for (i = 0; i < ARRAY_SIZE(macid); i++)
54 + macid[i] = rtl8xxxu_read8(priv, REG_MACID + i);
55 +
56 + for (i = 0; i < ARRAY_SIZE(bssid); i++)
57 + bssid[i] = rtl8xxxu_read8(priv, REG_BSSID + i);
58 +
59 + for (i = 0; i < ARRAY_SIZE(macid_1); i++)
60 + macid_1[i] = rtl8xxxu_read8(priv, REG_MACID1 + i);
61 +
62 + for (i = 0; i < ARRAY_SIZE(bssid_1); i++)
63 + bssid_1[i] = rtl8xxxu_read8(priv, REG_BSSID1 + i);
64 +
65 + /* disable bcn function, disable update TSF */
66 + rtl8xxxu_write8(priv, REG_BEACON_CTRL, (bcn_ctrl &
67 + (~BEACON_FUNCTION_ENABLE)) | BEACON_DISABLE_TSF_UPDATE);
68 + rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, (bcn_ctrl_1 &
69 + (~BEACON_FUNCTION_ENABLE)) | BEACON_DISABLE_TSF_UPDATE);
70 +
71 + /* switch msr */
72 + msr = (msr & 0xf0) | ((msr & 0x03) << 2) | ((msr & 0x0c) >> 2);
73 + rtl8xxxu_write8(priv, REG_MSR, msr);
74 +
75 + /* write port0 */
76 + rtl8xxxu_write8(priv, REG_BEACON_CTRL, bcn_ctrl_1 & ~BEACON_FUNCTION_ENABLE);
77 + for (i = 0; i < ARRAY_SIZE(atimwnd_1); i++)
78 + rtl8xxxu_write8(priv, REG_ATIMWND + i, atimwnd_1[i]);
79 + for (i = 0; i < ARRAY_SIZE(tsftr_1); i++)
80 + rtl8xxxu_write8(priv, REG_TSFTR + i, tsftr_1[i]);
81 + for (i = 0; i < ARRAY_SIZE(macid_1); i++)
82 + rtl8xxxu_write8(priv, REG_MACID + i, macid_1[i]);
83 + for (i = 0; i < ARRAY_SIZE(bssid_1); i++)
84 + rtl8xxxu_write8(priv, REG_BSSID + i, bssid_1[i]);
85 +
86 + /* write port1 */
87 + rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, bcn_ctrl & ~BEACON_FUNCTION_ENABLE);
88 + for (i = 0; i < ARRAY_SIZE(atimwnd); i++)
89 + rtl8xxxu_write8(priv, REG_ATIMWND_1 + i, atimwnd[i]);
90 + for (i = 0; i < ARRAY_SIZE(tsftr); i++)
91 + rtl8xxxu_write8(priv, REG_TSFTR1 + i, tsftr[i]);
92 + for (i = 0; i < ARRAY_SIZE(macid); i++)
93 + rtl8xxxu_write8(priv, REG_MACID1 + i, macid[i]);
94 + for (i = 0; i < ARRAY_SIZE(bssid); i++)
95 + rtl8xxxu_write8(priv, REG_BSSID1 + i, bssid[i]);
96 +
97 + /* write bcn ctl */
98 + rtl8xxxu_write8(priv, REG_BEACON_CTRL, bcn_ctrl_1);
99 + rtl8xxxu_write8(priv, REG_BEACON_CTRL_1, bcn_ctrl);
100 +
101 + vif = priv->vifs[0];
102 + priv->vifs[0] = priv->vifs[1];
103 + priv->vifs[1] = vif;
104 +
105 + /* priv->vifs[0] is NULL here, based on how this function is currently
106 + * called from rtl8xxxu_add_interface().
107 + * When this function will be used in the future for a different
108 + * scenario, please check whether vifs[0] or vifs[1] can be NULL and if
109 + * necessary add code to set port_num = 1.
110 + */
111 + rtlvif = (struct rtl8xxxu_vif *)priv->vifs[1]->drv_priv;
112 + rtlvif->port_num = 1;
113 +}
114 +
115 static int rtl8xxxu_add_interface(struct ieee80211_hw *hw,
116 struct ieee80211_vif *vif)
117 {
118 @@ -6651,8 +6736,10 @@ static int rtl8xxxu_add_interface(struct
119 }
120 break;
121 case NL80211_IFTYPE_AP:
122 - if (port_num == 1)
123 - return -EOPNOTSUPP;
124 + if (port_num == 1) {
125 + rtl8xxxu_switch_ports(priv);
126 + port_num = 0;
127 + }
128
129 rtl8xxxu_write8(priv, REG_BEACON_CTRL,
130 BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID);