]> Git Repo - linux.git/blob - drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
Linux 6.14-rc3
[linux.git] / drivers / net / wireless / realtek / rtlwifi / rtl8192de / fw.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2012  Realtek Corporation.*/
3
4 #include "../wifi.h"
5 #include "../pci.h"
6 #include "../base.h"
7 #include "../efuse.h"
8 #include "../rtl8192d/reg.h"
9 #include "../rtl8192d/def.h"
10 #include "../rtl8192d/fw_common.h"
11 #include "fw.h"
12 #include "sw.h"
13
14 int rtl92d_download_fw(struct ieee80211_hw *hw)
15 {
16         struct rtl_priv *rtlpriv = rtl_priv(hw);
17         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
18         u8 *pfwheader;
19         u8 *pfwdata;
20         u32 fwsize;
21         int err;
22         enum version_8192d version = rtlhal->version;
23         u8 value;
24         u32 count;
25         bool fw_downloaded = false, fwdl_in_process = false;
26         unsigned long flags;
27
28         if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
29                 return 1;
30         fwsize = rtlhal->fwsize;
31         pfwheader = rtlhal->pfirmware;
32         pfwdata = rtlhal->pfirmware;
33         rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
34         rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
35         rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
36                 "FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n",
37                 rtlhal->fw_version, rtlhal->fw_subversion,
38                 GET_FIRMWARE_HDR_SIGNATURE(pfwheader));
39         if (IS_FW_HEADER_EXIST(pfwheader)) {
40                 rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
41                         "Shift 32 bytes for FW header!!\n");
42                 pfwdata = pfwdata + 32;
43                 fwsize = fwsize - 32;
44         }
45
46         spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
47         fw_downloaded = rtl92d_is_fw_downloaded(rtlpriv);
48         if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
49                 fwdl_in_process = true;
50         else
51                 fwdl_in_process = false;
52         if (fw_downloaded) {
53                 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
54                 goto exit;
55         } else if (fwdl_in_process) {
56                 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
57                 for (count = 0; count < 5000; count++) {
58                         udelay(500);
59                         spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
60                         fw_downloaded = rtl92d_is_fw_downloaded(rtlpriv);
61                         if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
62                                 fwdl_in_process = true;
63                         else
64                                 fwdl_in_process = false;
65                         spin_unlock_irqrestore(&globalmutex_for_fwdownload,
66                                                flags);
67                         if (fw_downloaded)
68                                 goto exit;
69                         else if (!fwdl_in_process)
70                                 break;
71                         else
72                                 rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
73                                         "Wait for another mac download fw\n");
74                 }
75                 spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
76                 value = rtl_read_byte(rtlpriv, 0x1f);
77                 value |= BIT(5);
78                 rtl_write_byte(rtlpriv, 0x1f, value);
79                 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
80         } else {
81                 value = rtl_read_byte(rtlpriv, 0x1f);
82                 value |= BIT(5);
83                 rtl_write_byte(rtlpriv, 0x1f, value);
84                 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
85         }
86
87         /* If 8051 is running in RAM code, driver should
88          * inform Fw to reset by itself, or it will cause
89          * download Fw fail.*/
90         /* 8051 RAM code */
91         if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
92                 rtl92d_firmware_selfreset(hw);
93                 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
94         }
95         rtl92d_enable_fw_download(hw, true);
96         rtl92d_write_fw(hw, version, pfwdata, fwsize);
97         rtl92d_enable_fw_download(hw, false);
98         spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
99         err = rtl92d_fw_free_to_go(hw);
100         /* download fw over,clear 0x1f[5] */
101         value = rtl_read_byte(rtlpriv, 0x1f);
102         value &= (~BIT(5));
103         rtl_write_byte(rtlpriv, 0x1f, value);
104         spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
105         if (err)
106                 pr_err("fw is not ready to run!\n");
107 exit:
108         err = rtl92d_fw_init(hw);
109         return err;
110 }
111
112 static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
113                                     struct sk_buff *skb)
114 {
115         struct rtl_priv *rtlpriv = rtl_priv(hw);
116         struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
117         struct rtl8192_tx_ring *ring;
118         struct rtl_tx_desc *pdesc;
119         u8 idx = 0;
120         unsigned long flags;
121         struct sk_buff *pskb;
122
123         ring = &rtlpci->tx_ring[BEACON_QUEUE];
124         pskb = __skb_dequeue(&ring->queue);
125         kfree_skb(pskb);
126         spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
127         pdesc = &ring->desc[idx];
128         /* discard output from call below */
129         rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN);
130         rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, skb);
131         __skb_queue_tail(&ring->queue, skb);
132         spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
133         rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
134         return true;
135 }
136
137 #define BEACON_PG               0       /*->1 */
138 #define PSPOLL_PG               2
139 #define NULL_PG                 3
140 #define PROBERSP_PG             4       /*->5 */
141 #define TOTAL_RESERVED_PKT_LEN  768
142
143 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
144         /* page 0 beacon */
145         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
146         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
147         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
148         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
150         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
151         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
152         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
153         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
154         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
155         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
159         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161
162         /* page 1 beacon */
163         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175         0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
176         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177         0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179
180         /* page 2  ps-poll */
181         0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
182         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
183         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193         0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
194         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
195         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197
198         /* page 3  null */
199         0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
200         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
201         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
202         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211         0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
212         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
213         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215
216         /* page 4  probe_resp */
217         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
218         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
219         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
220         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
221         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
222         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
223         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
224         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
225         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
226         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
227         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
231         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233
234         /* page 5  probe_resp */
235         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 };
252
253 void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
254 {
255         struct rtl_priv *rtlpriv = rtl_priv(hw);
256         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
257         struct sk_buff *skb = NULL;
258         u32 totalpacketlen;
259         bool rtstatus;
260         u8 u1rsvdpageloc[3] = { PROBERSP_PG, PSPOLL_PG, NULL_PG };
261         bool dlok = false;
262         u8 *beacon;
263         u8 *p_pspoll;
264         u8 *nullfunc;
265         u8 *p_probersp;
266         /*---------------------------------------------------------
267                                                 (1) beacon
268         ---------------------------------------------------------*/
269         beacon = &reserved_page_packet[BEACON_PG * 128];
270         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
271         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
272         /*-------------------------------------------------------
273                                                 (2) ps-poll
274         --------------------------------------------------------*/
275         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
276         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
277         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
278         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
279         /*--------------------------------------------------------
280                                                 (3) null data
281         ---------------------------------------------------------*/
282         nullfunc = &reserved_page_packet[NULL_PG * 128];
283         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
284         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
285         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
286         /*---------------------------------------------------------
287                                                 (4) probe response
288         ----------------------------------------------------------*/
289         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
290         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
291         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
292         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
293         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
294         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
295                       "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
296                       &reserved_page_packet[0], totalpacketlen);
297         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
298                       "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
299                       u1rsvdpageloc, 3);
300         skb = dev_alloc_skb(totalpacketlen);
301         if (!skb) {
302                 dlok = false;
303         } else {
304                 skb_put_data(skb, &reserved_page_packet, totalpacketlen);
305                 rtstatus = _rtl92d_cmd_send_packet(hw, skb);
306
307                 if (rtstatus)
308                         dlok = true;
309         }
310         if (dlok) {
311                 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
312                         "Set RSVD page location to Fw\n");
313                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
314                               "H2C_RSVDPAGE", u1rsvdpageloc, 3);
315                 rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
316                         sizeof(u1rsvdpageloc), u1rsvdpageloc);
317         } else
318                 rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
319                         "Set RSVD page location to Fw FAIL!!!!!!\n");
320 }
This page took 0.052432 seconds and 4 git commands to generate.