drivers/net/wireless/realtek/rtw88/main.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/realtek/rtw88/main.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/realtek/rtw88/main.c
Extension
.c
Size
67250 bytes
Lines
2515
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct rtw_watch_dog_iter_data {
	struct rtw_dev *rtwdev;
	struct rtw_vif *rtwvif;
};

static void rtw_dynamic_csi_rate(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
{
	struct rtw_bf_info *bf_info = &rtwdev->bf_info;
	u8 fix_rate_enable = 0;
	u8 new_csi_rate_idx;

	if (rtwvif->bfee.role != RTW_BFEE_SU &&
	    rtwvif->bfee.role != RTW_BFEE_MU)
		return;

	rtw_chip_cfg_csi_rate(rtwdev, rtwdev->dm_info.min_rssi,
			      bf_info->cur_csi_rpt_rate,
			      fix_rate_enable, &new_csi_rate_idx);

	if (new_csi_rate_idx != bf_info->cur_csi_rpt_rate)
		bf_info->cur_csi_rpt_rate = new_csi_rate_idx;
}

static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif)
{
	struct rtw_watch_dog_iter_data *iter_data = data;
	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;

	if (vif->type == NL80211_IFTYPE_STATION)
		if (vif->cfg.assoc)
			iter_data->rtwvif = rtwvif;

	rtw_dynamic_csi_rate(iter_data->rtwdev, rtwvif);

	rtwvif->stats.tx_unicast = 0;
	rtwvif->stats.rx_unicast = 0;
	rtwvif->stats.tx_cnt = 0;
	rtwvif->stats.rx_cnt = 0;
}

static void rtw_sw_beacon_loss_check(struct rtw_dev *rtwdev,
				     struct rtw_vif *rtwvif, int received_beacons)
{
	int watchdog_delay = 2000000 / 1024; /* TU */
	int beacon_int, expected_beacons;

	if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER) || !rtwvif)
		return;

	beacon_int = rtwvif_to_vif(rtwvif)->bss_conf.beacon_int;
	expected_beacons = DIV_ROUND_UP(watchdog_delay, beacon_int);

	rtwdev->beacon_loss = received_beacons < expected_beacons / 2;
}

/* process TX/RX statistics periodically for hardware,
 * the information helps hardware to enhance performance
 */
static void rtw_watch_dog_work(struct work_struct *work)
{
	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
					      watch_dog_work.work);
	struct rtw_traffic_stats *stats = &rtwdev->stats;
	struct rtw_watch_dog_iter_data data = {};
	bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
	int received_beacons = rtwdev->dm_info.cur_pkt_count.num_bcn_pkt;
	u32 tx_unicast_mbps, rx_unicast_mbps;
	bool ps_active;

	mutex_lock(&rtwdev->mutex);

	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
		goto unlock;

	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work,
				     RTW_WATCH_DOG_DELAY_TIME);

	if (rtwdev->stats.tx_cnt > 100 || rtwdev->stats.rx_cnt > 100)
		set_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
	else
		clear_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);

	if (busy_traffic != test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags))
		rtw_coex_wl_status_change_notify(rtwdev, 0);

	if (stats->tx_cnt > RTW_LPS_THRESHOLD ||
	    stats->rx_cnt > RTW_LPS_THRESHOLD)
		ps_active = true;
	else
		ps_active = false;

Annotation

Implementation Notes