mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Create the new module rtl8192d-common and move some code into it from rtl8192de. Now the rtl8192de driver (PCI) and the new rtl8192du driver (USB) can share some of the code. This is mostly the code that required little effort to make it shareable. There are a few more functions which they could share, with more changes. Add phy_iq_calibrate member to struct rtl_hal_ops to allow moving the TX power tracking code from dm.c. The other changes in this patch are adjusting whitespace, renaming some functions, making some arrays const, and making checkpatch.pl less unhappy. rtl8192de is compile-tested only. rtl8192d-common is tested with the new rtl8192du driver. Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://msgid.link/69c4358a-6fbf-4433-92a6-341c83e9dd48@gmail.com
320 lines
12 KiB
C
320 lines
12 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright(c) 2009-2012 Realtek Corporation.*/
|
|
|
|
#include "../wifi.h"
|
|
#include "../pci.h"
|
|
#include "../base.h"
|
|
#include "../efuse.h"
|
|
#include "../rtl8192d/reg.h"
|
|
#include "../rtl8192d/def.h"
|
|
#include "../rtl8192d/fw_common.h"
|
|
#include "fw.h"
|
|
#include "sw.h"
|
|
|
|
int rtl92d_download_fw(struct ieee80211_hw *hw)
|
|
{
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
|
u8 *pfwheader;
|
|
u8 *pfwdata;
|
|
u32 fwsize;
|
|
int err;
|
|
enum version_8192d version = rtlhal->version;
|
|
u8 value;
|
|
u32 count;
|
|
bool fw_downloaded = false, fwdl_in_process = false;
|
|
unsigned long flags;
|
|
|
|
if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
|
|
return 1;
|
|
fwsize = rtlhal->fwsize;
|
|
pfwheader = rtlhal->pfirmware;
|
|
pfwdata = rtlhal->pfirmware;
|
|
rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
|
|
rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
|
|
rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
|
|
"FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n",
|
|
rtlhal->fw_version, rtlhal->fw_subversion,
|
|
GET_FIRMWARE_HDR_SIGNATURE(pfwheader));
|
|
if (IS_FW_HEADER_EXIST(pfwheader)) {
|
|
rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
|
|
"Shift 32 bytes for FW header!!\n");
|
|
pfwdata = pfwdata + 32;
|
|
fwsize = fwsize - 32;
|
|
}
|
|
|
|
spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
|
|
fw_downloaded = rtl92d_is_fw_downloaded(rtlpriv);
|
|
if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
|
|
fwdl_in_process = true;
|
|
else
|
|
fwdl_in_process = false;
|
|
if (fw_downloaded) {
|
|
spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
|
|
goto exit;
|
|
} else if (fwdl_in_process) {
|
|
spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
|
|
for (count = 0; count < 5000; count++) {
|
|
udelay(500);
|
|
spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
|
|
fw_downloaded = rtl92d_is_fw_downloaded(rtlpriv);
|
|
if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
|
|
fwdl_in_process = true;
|
|
else
|
|
fwdl_in_process = false;
|
|
spin_unlock_irqrestore(&globalmutex_for_fwdownload,
|
|
flags);
|
|
if (fw_downloaded)
|
|
goto exit;
|
|
else if (!fwdl_in_process)
|
|
break;
|
|
else
|
|
rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
|
|
"Wait for another mac download fw\n");
|
|
}
|
|
spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
|
|
value = rtl_read_byte(rtlpriv, 0x1f);
|
|
value |= BIT(5);
|
|
rtl_write_byte(rtlpriv, 0x1f, value);
|
|
spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
|
|
} else {
|
|
value = rtl_read_byte(rtlpriv, 0x1f);
|
|
value |= BIT(5);
|
|
rtl_write_byte(rtlpriv, 0x1f, value);
|
|
spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
|
|
}
|
|
|
|
/* If 8051 is running in RAM code, driver should
|
|
* inform Fw to reset by itself, or it will cause
|
|
* download Fw fail.*/
|
|
/* 8051 RAM code */
|
|
if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
|
|
rtl92d_firmware_selfreset(hw);
|
|
rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
|
|
}
|
|
rtl92d_enable_fw_download(hw, true);
|
|
rtl92d_write_fw(hw, version, pfwdata, fwsize);
|
|
rtl92d_enable_fw_download(hw, false);
|
|
spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
|
|
err = rtl92d_fw_free_to_go(hw);
|
|
/* download fw over,clear 0x1f[5] */
|
|
value = rtl_read_byte(rtlpriv, 0x1f);
|
|
value &= (~BIT(5));
|
|
rtl_write_byte(rtlpriv, 0x1f, value);
|
|
spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
|
|
if (err)
|
|
pr_err("fw is not ready to run!\n");
|
|
exit:
|
|
err = rtl92d_fw_init(hw);
|
|
return err;
|
|
}
|
|
|
|
static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
|
|
struct sk_buff *skb)
|
|
{
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
|
struct rtl8192_tx_ring *ring;
|
|
struct rtl_tx_desc *pdesc;
|
|
u8 idx = 0;
|
|
unsigned long flags;
|
|
struct sk_buff *pskb;
|
|
|
|
ring = &rtlpci->tx_ring[BEACON_QUEUE];
|
|
pskb = __skb_dequeue(&ring->queue);
|
|
kfree_skb(pskb);
|
|
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
|
|
pdesc = &ring->desc[idx];
|
|
/* discard output from call below */
|
|
rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN);
|
|
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, skb);
|
|
__skb_queue_tail(&ring->queue, skb);
|
|
spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
|
|
rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
|
|
return true;
|
|
}
|
|
|
|
#define BEACON_PG 0 /*->1 */
|
|
#define PSPOLL_PG 2
|
|
#define NULL_PG 3
|
|
#define PROBERSP_PG 4 /*->5 */
|
|
#define TOTAL_RESERVED_PKT_LEN 768
|
|
|
|
static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
|
|
/* page 0 beacon */
|
|
0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
|
|
0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
|
|
0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
|
|
0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
|
|
0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
|
|
0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
|
|
0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
|
|
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
|
|
0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
/* page 1 beacon */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
/* page 2 ps-poll */
|
|
0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
|
|
0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
|
0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
/* page 3 null */
|
|
0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
|
|
0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
|
|
0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
|
0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
/* page 4 probe_resp */
|
|
0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
|
|
0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
|
|
0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
|
|
0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
|
|
0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
|
|
0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
|
|
0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
|
|
0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
|
|
0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
|
|
0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
|
|
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
|
|
0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
/* page 5 probe_resp */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
|
|
{
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
|
struct sk_buff *skb = NULL;
|
|
u32 totalpacketlen;
|
|
bool rtstatus;
|
|
u8 u1rsvdpageloc[3] = { PROBERSP_PG, PSPOLL_PG, NULL_PG };
|
|
bool dlok = false;
|
|
u8 *beacon;
|
|
u8 *p_pspoll;
|
|
u8 *nullfunc;
|
|
u8 *p_probersp;
|
|
/*---------------------------------------------------------
|
|
(1) beacon
|
|
---------------------------------------------------------*/
|
|
beacon = &reserved_page_packet[BEACON_PG * 128];
|
|
SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
|
|
SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
|
|
/*-------------------------------------------------------
|
|
(2) ps-poll
|
|
--------------------------------------------------------*/
|
|
p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
|
|
SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
|
|
SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
|
|
SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
|
|
/*--------------------------------------------------------
|
|
(3) null data
|
|
---------------------------------------------------------*/
|
|
nullfunc = &reserved_page_packet[NULL_PG * 128];
|
|
SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
|
|
SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
|
|
SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
|
|
/*---------------------------------------------------------
|
|
(4) probe response
|
|
----------------------------------------------------------*/
|
|
p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
|
|
SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
|
|
SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
|
|
SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
|
|
totalpacketlen = TOTAL_RESERVED_PKT_LEN;
|
|
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
|
|
"rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
|
|
&reserved_page_packet[0], totalpacketlen);
|
|
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
|
|
"rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
|
|
u1rsvdpageloc, 3);
|
|
skb = dev_alloc_skb(totalpacketlen);
|
|
if (!skb) {
|
|
dlok = false;
|
|
} else {
|
|
skb_put_data(skb, &reserved_page_packet, totalpacketlen);
|
|
rtstatus = _rtl92d_cmd_send_packet(hw, skb);
|
|
|
|
if (rtstatus)
|
|
dlok = true;
|
|
}
|
|
if (dlok) {
|
|
rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
|
|
"Set RSVD page location to Fw\n");
|
|
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
|
|
"H2C_RSVDPAGE", u1rsvdpageloc, 3);
|
|
rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
|
|
sizeof(u1rsvdpageloc), u1rsvdpageloc);
|
|
} else
|
|
rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
|
|
"Set RSVD page location to Fw FAIL!!!!!!\n");
|
|
}
|