diff --git a/feeds/mediatek-sdk/mac80211/Makefile b/feeds/mediatek-sdk/mac80211/Makefile index 60969f7ac..bc4f989f9 100644 --- a/feeds/mediatek-sdk/mac80211/Makefile +++ b/feeds/mediatek-sdk/mac80211/Makefile @@ -77,6 +77,7 @@ config-y:= \ MAC80211_STA_DEBUG \ MAC80211_HT_DEBUG \ MAC80211_PS_DEBUG \ + MAC80211_DEBUG_COUNTERS \ config-$(call config_package,cfg80211) += CFG80211 config-$(CONFIG_PACKAGE_CFG80211_TESTMODE) += NL80211_TESTMODE diff --git a/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0013-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0013-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch index 5bd6dfd55..587310361 100644 --- a/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0013-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch +++ b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0013-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch @@ -1,8 +1,7 @@ -From 7a5c5d30c9f95cf990c415c4edb3359ac1c1ab5b Mon Sep 17 00:00:00 2001 +From 5c8d90efe02c47ce76a6d5383ea6aa90eb0c73d8 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Mon, 20 Feb 2023 14:25:24 +0800 -Subject: [PATCH 13/19] mac80211: mtk: add sta-assisted DFS state update - mechanism +Subject: [PATCH] mac80211: mtk: add sta-assisted DFS state update mechanism Signed-off-by: StanleyYP Wang --- @@ -62,7 +61,7 @@ index e674aa7..3e348a5 100644 /** diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index 8ee325a..48053e4 100644 +index 8ee325a..2dbc18c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1442,6 +1442,10 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, @@ -87,16 +86,16 @@ index 8ee325a..48053e4 100644 } static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) -@@ -3782,6 +3790,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, - event.u.mlme.status = MLME_SUCCESS; - drv_event_callback(sdata->local, sdata, &event); - sdata_info(sdata, "associated\n"); +@@ -3779,6 +3787,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + cfg80211_assoc_timeout(sdata->dev, cbss); + goto notify_driver; + } + cfg80211_sta_update_dfs_state(&sdata->wdev, + &sdata->vif.bss_conf.chandef, + NULL, sdata->vif.bss_conf.assoc); - - /* - * destroy assoc_data afterwards, as otherwise an idle + event.u.mlme.status = MLME_SUCCESS; + drv_event_callback(sdata->local, sdata, &event); + sdata_info(sdata, "associated\n"); diff --git a/net/wireless/chan.c b/net/wireless/chan.c index c217276..9f651f9 100644 --- a/net/wireless/chan.c diff --git a/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0024-mac80211-mtk-add-DFS-CAC-countdown-in-CSA-flow.patch b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0024-mac80211-mtk-add-DFS-CAC-countdown-in-CSA-flow.patch index f2fde36d0..beead44a4 100644 --- a/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0024-mac80211-mtk-add-DFS-CAC-countdown-in-CSA-flow.patch +++ b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0024-mac80211-mtk-add-DFS-CAC-countdown-in-CSA-flow.patch @@ -1,20 +1,20 @@ -From d10310d3eb842ebc449271b45ad2f47634149385 Mon Sep 17 00:00:00 2001 +From bb918e40dcc7d082f898234cf29cd545de78621e Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Wed, 15 Nov 2023 15:05:17 +0800 Subject: [PATCH] mac80211: mtk: add DFS CAC countdown in CSA flow Signed-off-by: StanleyYP Wang --- - include/net/cfg80211.h | 32 +++++++++++++++++ - net/mac80211/cfg.c | 45 +++++++++++++++++++++++- - net/mac80211/ieee80211_i.h | 2 ++ - net/mac80211/iface.c | 2 ++ - net/mac80211/mlme.c | 6 +++- - net/mac80211/util.c | 11 +++++- - net/wireless/chan.c | 71 ++++++++++++++++++++++++++++++++++++++ - net/wireless/nl80211.c | 5 +-- - net/wireless/rdev-ops.h | 17 +++++++++ - 9 files changed, 186 insertions(+), 5 deletions(-) + include/net/cfg80211.h | 32 +++++++++++++++ + net/mac80211/cfg.c | 84 +++++++++++++++++++++++++++++++++++--- + net/mac80211/ieee80211_i.h | 2 + + net/mac80211/iface.c | 2 + + net/mac80211/mlme.c | 6 ++- + net/mac80211/util.c | 11 ++++- + net/wireless/chan.c | 72 ++++++++++++++++++++++++++++++++ + net/wireless/nl80211.c | 5 ++- + net/wireless/rdev-ops.h | 17 ++++++++ + 9 files changed, 221 insertions(+), 10 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 03f072f..a443b0d 100644 @@ -67,7 +67,7 @@ index 03f072f..a443b0d 100644 * cfg80211_ch_switch_notify - update wdev channel and notify userspace * @dev: the device which switched channels diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index 56381f8..3e6e903 100644 +index 56381f8..7a30ca6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3328,6 +3328,39 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, @@ -122,7 +122,78 @@ index 56381f8..3e6e903 100644 sdata->vif.csa_active = false; err = ieee80211_set_after_csa_beacon(sdata, &changed); -@@ -4538,7 +4576,11 @@ ieee80211_skip_cac(struct wireless_dev *wdev) +@@ -3428,6 +3466,11 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + sdata->u.ap.next_beacon = + cfg80211_beacon_dup(¶ms->beacon_after); + if (!sdata->u.ap.next_beacon) +@@ -3586,15 +3629,14 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, + if (!list_empty(&local->roc_list) || local->scanning) + return -EBUSY; + +- if (sdata->wdev.cac_started) +- return -EBUSY; +- + if (cfg80211_chandef_identical(¶ms->chandef, + &sdata->vif.bss_conf.chandef)) + return -EINVAL; + +- /* don't allow another channel switch if one is already active. */ +- if (sdata->vif.csa_active) ++ /* don't allow another channel switch if one is already active ++ * unless its during post CSA radar detection. ++ */ ++ if (sdata->vif.csa_active && !sdata->wdev.cac_started) + return -EBUSY; + + mutex_lock(&local->chanctx_mtx); +@@ -3646,6 +3688,14 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, + goto out; + } + ++ /* Finalize CSA immediately if CAC is started during last channel switch */ ++ if (sdata->wdev.cac_started) { ++ ieee80211_wake_vif_queues(local, sdata, IEEE80211_QUEUE_STOP_REASON_CSA); ++ cancel_delayed_work(&sdata->dfs_cac_timer_work); ++ sdata->wdev.cac_started = false; ++ changed = 0; ++ } ++ + sdata->csa_chandef = params->chandef; + sdata->csa_block_tx = params->block_tx; + sdata->vif.csa_active = true; +@@ -3661,6 +3711,23 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, + ieee80211_bss_info_change_notify(sdata, changed); + drv_channel_switch_beacon(sdata, ¶ms->chandef); + } else { ++ struct ieee80211_sub_if_data *tmp; ++ int n_assigned = 0, n_reserved = 0; ++ ++ list_for_each_entry(tmp, &chanctx->assigned_vifs, ++ assigned_chanctx_list) { ++ n_assigned++; ++ if (tmp->reserved_chanctx) ++ n_reserved++; ++ } ++ ++ /* Wait for all interfaces to be ready */ ++ if (n_assigned != n_reserved) { ++ sdata->reserved_ready = true; ++ err = 0; ++ goto out; ++ } ++ + /* if the beacon didn't change, we can finalize immediately */ + ieee80211_csa_finalize(sdata); + } +@@ -4538,7 +4605,11 @@ ieee80211_skip_cac(struct wireless_dev *wdev) cancel_delayed_work(&sdata->dfs_cac_timer_work); if (wdev->cac_started) { @@ -135,7 +206,7 @@ index 56381f8..3e6e903 100644 cac_time_ms = wdev->cac_time_ms; wdev->cac_start_time = jiffies - msecs_to_jiffies(cac_time_ms + 1); -@@ -4630,6 +4672,7 @@ const struct cfg80211_ops mac80211_config_ops = { +@@ -4630,6 +4701,7 @@ const struct cfg80211_ops mac80211_config_ops = { #endif .get_channel = ieee80211_cfg_get_channel, .start_radar_detection = ieee80211_start_radar_detection, @@ -184,7 +255,7 @@ index 00b0443..ef32d53 100644 INIT_LIST_HEAD(&sdata->assigned_chanctx_list); INIT_LIST_HEAD(&sdata->reserved_chanctx_list); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index 48053e4..e9ec32d 100644 +index 2dbc18c..ed81ebf 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1870,7 +1870,11 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work) @@ -223,10 +294,10 @@ index 26cd627..e07fe73 100644 &chandef, NL80211_RADAR_CAC_ABORTED, diff --git a/net/wireless/chan.c b/net/wireless/chan.c -index 9f651f9..88dd69e 100644 +index 9f651f9..f02598b 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c -@@ -1262,6 +1262,77 @@ bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy, +@@ -1262,6 +1262,78 @@ bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax); @@ -267,11 +338,12 @@ index 9f651f9..88dd69e 100644 + enum nl80211_dfs_regions dfs_region; + int ret = 0; + ++ /* Update DFS channel state especially when original channel include DFS channel */ ++ cfg80211_sched_dfs_chan_update(rdev); ++ + if (cfg80211_chandef_dfs_available(wiphy, chandef)) + goto out; + -+ flush_delayed_work(&rdev->dfs_update_channels_wk); -+ + dfs_region = reg_get_dfs_region(wiphy); + if (dfs_region == NL80211_DFS_UNSET) + goto out; diff --git a/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0028-mac80211-mtk-backport-refactor-STA-CSA-paring-flow.patch b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0028-mac80211-mtk-backport-refactor-STA-CSA-paring-flow.patch new file mode 100644 index 000000000..7a3932669 --- /dev/null +++ b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0028-mac80211-mtk-backport-refactor-STA-CSA-paring-flow.patch @@ -0,0 +1,456 @@ +From 34063f56b7b5f69daea335ae70582fdbcea429a5 Mon Sep 17 00:00:00 2001 +From: Rex Lu +Date: Thu, 14 Mar 2024 17:06:52 +0800 +Subject: [PATCH] mac80211: mtk: backport refactor STA CSA paring flow + +According to https://github.com/torvalds/linux/commit/21c3f8f95554feff9bed15703e89adbe582e0383 + +Signed-off-by: Rex Lu +--- + include/net/cfg80211.h | 13 ++ + net/mac80211/spectmgmt.c | 273 +++++++++++++++++++++++++++++++-------- + net/wireless/util.c | 74 +++++++++++ + 3 files changed, 308 insertions(+), 52 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 0114c26..c333ba8 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -7840,6 +7840,19 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev, + bool ieee80211_operating_class_to_band(u8 operating_class, + enum nl80211_band *band); + ++/** ++ * ieee80211_operating_class_to_chandef - convert operating class to chandef ++ * ++ * @operating_class: the operating class to convert ++ * @chan: the ieee80211_channel to convert ++ * @chandef: a pointer to the resulting chandef ++ * ++ * Returns %true if the conversion was successful, %false otherwise. ++ */ ++bool ieee80211_operating_class_to_chandef(u8 operating_class, ++ struct ieee80211_channel *chan, ++ struct cfg80211_chan_def *chandef); ++ + /** + * ieee80211_chandef_to_operating_class - convert chandef to operation class + * +diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c +index 76747bf..ce00687 100644 +--- a/net/mac80211/spectmgmt.c ++++ b/net/mac80211/spectmgmt.c +@@ -19,6 +19,182 @@ + #include "sta_info.h" + #include "wme.h" + ++static bool ++wbcs_elem_to_chandef(const struct ieee80211_wide_bw_chansw_ie *wbcs_elem, ++ struct cfg80211_chan_def *chandef) ++{ ++ u8 ccfs0 = wbcs_elem->new_center_freq_seg0; ++ u8 ccfs1 = wbcs_elem->new_center_freq_seg1; ++ u32 cf0 = ieee80211_channel_to_frequency(ccfs0, chandef->chan->band); ++ u32 cf1 = ieee80211_channel_to_frequency(ccfs1, chandef->chan->band); ++ ++ switch (wbcs_elem->new_channel_width) { ++ case IEEE80211_VHT_CHANWIDTH_160MHZ: ++ /* deprecated encoding */ ++ chandef->width = NL80211_CHAN_WIDTH_160; ++ chandef->center_freq1 = cf0; ++ break; ++ case IEEE80211_VHT_CHANWIDTH_80P80MHZ: ++ /* deprecated encoding */ ++ chandef->width = NL80211_CHAN_WIDTH_80P80; ++ chandef->center_freq1 = cf0; ++ chandef->center_freq2 = cf1; ++ break; ++ case IEEE80211_VHT_CHANWIDTH_80MHZ: ++ chandef->width = NL80211_CHAN_WIDTH_80; ++ chandef->center_freq1 = cf0; ++ ++ if (ccfs1) { ++ u8 diff = abs(ccfs0 - ccfs1); ++ ++ if (diff == 8) { ++ chandef->width = NL80211_CHAN_WIDTH_160; ++ chandef->center_freq1 = cf1; ++ } else if (diff > 8) { ++ chandef->width = NL80211_CHAN_WIDTH_80P80; ++ chandef->center_freq2 = cf1; ++ } ++ } ++ break; ++ case IEEE80211_VHT_CHANWIDTH_USE_HT: ++ default: ++ /* If the WBCS Element is present, new channel bandwidth is ++ * at least 40 MHz. ++ */ ++ chandef->width = NL80211_CHAN_WIDTH_40; ++ chandef->center_freq1 = cf0; ++ break; ++ } ++ ++ return cfg80211_chandef_valid(chandef); ++} ++ ++static void ++validate_chandef_by_ht_vht_oper(struct ieee80211_sub_if_data *sdata, ++ u32 sta_flags, ++ u32 vht_cap_info, ++ struct cfg80211_chan_def *chandef) ++{ ++ u32 control_freq, center_freq1, center_freq2; ++ enum nl80211_chan_width chan_width; ++ struct ieee80211_ht_operation ht_oper; ++ struct ieee80211_vht_operation vht_oper; ++ ++ if (sta_flags & (IEEE80211_STA_DISABLE_HT | ++ IEEE80211_STA_DISABLE_40MHZ)) { ++ chandef->chan = NULL; ++ return; ++ } ++ ++ control_freq = chandef->chan->center_freq; ++ center_freq1 = chandef->center_freq1; ++ center_freq2 = chandef->center_freq2; ++ chan_width = chandef->width; ++ ++ ht_oper.primary_chan = ieee80211_frequency_to_channel(control_freq); ++ if (control_freq != center_freq1) ++ ht_oper.ht_param = control_freq > center_freq1 ? ++ IEEE80211_HT_PARAM_CHA_SEC_BELOW : ++ IEEE80211_HT_PARAM_CHA_SEC_ABOVE; ++ else ++ ht_oper.ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; ++ ++ ieee80211_chandef_ht_oper(&ht_oper, chandef); ++ ++ if (sta_flags & IEEE80211_STA_DISABLE_VHT) ++ return; ++ ++ vht_oper.center_freq_seg0_idx = ++ ieee80211_frequency_to_channel(center_freq1); ++ vht_oper.center_freq_seg1_idx = center_freq2 ? ++ ieee80211_frequency_to_channel(center_freq2) : 0; ++ ++ switch (chan_width) { ++ case NL80211_CHAN_WIDTH_160: ++ vht_oper.chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; ++ vht_oper.center_freq_seg1_idx = vht_oper.center_freq_seg0_idx; ++ vht_oper.center_freq_seg0_idx += ++ control_freq < center_freq1 ? -8 : 8; ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ vht_oper.chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; ++ break; ++ case NL80211_CHAN_WIDTH_80: ++ vht_oper.chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; ++ break; ++ default: ++ vht_oper.chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT; ++ break; ++ } ++ ++ ht_oper.operation_mode = ++ cpu_to_le16(vht_oper.center_freq_seg1_idx << ++ IEEE80211_HT_OP_MODE_CCFS2_SHIFT); ++ ++ if (!ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info, ++ &vht_oper, &ht_oper, chandef)) ++ chandef->chan = NULL; ++} ++ ++static void ++validate_chandef_by_6ghz_he_eht_oper(struct ieee80211_sub_if_data *sdata, ++ u32 sta_flags, ++ struct cfg80211_chan_def *chandef) ++{ ++ u32 control_freq, center_freq1, center_freq2; ++ enum nl80211_chan_width chan_width; ++ struct { ++ struct ieee80211_he_operation _oper; ++ struct ieee80211_he_6ghz_oper _6ghz_oper; ++ } __packed he; ++ ++ if (sta_flags & (IEEE80211_STA_DISABLE_HE)) { ++ chandef->chan = NULL; ++ return; ++ } ++ ++ control_freq = chandef->chan->center_freq; ++ center_freq1 = chandef->center_freq1; ++ center_freq2 = chandef->center_freq2; ++ chan_width = chandef->width; ++ ++ he._oper.he_oper_params = cpu_to_le32(u32_encode_bits(1, ++ IEEE80211_HE_OPERATION_6GHZ_OP_INFO)); ++ he._6ghz_oper.primary = ++ ieee80211_frequency_to_channel(control_freq); ++ he._6ghz_oper.ccfs0 = ieee80211_frequency_to_channel(center_freq1); ++ he._6ghz_oper.ccfs1 = center_freq2 ? ++ ieee80211_frequency_to_channel(center_freq2) : 0; ++ ++ switch (chan_width) { ++ case NL80211_CHAN_WIDTH_160: ++ he._6ghz_oper.ccfs1 = he._6ghz_oper.ccfs0; ++ he._6ghz_oper.ccfs0 += control_freq < center_freq1 ? -8 : 8; ++ fallthrough; ++ case NL80211_CHAN_WIDTH_80P80: ++ he._6ghz_oper.control = ++ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ; ++ break; ++ case NL80211_CHAN_WIDTH_80: ++ he._6ghz_oper.control = ++ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ; ++ break; ++ case NL80211_CHAN_WIDTH_40: ++ he._6ghz_oper.control = ++ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ; ++ break; ++ default: ++ he._6ghz_oper.control = ++ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ; ++ break; ++ } ++ ++ ++ if (!ieee80211_chandef_he_6ghz_oper(sdata, &he._oper, chandef)) ++ chandef->chan = NULL; ++ ++} ++ + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, + struct ieee802_11_elems *elems, + enum nl80211_band current_band, +@@ -28,17 +204,19 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, + { + enum nl80211_band new_band = current_band; + int new_freq; +- u8 new_chan_no; ++ u8 new_chan_no = 0, new_op_class = 0; + struct ieee80211_channel *new_chan; +- struct cfg80211_chan_def new_vht_chandef = {}; ++ struct cfg80211_chan_def new_chandef = {}; + const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; + const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; ++ const struct ieee80211_ext_chansw_ie *ext_chansw_elem; + int secondary_channel_offset = -1; + + memset(csa_ie, 0, sizeof(*csa_ie)); + + sec_chan_offs = elems->sec_chan_offs; + wide_bw_chansw_ie = elems->wide_bw_chansw_ie; ++ ext_chansw_elem = elems->ext_chansw_ie; + + if (sta_flags & (IEEE80211_STA_DISABLE_HT | + IEEE80211_STA_DISABLE_40MHZ)) { +@@ -49,26 +227,29 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, + if (sta_flags & IEEE80211_STA_DISABLE_VHT) + wide_bw_chansw_ie = NULL; + +- if (elems->ext_chansw_ie) { +- if (!ieee80211_operating_class_to_band( +- elems->ext_chansw_ie->new_operating_class, +- &new_band)) { +- sdata_info(sdata, +- "cannot understand ECSA IE operating class, %d, ignoring\n", +- elems->ext_chansw_ie->new_operating_class); ++ if (ext_chansw_elem) { ++ new_op_class = ext_chansw_elem->new_operating_class; ++ if (!ieee80211_operating_class_to_band(new_op_class, &new_band)) { ++ new_op_class = 0; ++ sdata_info(sdata, "cannot understand ECSA IE operating class, %d, ignoring\n", ++ ext_chansw_elem->new_operating_class); ++ } else { ++ new_chan_no = ext_chansw_elem->new_ch_num; ++ csa_ie->count = ext_chansw_elem->count; ++ csa_ie->mode = ext_chansw_elem->mode; + } +- new_chan_no = elems->ext_chansw_ie->new_ch_num; +- csa_ie->count = elems->ext_chansw_ie->count; +- csa_ie->mode = elems->ext_chansw_ie->mode; +- } else if (elems->ch_switch_ie) { ++ } ++ ++ if (!new_op_class && elems->ch_switch_ie) { + new_chan_no = elems->ch_switch_ie->new_ch_num; + csa_ie->count = elems->ch_switch_ie->count; + csa_ie->mode = elems->ch_switch_ie->mode; +- } else { +- /* nothing here we understand */ +- return 1; + } + ++ /* nothing here we understand */ ++ if (!new_chan_no) ++ return 1; ++ + /* Mesh Channel Switch Parameters Element */ + if (elems->mesh_chansw_params_ie) { + csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl; +@@ -132,52 +313,40 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, + break; + } + +- if (wide_bw_chansw_ie) { +- u8 new_seg1 = wide_bw_chansw_ie->new_center_freq_seg1; +- struct ieee80211_vht_operation vht_oper = { +- .chan_width = +- wide_bw_chansw_ie->new_channel_width, +- .center_freq_seg0_idx = +- wide_bw_chansw_ie->new_center_freq_seg0, +- .center_freq_seg1_idx = new_seg1, +- /* .basic_mcs_set doesn't matter */ +- }; +- struct ieee80211_ht_operation ht_oper = { +- .operation_mode = +- cpu_to_le16(new_seg1 << +- IEEE80211_HT_OP_MODE_CCFS2_SHIFT), +- }; +- +- /* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT, +- * to the previously parsed chandef +- */ +- new_vht_chandef = csa_ie->chandef; ++ /* parse one of the Elements to build a new chandef */ ++ memset(&new_chandef, 0, sizeof(new_chandef)); ++ new_chandef.chan = new_chan; ++ ++ if (!wide_bw_chansw_ie || !wbcs_elem_to_chandef(wide_bw_chansw_ie, ++ &new_chandef)) { ++ if (!ieee80211_operating_class_to_chandef(new_op_class, new_chan, ++ &new_chandef)) ++ new_chandef = csa_ie->chandef; ++ } + +- /* ignore if parsing fails */ +- if (!ieee80211_chandef_vht_oper(&sdata->local->hw, +- vht_cap_info, +- &vht_oper, &ht_oper, +- &new_vht_chandef)) +- new_vht_chandef.chan = NULL; ++ /* check if the new chandef fits the capabilities */ ++ if (new_band == NL80211_BAND_6GHZ) ++ validate_chandef_by_6ghz_he_eht_oper(sdata, sta_flags, ++ &new_chandef); ++ else ++ validate_chandef_by_ht_vht_oper(sdata, sta_flags, vht_cap_info, ++ &new_chandef); + ++ /* if data is there validate the bandwidth & use it */ ++ if (new_chandef.chan) { + if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ && +- new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80) +- ieee80211_chandef_downgrade(&new_vht_chandef); +- if (sta_flags & IEEE80211_STA_DISABLE_160MHZ && +- new_vht_chandef.width == NL80211_CHAN_WIDTH_160) +- ieee80211_chandef_downgrade(&new_vht_chandef); +- } ++ (new_chandef.width == NL80211_CHAN_WIDTH_80P80 || ++ new_chandef.width == NL80211_CHAN_WIDTH_160)) ++ ieee80211_chandef_downgrade(&new_chandef); + +- /* if VHT data is there validate & use it */ +- if (new_vht_chandef.chan) { +- if (!cfg80211_chandef_compatible(&new_vht_chandef, ++ if (!cfg80211_chandef_compatible(&new_chandef, + &csa_ie->chandef)) { + sdata_info(sdata, + "BSS %pM: CSA has inconsistent channel data, disconnecting\n", + bssid); + return -EINVAL; + } +- csa_ie->chandef = new_vht_chandef; ++ csa_ie->chandef = new_chandef; + } + + if (elems->max_channel_switch_time) +diff --git a/net/wireless/util.c b/net/wireless/util.c +index c2a560f..ddf85be 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -1668,6 +1668,80 @@ bool ieee80211_operating_class_to_band(u8 operating_class, + } + EXPORT_SYMBOL(ieee80211_operating_class_to_band); + ++bool ieee80211_operating_class_to_chandef(u8 operating_class, ++ struct ieee80211_channel *chan, ++ struct cfg80211_chan_def *chandef) ++{ ++ u32 control_freq, offset = 0; ++ enum nl80211_band band; ++ ++ if (!ieee80211_operating_class_to_band(operating_class, &band) || ++ !chan || band != chan->band) ++ return false; ++ ++ control_freq = chan->center_freq; ++ chandef->chan = chan; ++ ++ if (control_freq >= 5955) ++ offset = control_freq - 5955; ++ else if (control_freq >= 5745) ++ offset = control_freq - 5745; ++ else if (control_freq >= 5180) ++ offset = control_freq - 5180; ++ offset /= 20; ++ ++ switch (operating_class) { ++ case 81: /* 2 GHz band; 20 MHz; channels 1..13 */ ++ case 82: /* 2 GHz band; 20 MHz; channel 14 */ ++ case 115: /* 5 GHz band; 20 MHz; channels 36,40,44,48 */ ++ case 118: /* 5 GHz band; 20 MHz; channels 52,56,60,64 */ ++ case 121: /* 5 GHz band; 20 MHz; channels 100..144 */ ++ case 124: /* 5 GHz band; 20 MHz; channels 149,153,157,161 */ ++ case 125: /* 5 GHz band; 20 MHz; channels 149..177 */ ++ case 131: /* 6 GHz band; 20 MHz; channels 1..233*/ ++ case 136: /* 6 GHz band; 20 MHz; channel 2 */ ++ chandef->center_freq1 = control_freq; ++ chandef->width = NL80211_CHAN_WIDTH_20; ++ return true; ++ case 83: /* 2 GHz band; 40 MHz; channels 1..9 */ ++ case 116: /* 5 GHz band; 40 MHz; channels 36,44 */ ++ case 119: /* 5 GHz band; 40 MHz; channels 52,60 */ ++ case 122: /* 5 GHz band; 40 MHz; channels 100,108,116,124,132,140 */ ++ case 126: /* 5 GHz band; 40 MHz; channels 149,157,165,173 */ ++ chandef->center_freq1 = control_freq + 10; ++ chandef->width = NL80211_CHAN_WIDTH_40; ++ return true; ++ case 84: /* 2 GHz band; 40 MHz; channels 5..13 */ ++ case 117: /* 5 GHz band; 40 MHz; channels 40,48 */ ++ case 120: /* 5 GHz band; 40 MHz; channels 56,64 */ ++ case 123: /* 5 GHz band; 40 MHz; channels 104,112,120,128,136,144 */ ++ case 127: /* 5 GHz band; 40 MHz; channels 153,161,169,177 */ ++ chandef->center_freq1 = control_freq - 10; ++ chandef->width = NL80211_CHAN_WIDTH_40; ++ return true; ++ case 132: /* 6 GHz band; 40 MHz; channels 1,5,..,229*/ ++ chandef->center_freq1 = control_freq + 10 - (offset & 1) * 20; ++ chandef->width = NL80211_CHAN_WIDTH_40; ++ return true; ++ case 128: /* 5 GHz band; 80 MHz; channels 36..64,100..144,149..177 */ ++ case 133: /* 6 GHz band; 80 MHz; channels 1,5,..,229 */ ++ chandef->center_freq1 = control_freq + 30 - (offset & 3) * 20; ++ chandef->width = NL80211_CHAN_WIDTH_80; ++ return true; ++ case 129: /* 5 GHz band; 160 MHz; channels 36..64,100..144,149..177 */ ++ case 134: /* 6 GHz band; 160 MHz; channels 1,5,..,229 */ ++ chandef->center_freq1 = control_freq + 70 - (offset & 7) * 20; ++ chandef->width = NL80211_CHAN_WIDTH_160; ++ return true; ++ case 130: /* 5 GHz band; 80+80 MHz; channels 36..64,100..144,149..177 */ ++ case 135: /* 6 GHz band; 80+80 MHz; channels 1,5,..,229 */ ++ /* The center_freq2 of 80+80 MHz is unknown */ ++ default: ++ return false; ++ } ++} ++EXPORT_SYMBOL(ieee80211_operating_class_to_chandef); ++ + bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, + u8 *op_class) + { +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0029-mac80211-mtk-send-4-addr-nullfunc-after-drv_event_ca.patch b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0029-mac80211-mtk-send-4-addr-nullfunc-after-drv_event_ca.patch new file mode 100644 index 000000000..981a5324e --- /dev/null +++ b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0029-mac80211-mtk-send-4-addr-nullfunc-after-drv_event_ca.patch @@ -0,0 +1,46 @@ +From 8cb06d601dff5b2728684f230ffe46d42e98cab3 Mon Sep 17 00:00:00 2001 +From: Peter Chiu +Date: Fri, 29 Mar 2024 14:55:41 +0800 +Subject: [PATCH] mac80211: mtk: send 4 addr nullfunc after drv_event_callback + +mt76 set channel in drv_event_callback and the 4 addr nullfunc may +be dropped. Send 4 addr nullfunc after drv_event_callback to avoid +this issue. + +Signed-off-by: Peter Chiu + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index ed81ebf..0f3d8cc 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3671,13 +3671,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + bss_conf->assoc_capability = capab_info; + ieee80211_set_associated(sdata, cbss, changed); + +- /* +- * If we're using 4-addr mode, let the AP know that we're +- * doing so, so that it can create the STA VLAN on its side +- */ +- if (ifmgd->use_4addr) +- ieee80211_send_4addr_nullfunc(local, sdata); +- + /* + * Start timer to probe the connection to the AP now. + * Also start the timer that will detect beacon loss. +@@ -3798,6 +3791,13 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + drv_event_callback(sdata->local, sdata, &event); + sdata_info(sdata, "associated\n"); + ++ /* ++ * If we're using 4-addr mode, let the AP know that we're ++ * doing so, so that it can create the STA VLAN on its side ++ */ ++ if (ifmgd->use_4addr) ++ ieee80211_send_4addr_nullfunc(sdata->local, sdata); ++ + /* + * destroy assoc_data afterwards, as otherwise an idle + * recalc after assoc_data is NULL but before associated +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0030-mac80211-mtk-fix-incorrect-VIF-assignment-for-IEEE-8.patch b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0030-mac80211-mtk-fix-incorrect-VIF-assignment-for-IEEE-8.patch new file mode 100644 index 000000000..60fa62b92 --- /dev/null +++ b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0030-mac80211-mtk-fix-incorrect-VIF-assignment-for-IEEE-8.patch @@ -0,0 +1,33 @@ +From 6f8a21b15ee4078ecf14c11a5cca0d8dee0bc474 Mon Sep 17 00:00:00 2001 +From: Benjamin Lin +Date: Wed, 3 Apr 2024 14:23:51 +0800 +Subject: [PATCH] mac80211: mtk: fix incorrect VIF assignment for IEEE 802.11 + fragments + +When in WDS mode (vif is AP_VLAN), only the first fragment would be dequeued from txq and go through some tx processing which includes the replacement of vif in CB(SKB) from the AP_VLAN one to the AP one. However, the rest of the fragments would be dequeued from txqi->frags and bypass this process which in turn results in different VIF assignment for softmac to fill in TXD. Therefore, we fix this by assigning the correct AP VIF to SKB_CB of the rest fragments. + +Signed-off-by: Benjamin Lin +--- + net/mac80211/tx.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 4085444..0577764 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3736,8 +3736,11 @@ begin: + skb = __skb_dequeue(&txqi->frags); + if (unlikely(skb)) { + if (!(IEEE80211_SKB_CB(skb)->control.flags & +- IEEE80211_TX_INTCFL_NEED_TXPROCESSING)) ++ IEEE80211_TX_INTCFL_NEED_TXPROCESSING)) { ++ // TODO: report airtime of non-first fragments. ++ IEEE80211_SKB_CB(skb)->control.vif = vif; + goto out; ++ } + IEEE80211_SKB_CB(skb)->control.flags &= + ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + } else { +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0031-mac80211-mtk-add-exported-function-for-SoftMAC-drive.patch b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0031-mac80211-mtk-add-exported-function-for-SoftMAC-drive.patch new file mode 100644 index 000000000..a26fc338b --- /dev/null +++ b/feeds/mediatek-sdk/mac80211/patches/subsys/mtk-0031-mac80211-mtk-add-exported-function-for-SoftMAC-drive.patch @@ -0,0 +1,58 @@ +From ac1e8443a250f418b6124e7b4f4ea65a03c4d02b Mon Sep 17 00:00:00 2001 +From: Benjamin Lin +Date: Fri, 26 Apr 2024 09:29:39 +0800 +Subject: [PATCH] mac80211: mtk: add exported function for SoftMAC driver to + get QoS map + +The mapping from IP DSCP to IEEE 802.11 user priority may be customized. +Therefore, driver needs to pass the mapping to HW, so that the QoS type of traffic can be mapped in a consistent manner for both SW and HW paths. + +Signed-off-by: Benjamin Lin +--- + include/net/mac80211.h | 12 ++++++++++++ + net/mac80211/util.c | 10 +++++++++- + 2 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 5c26752..420963f 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6942,4 +6942,16 @@ static inline bool ieee80211_is_tx_data(struct sk_buff *skb) + * @hw: pointer as obtained from ieee80211_alloc_hw() + */ + unsigned long ieee80211_get_scanning(struct ieee80211_hw *hw); ++ ++/** ++ * ieee80211_get_qos_map - get QoS mapping information. ++ * ++ * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * ++ * Return: Pointer to the QoS mapping information. ++ * ++ * Note that the return value is an RCU-protected pointer, so rcu_read_lock() ++ * must be held when calling this function. ++ */ ++struct cfg80211_qos_map *ieee80211_get_qos_map(struct ieee80211_vif *vif); + #endif /* MAC80211_H */ +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index e07fe73..865c4ac 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -4643,4 +4643,12 @@ unsigned long ieee80211_get_scanning(struct ieee80211_hw *hw) + + return local->scanning; + } +-EXPORT_SYMBOL(ieee80211_get_scanning); +\ No newline at end of file ++EXPORT_SYMBOL(ieee80211_get_scanning); ++ ++struct cfg80211_qos_map *ieee80211_get_qos_map(struct ieee80211_vif *vif) ++{ ++ struct mac80211_qos_map *qos_map = rcu_dereference(vif_to_sdata(vif)->qos_map); ++ ++ return qos_map ? &qos_map->qos_map : NULL; ++} ++EXPORT_SYMBOL(ieee80211_get_qos_map); +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mediatek/Makefile b/feeds/mediatek-sdk/mediatek/Makefile index 0be214f62..356298c45 100644 --- a/feeds/mediatek-sdk/mediatek/Makefile +++ b/feeds/mediatek-sdk/mediatek/Makefile @@ -11,6 +11,8 @@ FEATURES:=squashfs nand ramdisk fpu KERNEL_PATCHVER:=5.4 KERNEL_TESTING_PATCHVER:=5.4 +DEVICE_TYPE:=fw3 + PLATFORM_DIR:=${CURDIR} GENERIC_BACKPORT_DIR := $(PLATFORM_DIR)/backport-$(KERNEL_PATCHVER) GENERIC_PATCH_DIR := $(PLATFORM_DIR)/pending-$(KERNEL_PATCHVER) diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855-gsw.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855-gsw.dts new file mode 100644 index 000000000..3f0bb9033 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855-gsw.dts @@ -0,0 +1,295 @@ +/dts-v1/; +#include "mt7981.dtsi" +/ { + model = "MediaTek MT7981 RFB"; + compatible = "mediatek,mt7981-spim-snand-2500wan-an8855-gsw-rfb"; + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11002000"; + }; + + memory { + // fpga ddr2: 128MB*2 + reg = <0 0x40000000 0 0x10000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + }; + + nmbm_spim_nand { + compatible = "generic,nmbm"; + + #address-cells = <1>; + #size-cells = <1>; + + lower-mtd-device = <&spi_nand>; + forced-create; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; + + gsw: gsw@0 { + compatible = "airoha,an8855"; + #mediatek,ethsys = <ðsys>; + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + reset-gpios = <&pio 14 1>; + reset-delay-us = <600>; + + phy5: phy@5 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <5>; + }; + }; +}; + +&gsw { + airoha,mdio = <&mdio>; + airoha,portmap = "llllw"; + airoha,smi-addr = <6>; + reset-gpios = <&pio 39 0>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + status = "okay"; + + port5: port@5 { + compatible = "airoha,an8855-port"; + reg = <5>; + phy-mode = "2500base-x"; + /* airoha,stag-on = <1>; */ + + fixed-link { + speed = <2500>; + full-duplex; + }; + }; +}; + +&hnat { + mtketh-wan = "eth1"; + mtketh-lan = "eth0"; + mtketh-max-gmac = <2>; + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic_pins>; + status = "disabled"; + + slb9670: slb9670@0 { + compatible = "infineon,slb9670"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <2>; + spi-cal-data = /bits/ 8 <0x00 0x1b>; + spi-max-frequency = <20000000>; + }; +}; + +&wbsys { + mediatek,mtd-eeprom = <&factory 0x0000>; + status = "okay"; + pinctrl-names = "dbdc"; + pinctrl-0 = <&wf_dbdc_pins>; +}; + +&pio { + + i2c_pins: i2c-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_0"; + }; + }; + + pcm_pins: pcm-pins-g0 { + mux { + function = "pcm"; + groups = "pcm"; + }; + }; + + pwm0_pin: pwm0-pin-g0 { + mux { + function = "pwm"; + groups = "pwm0_0"; + }; + }; + + pwm1_pin: pwm1-pin-g0 { + mux { + function = "pwm"; + groups = "pwm1_0"; + }; + }; + + pwm2_pin: pwm2-pin { + mux { + function = "pwm"; + groups = "pwm2"; + }; + }; + + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + + spic_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1_1"; + }; + }; + + uart1_pins: uart1-pins-g1 { + mux { + function = "uart"; + groups = "uart1_1"; + }; + }; + + uart2_pins: uart2-pins-g1 { + mux { + function = "uart"; + groups = "uart2_1"; + }; + }; + + wf_dbdc_pins: wf_dbdc-pins { + mux { + function = "eth"; + groups = "wf0_mode1"; + }; + conf { + pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4", + "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6", + "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10", + "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ", + "WF_CBA_RESETB", "WF_DIG_RESETB"; + drive-strength = ; + }; + }; +}; + +&xhci { + status = "okay"; +}; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855.dts new file mode 100644 index 000000000..4697ef5eb --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855.dts @@ -0,0 +1,310 @@ +/dts-v1/; +#include "mt7981.dtsi" +/ { + model = "MediaTek MT7981 RFB"; + compatible = "mediatek,mt7981-spim-snand-2500wan-an8855-rfb"; + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11002000"; + }; + + memory { + // fpga ddr2: 128MB*2 + reg = <0 0x40000000 0 0x10000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + }; + + nmbm_spim_nand { + compatible = "generic,nmbm"; + + #address-cells = <1>; + #size-cells = <1>; + + lower-mtd-device = <&spi_nand>; + forced-create; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + reset-gpios = <&pio 14 1>; + reset-delay-us = <600>; + + phy5: phy@5 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <5>; + }; + + switch@0 { + compatible = "airoha,an8855"; + reg = <1>; + reset-gpios = <&pio 39 0>; + changesmiaddr = <6>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@5 { + reg = <5>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&hnat { + mtketh-wan = "eth1"; + mtketh-lan = "lan"; + mtketh-max-gmac = <2>; + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic_pins>; + status = "disabled"; + + slb9670: slb9670@0 { + compatible = "infineon,slb9670"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <2>; + spi-cal-data = /bits/ 8 <0x00 0x1b>; + spi-max-frequency = <20000000>; + }; +}; + +&wbsys { + mediatek,mtd-eeprom = <&factory 0x0000>; + status = "okay"; + pinctrl-names = "dbdc"; + pinctrl-0 = <&wf_dbdc_pins>; +}; + +&pio { + + i2c_pins: i2c-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_0"; + }; + }; + + pcm_pins: pcm-pins-g0 { + mux { + function = "pcm"; + groups = "pcm"; + }; + }; + + pwm0_pin: pwm0-pin-g0 { + mux { + function = "pwm"; + groups = "pwm0_0"; + }; + }; + + pwm1_pin: pwm1-pin-g0 { + mux { + function = "pwm"; + groups = "pwm1_0"; + }; + }; + + pwm2_pin: pwm2-pin { + mux { + function = "pwm"; + groups = "pwm2"; + }; + }; + + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + + spic_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1_1"; + }; + }; + + uart1_pins: uart1-pins-g1 { + mux { + function = "uart"; + groups = "uart1_1"; + }; + }; + + uart2_pins: uart2-pins-g1 { + mux { + function = "uart"; + groups = "uart2_1"; + }; + }; + + wf_dbdc_pins: wf_dbdc-pins { + mux { + function = "eth"; + groups = "wf0_mode1"; + }; + conf { + pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4", + "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6", + "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10", + "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ", + "WF_CBA_RESETB", "WF_DIG_RESETB"; + drive-strength = ; + }; + }; +}; + +&xhci { + status = "okay"; +}; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-rfb.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-rfb.dts index ac1b979d7..21e54f608 100755 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-rfb.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-rfb.dts @@ -10,7 +10,7 @@ memory { // fpga ddr2: 128MB*2 - reg = <0 0x40000000 0 0x20000000>; + reg = <0 0x40000000 0 0x10000000>; }; gpio-keys { @@ -123,12 +123,6 @@ status = "okay"; }; -&uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&uart2_pins>; - status = "okay"; -}; - &watchdog { status = "okay"; }; @@ -136,12 +130,17 @@ ð { status = "okay"; - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "sgmii"; - phy-handle = <&phy1>; // add phy handler - }; + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; gmac1: mac@1 { compatible = "mediatek,eth-mac"; @@ -162,15 +161,49 @@ nvmem-cell-names = "phy-cal-data"; }; - phy1: ethernet-phy@1 { - compatible = "ethernet-phy-id03a2.9471"; - reg = <24>; // set phy address to 0x18 - reset-gpios = <&pio 39 1>; - reset-assert-us = <600>; - reset-deassert-us = <20000>; - phy-mode = "sgmii"; - }; + switch@0 { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 0>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; }; }; @@ -221,24 +254,6 @@ pinctrl-0 = <&wf_dbdc_pins>; }; -&spi2 { - pinctrl-names = "default"; - pinctrl-0 = <&spi2_pins>; - status = "okay"; - - slb9670: slb9670@0 { - compatible = "infineon,slb9670"; - reg = <0>; /* CE0 */ - #address-cells = <1>; - #size-cells = <0>; - spi-cal-enable; - spi-cal-mode = "read-data"; - spi-cal-datalen = <2>; - spi-cal-data = /bits/ 8 <0x00 0x1b>; - spi-max-frequency = <40000000>; - }; -}; - &pio { i2c_pins: i2c-pins-g0 { @@ -302,13 +317,6 @@ }; }; - spi2_pins: spi2-pins { - mux { - function = "spi"; - groups = "spi2"; - }; - }; - uart1_pins: uart1-pins-g1 { mux { function = "uart"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-sfp.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-sfp.dts new file mode 100644 index 000000000..e0c116549 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-sfp.dts @@ -0,0 +1,319 @@ +/dts-v1/; +#include "mt7981.dtsi" +/ { + model = "MediaTek MT7981 RFB"; + compatible = "mediatek,mt7981-spim-snand-sfp"; + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11002000"; + }; + + memory { + // fpga ddr2: 128MB*2 + reg = <0 0x40000000 0 0x10000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + }; + + nmbm_spim_nand { + compatible = "generic,nmbm"; + + #address-cells = <1>; + #size-cells = <1>; + + lower-mtd-device = <&spi_nand>; + forced-create; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; + + sfp_cage1: sfp@1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + mod-def0-gpios = <&pio 25 1>; + los-gpios = <&pio 28 0>; + tx-disable-gpios = <&pio 27 0>; + }; +}; + +&uart0 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + managed = "in-band-status"; + sfp = <&sfp_cage1>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + reset-gpios = <&pio 14 1>; + reset-delay-us = <600>; + + switch@0 { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 0>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&hnat { + mtketh-wan = "eth1"; + mtketh-lan = "lan"; + mtketh-max-gmac = <2>; + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic_pins>; + status = "disabled"; + + slb9670: slb9670@0 { + compatible = "infineon,slb9670"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <2>; + spi-cal-data = /bits/ 8 <0x00 0x1b>; + spi-max-frequency = <20000000>; + }; +}; + +&wbsys { + mediatek,mtd-eeprom = <&factory 0x0000>; + status = "okay"; + pinctrl-names = "dbdc"; + pinctrl-0 = <&wf_dbdc_pins>; +}; + +&pio { + + i2c_pins: i2c-pins-g1 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + + pcm_pins: pcm-pins-g0 { + mux { + function = "pcm"; + groups = "pcm"; + }; + }; + + pwm0_pin: pwm0-pin-g0 { + mux { + function = "pwm"; + groups = "pwm0_0"; + }; + }; + + pwm1_pin: pwm1-pin-g0 { + mux { + function = "pwm"; + groups = "pwm1_0"; + }; + }; + + pwm2_pin: pwm2-pin { + mux { + function = "pwm"; + groups = "pwm2"; + }; + }; + + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + + spic_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1_1"; + }; + }; + + uart1_pins: uart1-pins-g1 { + mux { + function = "uart"; + groups = "uart1_1"; + }; + }; + + uart2_pins: uart2-pins-g1 { + mux { + function = "uart"; + groups = "uart2_1"; + }; + }; + + wf_dbdc_pins: wf_dbdc-pins { + mux { + function = "eth"; + groups = "wf0_mode1"; + }; + conf { + pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4", + "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6", + "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10", + "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ", + "WF_CBA_RESETB", "WF_DIG_RESETB"; + drive-strength = ; + }; + }; +}; + +&xhci { + status = "okay"; +}; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi index 620fff91e..0fd2d4764 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi @@ -585,6 +585,7 @@ interrupt-names = "ring0", "ring1", "ring2", "ring3"; status = "okay"; eth = <ð>; + hnat = <&hnat>; }; afe: audio-controller@11210000 { diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dts new file mode 100644 index 000000000..f07aa6ee0 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dts @@ -0,0 +1,703 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include +#include + +#include "mt7988.dtsi" + +/ { + model = "Bananapi BPI-R4"; + compatible = "bananapi,bpi-r4", "mediatek,mt7988a"; + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11000000 \ + earlyprintk pci=pcie_bus_perf \ + root=PARTLABEL=rootfs rootwait \ + rootfstype=squashfs,f2fs"; + }; + + memory { + reg = <0 0x40000000 0 0x10000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 14 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + blue { + label = "bpi-r4:pio:blue"; + gpios = <&pio 63 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green { + label = "bpi-r4:pio:green"; + gpios = <&pio 79 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + nmbm_spim_nand { + compatible = "generic,nmbm"; + + #address-cells = <1>; + #size-cells = <1>; + + lower-mtd-device = <&spi_nand>; + forced-create; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0400000>; + }; + + partition@580000 { + label = "FIP"; + reg = <0x580000 0x0200000>; + }; + }; + }; + + wsys_adie: wsys_adie@0 { + // fpga cases need to manual change adie_id / sku_type for dvt only + compatible = "mediatek,rebb-mt7988-adie"; + adie_id = <7976>; + sku_type = <3000>; + }; + + sfp_esp0: sfp@0 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sfp0>; + mod-def0-gpios = <&pio 82 1>; + los-gpios = <&pio 54 0>; + tx-disable-gpios = <&pio 70 0>; + maximum-power-milliwatt = <3000>; + }; + + sfp_esp1: sfp@1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sfp1>; + mod-def0-gpios = <&pio 83 1>; + los-gpios = <&pio 2 0>; + tx-disable-gpios = <&pio 0 0>; + maximum-power-milliwatt = <3000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&fan { + pwms = <&pwm 0 50000 0>; + status = "okay"; +}; + +&pwm { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "disabled"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "disabled"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + status = "okay"; + + pca9545@70 { + compatible = "nxp,pca9545"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + // MAC Address EEPROM + eeprom@57 { + compatible = "atmel,24c02"; + reg = <0x57>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + + // RTC AT8563 + rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; + }; + + i2c2_sfp0: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1>; + }; + + i2c2_sfp1: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + + // 5G WIFI MAC Address EEPROM + wifi_eeprom@51 { + compatible = "atmel,24c02"; + reg = <0x51>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + + // 6G WIFI MAC Address EEPROM + wifi_eeprom@52 { + compatible = "atmel,24c02"; + reg = <0x52>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&spi1 { + pinctrl-names = "default"; + /* pin shared with snfi */ + pinctrl-0 = <&spic_pins>; + status = "disabled"; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +&pcie2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_pins>; + status = "okay"; +}; + +&pcie3 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_pins>; + status = "okay"; +}; + +&pio { + /* GPIO 4 WIFI PWREN. output-high: enable, output-low: disable */ + asm_sel { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-high; + }; + + /* GPIO 5 PCA9545 RST PIN, output-high */ + pca9545_rst { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; + + mdio0_pins: mdio0-pins { + mux { + function = "mdio"; + groups = "mdc_mdio0"; + }; + + conf { + groups = "mdc_mdio0"; + drive-strength = ; + }; + }; + + gbe0_led0_pins: gbe0-pins { + mux { + function = "led"; + groups = "gbe0_led0"; + }; + }; + + gbe1_led0_pins: gbe1-pins { + mux { + function = "led"; + groups = "gbe1_led0"; + }; + }; + + gbe2_led0_pins: gbe2-pins { + mux { + function = "led"; + groups = "gbe2_led0"; + }; + }; + + gbe3_led0_pins: gbe3-pins { + mux { + function = "led"; + groups = "gbe3_led0"; + }; + }; + + i2p5gbe_led0_pins: 2p5gbe-pins { + mux { + function = "led"; + groups = "2p5gbe_led0"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0", + "pcie_wake_n0_0"; + }; + }; + + pcie1_pins: pcie1-pins { + mux { + function = "pcie"; + groups = "pcie_2l_1_pereset", "pcie_clk_req_n1", + "pcie_wake_n1_0"; + }; + }; + + pcie2_pins: pcie2-pins { + mux { + function = "pcie"; + groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0", + "pcie_wake_n2_0"; + }; + }; + + pcie3_pins: pcie3-pins { + mux { + function = "pcie"; + groups = "pcie_1l_1_pereset", "pcie_clk_req_n3", + "pcie_wake_n3_0"; + }; + }; + + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spic_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1"; + }; + }; + + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + + i2c1_pins: i2c1-pins { + mux { + function = "i2c"; + groups = "i2c1_0"; + }; + }; + + i2c2_pins: i2c2-pins { + mux { + function = "i2c"; + groups = "i2c2_1"; + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "tops_uart1_2"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + }; + + mmc0_pins_default: mmc0-pins-default { + mux { + function = "flash"; + groups = "emmc_51"; + }; + }; + + mmc0_pins_uhs: mmc0-pins-uhs { + mux { + function = "flash"; + groups = "emmc_51"; + }; + }; +}; + +&watchdog { + status = "disabled"; +}; + +&xhci0 { + status = "disabled"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio0_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + mac-type = "xgdm"; + phy-mode = "10gbase-kr"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + mac-type = "xgdm"; + + /* support internal 2.5G PHY Copper */ + //phy-mode = "xgmii"; + //phy-handle = <&phy0>; + + /* Support external 10G SFP+ Module */ + phy-mode = "10gbase-kr"; + managed = "in-band-status"; + sfp = <&sfp_esp1>; + }; + + gmac2: mac@2 { + compatible = "mediatek,eth-mac"; + reg = <2>; + mac-type = "xgdm"; + + /* Support external 10G SFP+ Module */ + phy-mode = "10gbase-kr"; + managed = "in-band-status"; + sfp = <&sfp_esp0>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <10500000>; + + phy0: ethernet-phy@0 { + pinctrl-names = "i2p5gbe-led"; + pinctrl-0 = <&i2p5gbe_led0_pins>; + reg = <15>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "xgmii"; + }; + + switch@0 { + compatible = "mediatek,mt7988"; + reg = <31>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan0"; + phy-mode = "gmii"; + phy-handle = <&sphy0>; + }; + + port@1 { + reg = <1>; + label = "lan1"; + phy-mode = "gmii"; + phy-handle = <&sphy1>; + }; + + port@2 { + reg = <2>; + label = "lan2"; + phy-mode = "gmii"; + phy-handle = <&sphy2>; + }; + + port@3 { + reg = <3>; + label = "lan3"; + phy-mode = "gmii"; + phy-handle = <&sphy3>; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "10gbase-kr"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + }; + + mdio { + compatible = "mediatek,dsa-slave-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + sphy0: switch_phy0@0 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <0>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe0_led0_pins>; + nvmem-cells = <&phy_calibration_p0>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy1: switch_phy1@1 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <1>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe1_led0_pins>; + nvmem-cells = <&phy_calibration_p1>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy2: switch_phy2@2 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <2>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe2_led0_pins>; + nvmem-cells = <&phy_calibration_p2>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy3: switch_phy3@3 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <3>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe3_led0_pins>; + nvmem-cells = <&phy_calibration_p3>; + nvmem-cell-names = "phy-cal-data"; + }; + }; + }; + }; +}; + +&hnat { + mtketh-wan = "eth2"; + mtketh-lan = "lan"; + mtketh-lan2 = "eth1"; + mtketh-max-gmac = <3>; + status = "okay"; +}; + +&crypto { + status = "disabled"; +}; + +&slot0 { + mt7996@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0>; + }; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x12814>; + vqmmc-supply = <®_1p8v>; + vmmc-supply = <®_3p3v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; +}; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-nand.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-nand.dts new file mode 100644 index 000000000..f4511b934 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-nand.dts @@ -0,0 +1,706 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include +#include + +#include "mt7988.dtsi" + +/ { + model = "Bananapi BPI-R4"; + compatible = "bananapi,bpi-r4", "mediatek,mt7988a"; + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11000000 \ + pci=pcie_bus_perf"; + }; + + memory { + reg = <0 0x40000000 0 0x10000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 14 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + blue { + label = "bpi-r4:pio:blue"; + gpios = <&pio 63 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green { + label = "bpi-r4:pio:green"; + gpios = <&pio 79 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + nmbm_spim_nand { + compatible = "generic,nmbm"; + + #address-cells = <1>; + #size-cells = <1>; + + lower-mtd-device = <&spi_nand>; + forced-create; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0400000>; + }; + + partition@580000 { + label = "FIP"; + reg = <0x580000 0x0200000>; + }; + + partition@780000 { + label = "ubi"; + reg = <0x780000 0x7080000>; + }; + }; + }; + + wsys_adie: wsys_adie@0 { + // fpga cases need to manual change adie_id / sku_type for dvt only + compatible = "mediatek,rebb-mt7988-adie"; + adie_id = <7976>; + sku_type = <3000>; + }; + + sfp_esp0: sfp@0 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sfp0>; + mod-def0-gpios = <&pio 82 1>; + los-gpios = <&pio 54 0>; + tx-disable-gpios = <&pio 70 0>; + maximum-power-milliwatt = <3000>; + }; + + sfp_esp1: sfp@1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sfp1>; + mod-def0-gpios = <&pio 83 1>; + los-gpios = <&pio 2 0>; + tx-disable-gpios = <&pio 0 0>; + maximum-power-milliwatt = <3000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&fan { + pwms = <&pwm 0 50000 0>; + status = "okay"; +}; + +&pwm { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "disabled"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "disabled"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + status = "okay"; + + pca9545@70 { + compatible = "nxp,pca9545"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + // MAC Address EEPROM + eeprom@57 { + compatible = "atmel,24c02"; + reg = <0x57>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + + // RTC AT8563 + rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; + }; + + i2c2_sfp0: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1>; + }; + + i2c2_sfp1: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + + // 5G WIFI MAC Address EEPROM + wifi_eeprom@51 { + compatible = "atmel,24c02"; + reg = <0x51>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + + // 6G WIFI MAC Address EEPROM + wifi_eeprom@52 { + compatible = "atmel,24c02"; + reg = <0x52>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&spi1 { + pinctrl-names = "default"; + /* pin shared with snfi */ + pinctrl-0 = <&spic_pins>; + status = "disabled"; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +&pcie2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_pins>; + status = "okay"; +}; + +&pcie3 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_pins>; + status = "okay"; +}; + +&pio { + /* GPIO 4 WIFI PWREN. output-high: enable, output-low: disable */ + asm_sel { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-high; + }; + + /* GPIO 5 PCA9545 RST PIN, output-high */ + pca9545_rst { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; + + mdio0_pins: mdio0-pins { + mux { + function = "mdio"; + groups = "mdc_mdio0"; + }; + + conf { + groups = "mdc_mdio0"; + drive-strength = ; + }; + }; + + gbe0_led0_pins: gbe0-pins { + mux { + function = "led"; + groups = "gbe0_led0"; + }; + }; + + gbe1_led0_pins: gbe1-pins { + mux { + function = "led"; + groups = "gbe1_led0"; + }; + }; + + gbe2_led0_pins: gbe2-pins { + mux { + function = "led"; + groups = "gbe2_led0"; + }; + }; + + gbe3_led0_pins: gbe3-pins { + mux { + function = "led"; + groups = "gbe3_led0"; + }; + }; + + i2p5gbe_led0_pins: 2p5gbe-pins { + mux { + function = "led"; + groups = "2p5gbe_led0"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0", + "pcie_wake_n0_0"; + }; + }; + + pcie1_pins: pcie1-pins { + mux { + function = "pcie"; + groups = "pcie_2l_1_pereset", "pcie_clk_req_n1", + "pcie_wake_n1_0"; + }; + }; + + pcie2_pins: pcie2-pins { + mux { + function = "pcie"; + groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0", + "pcie_wake_n2_0"; + }; + }; + + pcie3_pins: pcie3-pins { + mux { + function = "pcie"; + groups = "pcie_1l_1_pereset", "pcie_clk_req_n3", + "pcie_wake_n3_0"; + }; + }; + + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spic_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1"; + }; + }; + + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + + i2c1_pins: i2c1-pins { + mux { + function = "i2c"; + groups = "i2c1_0"; + }; + }; + + i2c2_pins: i2c2-pins { + mux { + function = "i2c"; + groups = "i2c2_1"; + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "tops_uart1_2"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + }; + + mmc0_pins_default: mmc0-pins-default { + mux { + function = "flash"; + groups = "emmc_51"; + }; + }; + + mmc0_pins_uhs: mmc0-pins-uhs { + mux { + function = "flash"; + groups = "emmc_51"; + }; + }; +}; + +&watchdog { + status = "disabled"; +}; + +&xhci0 { + status = "disabled"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio0_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + mac-type = "xgdm"; + phy-mode = "10gbase-kr"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + mac-type = "xgdm"; + + /* support internal 2.5G PHY Copper */ + //phy-mode = "xgmii"; + //phy-handle = <&phy0>; + + /* Support external 10G SFP+ Module */ + phy-mode = "10gbase-kr"; + managed = "in-band-status"; + sfp = <&sfp_esp1>; + }; + + gmac2: mac@2 { + compatible = "mediatek,eth-mac"; + reg = <2>; + mac-type = "xgdm"; + + /* Support external 10G SFP+ Module */ + phy-mode = "10gbase-kr"; + managed = "in-band-status"; + sfp = <&sfp_esp0>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <10500000>; + + phy0: ethernet-phy@0 { + pinctrl-names = "i2p5gbe-led"; + pinctrl-0 = <&i2p5gbe_led0_pins>; + reg = <15>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "xgmii"; + }; + + switch@0 { + compatible = "mediatek,mt7988"; + reg = <31>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan0"; + phy-mode = "gmii"; + phy-handle = <&sphy0>; + }; + + port@1 { + reg = <1>; + label = "lan1"; + phy-mode = "gmii"; + phy-handle = <&sphy1>; + }; + + port@2 { + reg = <2>; + label = "lan2"; + phy-mode = "gmii"; + phy-handle = <&sphy2>; + }; + + port@3 { + reg = <3>; + label = "lan3"; + phy-mode = "gmii"; + phy-handle = <&sphy3>; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "10gbase-kr"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + }; + + mdio { + compatible = "mediatek,dsa-slave-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + sphy0: switch_phy0@0 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <0>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe0_led0_pins>; + nvmem-cells = <&phy_calibration_p0>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy1: switch_phy1@1 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <1>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe1_led0_pins>; + nvmem-cells = <&phy_calibration_p1>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy2: switch_phy2@2 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <2>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe2_led0_pins>; + nvmem-cells = <&phy_calibration_p2>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy3: switch_phy3@3 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <3>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe3_led0_pins>; + nvmem-cells = <&phy_calibration_p3>; + nvmem-cell-names = "phy-cal-data"; + }; + }; + }; + }; +}; + +&hnat { + mtketh-wan = "eth2"; + mtketh-lan = "lan"; + mtketh-lan2 = "eth1"; + mtketh-max-gmac = <3>; + status = "okay"; +}; + +&crypto { + status = "disabled"; +}; + +&slot0 { + mt7996@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0>; + }; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x12814>; + vqmmc-supply = <®_1p8v>; + vmmc-supply = <®_3p3v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; +}; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dts new file mode 100644 index 000000000..ef6e6ec59 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dts @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include +#include + +#include "mt7988.dtsi" + +/ { + model = "Bananapi BPI-R4"; + compatible = "bananapi,bpi-r4", "mediatek,mt7988a"; + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11000000 \ + earlyprintk pci=pcie_bus_perf \ + root=PARTLABEL=rootfs rootwait \ + rootfstype=squashfs,f2fs"; + }; + + memory { + reg = <0 0x40000000 0 0x10000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 14 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + blue { + label = "bpi-r4:pio:blue"; + gpios = <&pio 63 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green { + label = "bpi-r4:pio:green"; + gpios = <&pio 79 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + nmbm_spim_nand { + compatible = "generic,nmbm"; + + #address-cells = <1>; + #size-cells = <1>; + + lower-mtd-device = <&spi_nand>; + forced-create; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0400000>; + }; + + partition@580000 { + label = "FIP"; + reg = <0x580000 0x0200000>; + }; + }; + }; + + wsys_adie: wsys_adie@0 { + // fpga cases need to manual change adie_id / sku_type for dvt only + compatible = "mediatek,rebb-mt7988-adie"; + adie_id = <7976>; + sku_type = <3000>; + }; + + sfp_esp0: sfp@0 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sfp0>; + mod-def0-gpios = <&pio 82 1>; + los-gpios = <&pio 54 0>; + tx-disable-gpios = <&pio 70 0>; + maximum-power-milliwatt = <3000>; + }; + + sfp_esp1: sfp@1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sfp1>; + mod-def0-gpios = <&pio 83 1>; + los-gpios = <&pio 2 0>; + tx-disable-gpios = <&pio 0 0>; + maximum-power-milliwatt = <3000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&fan { + pwms = <&pwm 0 50000 0>; + status = "okay"; +}; + +&pwm { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "disabled"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "disabled"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + status = "okay"; + + pca9545@70 { + compatible = "nxp,pca9545"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + // MAC Address EEPROM + eeprom@57 { + compatible = "atmel,24c02"; + reg = <0x57>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + + // RTC AT8563 + rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; + }; + + i2c2_sfp0: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1>; + }; + + i2c2_sfp1: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + + // 5G WIFI MAC Address EEPROM + wifi_eeprom@51 { + compatible = "atmel,24c02"; + reg = <0x51>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + + // 6G WIFI MAC Address EEPROM + wifi_eeprom@52 { + compatible = "atmel,24c02"; + reg = <0x52>; + + address-bits = <8>; + page-size = <8>; + size = <256>; + }; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&spi1 { + pinctrl-names = "default"; + /* pin shared with snfi */ + pinctrl-0 = <&spic_pins>; + status = "disabled"; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +&pcie2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_pins>; + status = "okay"; +}; + +&pcie3 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_pins>; + status = "okay"; +}; + +&pio { + /* GPIO 4 WIFI PWREN. output-high: enable, output-low: disable */ + asm_sel { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-high; + }; + + /* GPIO 5 PCA9545 RST PIN, output-high */ + pca9545_rst { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; + + mdio0_pins: mdio0-pins { + mux { + function = "mdio"; + groups = "mdc_mdio0"; + }; + + conf { + groups = "mdc_mdio0"; + drive-strength = ; + }; + }; + + gbe0_led0_pins: gbe0-pins { + mux { + function = "led"; + groups = "gbe0_led0"; + }; + }; + + gbe1_led0_pins: gbe1-pins { + mux { + function = "led"; + groups = "gbe1_led0"; + }; + }; + + gbe2_led0_pins: gbe2-pins { + mux { + function = "led"; + groups = "gbe2_led0"; + }; + }; + + gbe3_led0_pins: gbe3-pins { + mux { + function = "led"; + groups = "gbe3_led0"; + }; + }; + + i2p5gbe_led0_pins: 2p5gbe-pins { + mux { + function = "led"; + groups = "2p5gbe_led0"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0", + "pcie_wake_n0_0"; + }; + }; + + pcie1_pins: pcie1-pins { + mux { + function = "pcie"; + groups = "pcie_2l_1_pereset", "pcie_clk_req_n1", + "pcie_wake_n1_0"; + }; + }; + + pcie2_pins: pcie2-pins { + mux { + function = "pcie"; + groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0", + "pcie_wake_n2_0"; + }; + }; + + pcie3_pins: pcie3-pins { + mux { + function = "pcie"; + groups = "pcie_1l_1_pereset", "pcie_clk_req_n3", + "pcie_wake_n3_0"; + }; + }; + + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spic_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1"; + }; + }; + + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + + i2c1_pins: i2c1-pins { + mux { + function = "i2c"; + groups = "i2c1_0"; + }; + }; + + i2c2_pins: i2c2-pins { + mux { + function = "i2c"; + groups = "i2c2_1"; + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "tops_uart1_2"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + }; + + mmc0_pins_default: mmc0-pins-default { + mux { + function = "flash"; + groups = "sdcard"; + }; + }; + + mmc0_pins_uhs: mmc0-pins-uhs { + mux { + function = "flash"; + groups = "sdcard"; + }; + }; +}; + +&watchdog { + status = "disabled"; +}; + +&xhci0 { + status = "disabled"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio0_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + mac-type = "xgdm"; + phy-mode = "10gbase-kr"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + mac-type = "xgdm"; + + /* support internal 2.5G PHY Copper */ + //phy-mode = "xgmii"; + //phy-handle = <&phy0>; + + /* Support external 10G SFP+ Module */ + phy-mode = "10gbase-kr"; + managed = "in-band-status"; + sfp = <&sfp_esp1>; + }; + + gmac2: mac@2 { + compatible = "mediatek,eth-mac"; + reg = <2>; + mac-type = "xgdm"; + + /* Support external 10G SFP+ Module */ + phy-mode = "10gbase-kr"; + managed = "in-band-status"; + sfp = <&sfp_esp0>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <10500000>; + + phy0: ethernet-phy@0 { + pinctrl-names = "i2p5gbe-led"; + pinctrl-0 = <&i2p5gbe_led0_pins>; + reg = <15>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "xgmii"; + }; + + switch@0 { + compatible = "mediatek,mt7988"; + reg = <31>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan0"; + phy-mode = "gmii"; + phy-handle = <&sphy0>; + }; + + port@1 { + reg = <1>; + label = "lan1"; + phy-mode = "gmii"; + phy-handle = <&sphy1>; + }; + + port@2 { + reg = <2>; + label = "lan2"; + phy-mode = "gmii"; + phy-handle = <&sphy2>; + }; + + port@3 { + reg = <3>; + label = "lan3"; + phy-mode = "gmii"; + phy-handle = <&sphy3>; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "10gbase-kr"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + }; + + mdio { + compatible = "mediatek,dsa-slave-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + sphy0: switch_phy0@0 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <0>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe0_led0_pins>; + nvmem-cells = <&phy_calibration_p0>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy1: switch_phy1@1 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <1>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe1_led0_pins>; + nvmem-cells = <&phy_calibration_p1>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy2: switch_phy2@2 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <2>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe2_led0_pins>; + nvmem-cells = <&phy_calibration_p2>; + nvmem-cell-names = "phy-cal-data"; + }; + + sphy3: switch_phy3@3 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <3>; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe3_led0_pins>; + nvmem-cells = <&phy_calibration_p3>; + nvmem-cell-names = "phy-cal-data"; + }; + }; + }; + }; +}; + +&hnat { + mtketh-wan = "eth2"; + mtketh-lan = "lan"; + mtketh-lan2 = "eth1"; + mtketh-max-gmac = <3>; + status = "okay"; +}; + +&crypto { + status = "disabled"; +}; + +&slot0 { + mt7996@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0>; + }; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <4>; + max-frequency = <52000000>; + cap-sd-highspeed; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_3p3v>; + no-mmc; + no-sdio; + status = "okay"; +}; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts index 5a12bf9f0..1fb43e55e 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts @@ -63,6 +63,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -137,6 +189,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts index f175a27dd..c41aa5717 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts @@ -54,6 +54,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -128,6 +180,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts index a4a61d6fe..7881834ca 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts @@ -88,6 +88,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -162,6 +214,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts index a22af2966..2fa9f5daa 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts @@ -45,6 +45,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -162,6 +214,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts index f13573c41..2f32e4544 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts @@ -67,6 +67,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -148,6 +200,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts index 858c3e064..d7e41c5b3 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts @@ -58,6 +58,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -139,6 +191,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts index f7c233823..f3cee2ba4 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts @@ -92,6 +92,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -173,6 +225,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts index effcfd84c..be66a65ce 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts @@ -49,6 +49,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -173,6 +225,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts index 508ee7be8..71c2e3dd8 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts +++ b/feeds/mediatek-sdk/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts @@ -67,6 +67,58 @@ status = "okay"; }; +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck3 { + regulator-name = "proc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; +}; + &spi1 { pinctrl-names = "default"; /* pin shared with snfi */ @@ -148,6 +200,13 @@ }; }; + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + pcie0_pins: pcie0-pins { mux { function = "pcie"; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/Makefile b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/Makefile index b725c38b0..f3f3692ee 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/Makefile +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_MTK_ICE_DEBUG) += ice_debug/ obj-y += infra_bus_prot/ +obj-y += reset-boot-count/ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/Makefile b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/Makefile new file mode 100644 index 000000000..a8c3756ae --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/Makefile @@ -0,0 +1,2 @@ + +obj-y := reset-boot-count.o diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/reset-boot-count.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/reset-boot-count.c new file mode 100644 index 000000000..2b82d89c7 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/reset-boot-count.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (C) 2024 MediaTek Inc. All rights reserved. + * + * Helper for resetting boot count of A/B boot systems + * + * Author: Weijie Gao + */ + +#include +#include +#include +#include +#include +#include +#include + +#define RBC "reset_boot_count" + +#define MTK_SIP_READ_NONRST_REG 0xC2000550 +#define MTK_SIP_WRITE_NONRST_REG 0xC2000551 + +static struct proc_dir_entry *rbc_entry; + +static bool dual_boot_get_boot_count(u32 *retslot, u32 *retcnt) +{ + struct arm_smccc_res res = {0}; + u32 val, slot; + s8 neg, pos; + + arm_smccc_smc(MTK_SIP_READ_NONRST_REG, 0, 0, 0, 0, 0, 0, 0, &res); + + val = (u32)res.a0; + + /* slot: val[31..24] = -slot, val[23..16] = slot */ + pos = (val >> 16) & 0xff; + neg = (val >> 24) & 0xff; + + if (!(pos >= 0 && neg <= 0 && pos + neg == 0)) { + pr_debug("slot of boot count is invalid\n"); + goto err; + } + + slot = pos; + + /* count: val[15..8] = -count, val[7..0] = count */ + pos = val & 0xff; + neg = (val >> 8) & 0xff; + + if (!(pos >= 0 && neg <= 0 && pos + neg == 0)) { + pr_debug("count of boot count is invalid\n"); + goto err; + } + + if (retslot) + *retslot = slot; + + if (retcnt) + *retcnt = pos; + + return true; + +err: + if (retslot) + *retslot = 0; + + if (retcnt) + *retcnt = 0; + + return false; +} + +static void dual_boot_set_boot_count(u32 slot, u32 count) +{ + struct arm_smccc_res res = {0}; + u32 val; + s32 neg; + + if (slot > 127 || count > 127) + return; + + neg = -count; + val = count | ((neg << 8) & 0xff00); + + neg = -slot; + val = val | ((uint32_t)slot << 16) | ((neg << 24) & 0xff000000); + + arm_smccc_smc(MTK_SIP_WRITE_NONRST_REG, 0, val, 0, 0, 0, 0, 0, &res); +} + +static int rbc_display(struct seq_file *seq, void *v) +{ + return 0; +} + +static int rbc_open(struct inode *inode, struct file *file) +{ + return single_open(file, rbc_display, inode->i_private); +} + +static ssize_t rbc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + u32 slot; + + dual_boot_get_boot_count(&slot, NULL); + dual_boot_set_boot_count(slot, 0); + + pr_info("Boot count reset\n"); + + return count; +} + +static const struct file_operations rbc_fops = +{ + .open = rbc_open, + .read = seq_read, + .write = rbc_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init rbc_init(void) +{ + rbc_entry = proc_create(RBC, 0200, NULL, &rbc_fops); + + if (!rbc_entry) + pr_err("failed to create proc entry " RBC); + + return 0; +} + +static void __exit rbc_exit(void) +{ + remove_proc_entry(RBC, NULL); +} + +module_init(rbc_init); +module_exit(rbc_exit); + +MODULE_AUTHOR("Weijie Gao "); +MODULE_DESCRIPTION("Kernel module for resetting boot count of A/B boot systems"); +MODULE_LICENSE("BSD"); diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Kconfig b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Kconfig new file mode 100644 index 000000000..fc00f75d1 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Kconfig @@ -0,0 +1,10 @@ + +config NET_DSA_AN8855 + tristate "Airoha AN8855 Ethernet switch support" + depends on NET_DSA + select NET_DSA_TAG_AIROHA + help + AN8855 support 2.5G speed and managed by SMI interface. + This enables support for the Airoha AN8855 Ethernet switch + chip. + To compile this driver as a module, choose M here. diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Makefile b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Makefile new file mode 100644 index 000000000..99c99bd6c --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Airoha AN8855 gigabit switch +# +obj-$(CONFIG_NET_DSA_AN8855) += an8855-dsa.o +an8855-dsa-objs := an8855.o an8855_nl.o an8855_phy.o diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.c new file mode 100644 index 000000000..b0ba4be0a --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.c @@ -0,0 +1,2358 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Airoha AN8855 DSA Switch driver + * Copyright (C) 2023 Min Yao + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "an8855.h" +#include "an8855_nl.h" + +/* AN8855 driver version */ +#define ARHT_AN8855_DSA_DRIVER_VER "1.0.1-L5.4" + +/* String, offset, and register size in bytes if different from 4 bytes */ +static const struct an8855_mib_desc an8855_mib[] = { + MIB_DESC(1, 0x00, "TxDrop"), + MIB_DESC(1, 0x04, "TxCrcErr"), + MIB_DESC(1, 0x08, "TxUnicast"), + MIB_DESC(1, 0x0c, "TxMulticast"), + MIB_DESC(1, 0x10, "TxBroadcast"), + MIB_DESC(1, 0x14, "TxCollision"), + MIB_DESC(1, 0x18, "TxSingleCollision"), + MIB_DESC(1, 0x1c, "TxMultipleCollision"), + MIB_DESC(1, 0x20, "TxDeferred"), + MIB_DESC(1, 0x24, "TxLateCollision"), + MIB_DESC(1, 0x28, "TxExcessiveCollistion"), + MIB_DESC(1, 0x2c, "TxPause"), + MIB_DESC(1, 0x30, "TxPktSz64"), + MIB_DESC(1, 0x34, "TxPktSz65To127"), + MIB_DESC(1, 0x38, "TxPktSz128To255"), + MIB_DESC(1, 0x3c, "TxPktSz256To511"), + MIB_DESC(1, 0x40, "TxPktSz512To1023"), + MIB_DESC(1, 0x44, "TxPktSz1024To1518"), + MIB_DESC(1, 0x48, "TxPktSz1519ToMax"), + MIB_DESC(2, 0x4c, "TxBytes"), + MIB_DESC(1, 0x54, "TxOversizeDrop"), + MIB_DESC(2, 0x58, "TxBadPktBytes"), + MIB_DESC(1, 0x80, "RxDrop"), + MIB_DESC(1, 0x84, "RxFiltering"), + MIB_DESC(1, 0x88, "RxUnicast"), + MIB_DESC(1, 0x8c, "RxMulticast"), + MIB_DESC(1, 0x90, "RxBroadcast"), + MIB_DESC(1, 0x94, "RxAlignErr"), + MIB_DESC(1, 0x98, "RxCrcErr"), + MIB_DESC(1, 0x9c, "RxUnderSizeErr"), + MIB_DESC(1, 0xa0, "RxFragErr"), + MIB_DESC(1, 0xa4, "RxOverSzErr"), + MIB_DESC(1, 0xa8, "RxJabberErr"), + MIB_DESC(1, 0xac, "RxPause"), + MIB_DESC(1, 0xb0, "RxPktSz64"), + MIB_DESC(1, 0xb4, "RxPktSz65To127"), + MIB_DESC(1, 0xb8, "RxPktSz128To255"), + MIB_DESC(1, 0xbc, "RxPktSz256To511"), + MIB_DESC(1, 0xc0, "RxPktSz512To1023"), + MIB_DESC(1, 0xc4, "RxPktSz1024To1518"), + MIB_DESC(1, 0xc8, "RxPktSz1519ToMax"), + MIB_DESC(2, 0xcc, "RxBytes"), + MIB_DESC(1, 0xd4, "RxCtrlDrop"), + MIB_DESC(1, 0xd8, "RxIngressDrop"), + MIB_DESC(1, 0xdc, "RxArlDrop"), + MIB_DESC(1, 0xe0, "FlowControlDrop"), + MIB_DESC(1, 0xe4, "WredDrop"), + MIB_DESC(1, 0xe8, "MirrorDrop"), + MIB_DESC(2, 0xec, "RxBadPktBytes"), + MIB_DESC(1, 0xf4, "RxsFlowSamplingPktDrop"), + MIB_DESC(1, 0xf8, "RxsFlowTotalPktDrop"), + MIB_DESC(1, 0xfc, "PortControlDrop"), +}; + +static int +an8855_mii_write(struct an8855_priv *priv, u32 reg, u32 val) +{ + struct mii_bus *bus = priv->bus; + int ret = 0; + + ret = bus->write(bus, priv->phy_base, 0x1f, 0x4); + ret = bus->write(bus, priv->phy_base, 0x10, 0); + + ret = bus->write(bus, priv->phy_base, 0x11, ((reg >> 16) & 0xFFFF)); + ret = bus->write(bus, priv->phy_base, 0x12, (reg & 0xFFFF)); + + ret = bus->write(bus, priv->phy_base, 0x13, ((val >> 16) & 0xFFFF)); + ret = bus->write(bus, priv->phy_base, 0x14, (val & 0xFFFF)); + + ret = bus->write(bus, priv->phy_base, 0x1f, 0); + ret = bus->write(bus, priv->phy_base, 0x10, 0); + + if (ret < 0) { + dev_err(&bus->dev, "failed to write an8855 register\n"); + return ret; + } + + return ret; +} + +static u32 +an8855_mii_read(struct an8855_priv *priv, u32 reg) +{ + struct mii_bus *bus = priv->bus; + u16 lo, hi; + int ret; + + ret = bus->write(bus, priv->phy_base, 0x1f, 0x4); + ret = bus->write(bus, priv->phy_base, 0x10, 0); + + ret = bus->write(bus, priv->phy_base, 0x15, ((reg >> 16) & 0xFFFF)); + ret = bus->write(bus, priv->phy_base, 0x16, (reg & 0xFFFF)); + if (ret < 0) { + dev_err(&bus->dev, "failed to read an8855 register\n"); + return ret; + } + + lo = bus->read(bus, priv->phy_base, 0x18); + hi = bus->read(bus, priv->phy_base, 0x17); + + ret = bus->write(bus, priv->phy_base, 0x1f, 0); + ret = bus->write(bus, priv->phy_base, 0x10, 0); + if (ret < 0) { + dev_err(&bus->dev, "failed to read an8855 register\n"); + return ret; + } + + return (hi << 16) | (lo & 0xffff); +} + +void +an8855_write(struct an8855_priv *priv, u32 reg, u32 val) +{ + struct mii_bus *bus = priv->bus; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + + an8855_mii_write(priv, reg, val); + + mutex_unlock(&bus->mdio_lock); +} + +static u32 +_an8855_read(struct an8855_dummy_poll *p) +{ + struct mii_bus *bus = p->priv->bus; + u32 val; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + + val = an8855_mii_read(p->priv, p->reg); + + mutex_unlock(&bus->mdio_lock); + + return val; +} + +u32 +an8855_read(struct an8855_priv *priv, u32 reg) +{ + struct an8855_dummy_poll p; + + INIT_AN8855_DUMMY_POLL(&p, priv, reg); + return _an8855_read(&p); +} + +static void +an8855_rmw(struct an8855_priv *priv, u32 reg, u32 mask, u32 set) +{ + struct mii_bus *bus = priv->bus; + u32 val; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + + val = an8855_mii_read(priv, reg); + val &= ~mask; + val |= set; + an8855_mii_write(priv, reg, val); + + mutex_unlock(&bus->mdio_lock); +} + +static void +an8855_set(struct an8855_priv *priv, u32 reg, u32 val) +{ + an8855_rmw(priv, reg, 0, val); +} + +static void +an8855_clear(struct an8855_priv *priv, u32 reg, u32 val) +{ + an8855_rmw(priv, reg, val, 0); +} + +static int +an8855_fdb_cmd(struct an8855_priv *priv, u32 cmd, u32 *rsp) +{ + u32 val; + int ret; + struct an8855_dummy_poll p; + + /* Set the command operating upon the MAC address entries */ + val = ATC_BUSY | cmd; + an8855_write(priv, AN8855_ATC, val); + + INIT_AN8855_DUMMY_POLL(&p, priv, AN8855_ATC); + ret = readx_poll_timeout(_an8855_read, &p, val, + !(val & ATC_BUSY), 20, 200000); + if (ret < 0) { + dev_err(priv->dev, "reset timeout\n"); + return ret; + } + + if (rsp) + *rsp = val; + + return 0; +} + +static void +an8855_fdb_read(struct an8855_priv *priv, struct an8855_fdb *fdb) +{ + u32 reg[4]; + int i; + + /* Read from ARL table into an array */ + for (i = 0; i < 4; i++) + reg[i] = an8855_read(priv, AN8855_ATRD0 + (i * 4)); + + fdb->live = reg[0] & 0x1; + fdb->type = (reg[0] >> 3) & 0x3; + fdb->ivl = (reg[0] >> 9) & 0x1; + fdb->vid = (reg[0] >> 10) & 0xfff; + fdb->fid = (reg[0] >> 25) & 0xf; + fdb->aging = (reg[1] >> 3) & 0x1ff; + fdb->port_mask = reg[3] & 0xff; + fdb->mac[0] = (reg[2] >> MAC_BYTE_0) & MAC_BYTE_MASK; + fdb->mac[1] = (reg[2] >> MAC_BYTE_1) & MAC_BYTE_MASK; + fdb->mac[2] = (reg[2] >> MAC_BYTE_2) & MAC_BYTE_MASK; + fdb->mac[3] = (reg[2] >> MAC_BYTE_3) & MAC_BYTE_MASK; + fdb->mac[4] = (reg[1] >> MAC_BYTE_4) & MAC_BYTE_MASK; + fdb->mac[5] = (reg[1] >> MAC_BYTE_5) & MAC_BYTE_MASK; + fdb->noarp = !!((reg[0] >> 1) & 0x3); +} + +static void +an8855_fdb_write(struct an8855_priv *priv, u16 vid, + u8 port_mask, const u8 *mac, u8 add) +{ + u32 reg = 0; + + reg |= mac[3] << MAC_BYTE_3; + reg |= mac[2] << MAC_BYTE_2; + reg |= mac[1] << MAC_BYTE_1; + reg |= mac[0] << MAC_BYTE_0; + an8855_write(priv, AN8855_ATA1, reg); + reg = 0; + reg |= mac[5] << MAC_BYTE_5; + reg |= mac[4] << MAC_BYTE_4; + an8855_write(priv, AN8855_ATA2, reg); + reg = 0; + if (add) + reg |= 0x1; + reg |= 0x1 << 15; + reg |= vid << 16; + an8855_write(priv, AN8855_ATWD, reg); + an8855_write(priv, AN8855_ATWD2, port_mask); +} + +static int +an8855_pad_setup(struct dsa_switch *ds, phy_interface_t interface) +{ + return 0; +} + +static void +an8855_mib_reset(struct dsa_switch *ds) +{ + struct an8855_priv *priv = ds->priv; + + an8855_write(priv, AN8855_MIB_CCR, CCR_MIB_FLUSH); + an8855_write(priv, AN8855_MIB_CCR, CCR_MIB_ACTIVATE); +} + +static int +an8855_cl22_read(struct an8855_priv *priv, int port, int regnum) +{ + return mdiobus_read_nested(priv->bus, port, regnum); +} + +static int +an8855_cl22_write(struct an8855_priv *priv, int port, int regnum, u16 val) +{ + return mdiobus_write_nested(priv->bus, port, regnum, val); +} + +static int +an8855_phy_read(struct dsa_switch *ds, int port, int regnum) +{ + struct an8855_priv *priv = ds->priv; + + port += priv->phy_base; + return an8855_cl22_read(ds->priv, port, regnum); +} + +static int +an8855_phy_write(struct dsa_switch *ds, int port, int regnum, + u16 val) +{ + struct an8855_priv *priv = ds->priv; + + port += priv->phy_base; + return an8855_cl22_write(ds->priv, port, regnum, val); +} + +static int +an8855_cl45_read(struct an8855_priv *priv, int port, int devad, int regnum) +{ + regnum = MII_ADDR_C45 | (devad << 16) | regnum; + return mdiobus_read_nested(priv->bus, port, regnum); +} + +static int +an8855_cl45_write(struct an8855_priv *priv, int port, int devad, int regnum, + u16 val) +{ + regnum = MII_ADDR_C45 | (devad << 16) | regnum; + return mdiobus_write_nested(priv->bus, port, regnum, val); +} + +int +an8855_phy_cl22_read(struct an8855_priv *priv, int port, int regnum) +{ + port += priv->phy_base; + return an8855_cl22_read(priv, port, regnum); +} + +int +an8855_phy_cl22_write(struct an8855_priv *priv, int port, int regnum, + u16 val) +{ + port += priv->phy_base; + return an8855_cl22_write(priv, port, regnum, val); +} + +int +an8855_phy_cl45_read(struct an8855_priv *priv, int port, int devad, int regnum) +{ + port += priv->phy_base; + return an8855_cl45_read(priv, port, devad, regnum); +} + +int +an8855_phy_cl45_write(struct an8855_priv *priv, int port, int devad, int regnum, + u16 val) +{ + port += priv->phy_base; + return an8855_cl45_write(priv, port, devad, regnum, val); +} + +static void +an8855_get_strings(struct dsa_switch *ds, int port, u32 stringset, + uint8_t *data) +{ + int i; + + if (stringset != ETH_SS_STATS) + return; + + for (i = 0; i < ARRAY_SIZE(an8855_mib); i++) + strncpy(data + i * ETH_GSTRING_LEN, an8855_mib[i].name, + ETH_GSTRING_LEN); +} + +static void +an8855_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) +{ + struct an8855_priv *priv = ds->priv; + const struct an8855_mib_desc *mib; + u32 reg, i; + u64 hi; + + for (i = 0; i < ARRAY_SIZE(an8855_mib); i++) { + mib = &an8855_mib[i]; + reg = AN8855_PORT_MIB_COUNTER(port) + mib->offset; + + data[i] = an8855_read(priv, reg); + if (mib->size == 2) { + hi = an8855_read(priv, reg + 4); + data[i] |= hi << 32; + } + } +} + +static int +an8855_get_sset_count(struct dsa_switch *ds, int port, int sset) +{ + if (sset != ETH_SS_STATS) + return 0; + + return ARRAY_SIZE(an8855_mib); +} + +static int +an8855_cpu_port_enable(struct dsa_switch *ds, int port) +{ + struct an8855_priv *priv = ds->priv; + + /* Setup max capability of CPU port at first */ + if (priv->info->cpu_port_config) + priv->info->cpu_port_config(ds, port); + + /* Enable Airoha header mode on the cpu port */ + an8855_write(priv, AN8855_PVC_P(port), + PORT_SPEC_REPLACE_MODE | PORT_SPEC_TAG); + + /* Unknown multicast frame forwarding to the cpu port */ + an8855_write(priv, AN8855_UNMF, BIT(port)); + + /* Set CPU port number */ + an8855_rmw(priv, AN8855_MFC, CPU_MASK, CPU_EN | CPU_PORT(port)); + + /* CPU port gets connected to all user ports of + * the switch. + */ + an8855_write(priv, AN8855_PORTMATRIX_P(port), + PORTMATRIX_MATRIX(dsa_user_ports(priv->ds))); + + return 0; +} + +static int +an8855_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) +{ + struct an8855_priv *priv = ds->priv; + + if (!dsa_is_user_port(ds, port)) + return 0; + + mutex_lock(&priv->reg_mutex); + + /* Allow the user port gets connected to the cpu port and also + * restore the port matrix if the port is the member of a certain + * bridge. + */ + priv->ports[port].pm |= PORTMATRIX_MATRIX(BIT(AN8855_CPU_PORT)); + priv->ports[port].enable = true; + an8855_write(priv, AN8855_PORTMATRIX_P(port), priv->ports[port].pm); + an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static void +an8855_port_disable(struct dsa_switch *ds, int port) +{ + struct an8855_priv *priv = ds->priv; + + if (!dsa_is_user_port(ds, port)) + return; + + mutex_lock(&priv->reg_mutex); + + /* Clear up all port matrix which could be restored in the next + * enablement for the port. + */ + priv->ports[port].enable = false; + an8855_write(priv, AN8855_PORTMATRIX_P(port), PORTMATRIX_CLR); + an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + + mutex_unlock(&priv->reg_mutex); +} + +static void +an8855_stp_state_set(struct dsa_switch *ds, int port, u8 state) +{ + struct an8855_priv *priv = ds->priv; + u32 stp_state; + + if (dsa_is_unused_port(ds, port)) + return; + + switch (state) { + case BR_STATE_DISABLED: + stp_state = AN8855_STP_DISABLED; + break; + case BR_STATE_BLOCKING: + stp_state = AN8855_STP_BLOCKING; + break; + case BR_STATE_LISTENING: + stp_state = AN8855_STP_LISTENING; + break; + case BR_STATE_LEARNING: + stp_state = AN8855_STP_LEARNING; + break; + case BR_STATE_FORWARDING: + default: + stp_state = AN8855_STP_FORWARDING; + break; + } + + an8855_rmw(priv, AN8855_SSP_P(port), FID_PST_MASK, stp_state); +} + +static int +an8855_port_bridge_join(struct dsa_switch *ds, int port, + struct net_device *bridge) +{ + struct an8855_priv *priv = ds->priv; + u32 port_bitmap = BIT(AN8855_CPU_PORT); + int i; + + mutex_lock(&priv->reg_mutex); + + for (i = 0; i < AN8855_NUM_PORTS; i++) { + /* Add this port to the port matrix of the other ports in the + * same bridge. If the port is disabled, port matrix is kept + * and not being setup until the port becomes enabled. + */ + if (dsa_is_user_port(ds, i) && i != port) { + if (dsa_to_port(ds, i)->bridge_dev != bridge) + continue; + if (priv->ports[i].enable) + an8855_set(priv, AN8855_PORTMATRIX_P(i), + PORTMATRIX_MATRIX(BIT(port))); + priv->ports[i].pm |= PORTMATRIX_MATRIX(BIT(port)); + + port_bitmap |= BIT(i); + } + } + + /* Add the all other ports to this port matrix. */ + if (priv->ports[port].enable) + an8855_rmw(priv, AN8855_PORTMATRIX_P(port), + PORTMATRIX_MASK, PORTMATRIX_MATRIX(port_bitmap)); + priv->ports[port].pm |= PORTMATRIX_MATRIX(port_bitmap); + + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static void +an8855_port_set_vlan_unaware(struct dsa_switch *ds, int port) +{ + struct an8855_priv *priv = ds->priv; + bool all_user_ports_removed = true; + int i; + + /* When a port is removed from the bridge, the port would be set up + * back to the default as is at initial boot which is a VLAN-unaware + * port. + */ + an8855_rmw(priv, AN8855_PCR_P(port), PCR_PORT_VLAN_MASK, + AN8855_PORT_MATRIX_MODE); + an8855_rmw(priv, AN8855_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK, + VLAN_ATTR(AN8855_VLAN_TRANSPARENT) | + PVC_EG_TAG(AN8855_VLAN_EG_CONSISTENT)); + + for (i = 0; i < AN8855_NUM_PORTS; i++) { + if (dsa_is_user_port(ds, i) && + dsa_port_is_vlan_filtering(&ds->ports[i])) { + all_user_ports_removed = false; + break; + } + } + + /* CPU port also does the same thing until all user ports belonging to + * the CPU port get out of VLAN filtering mode. + */ + if (all_user_ports_removed) { + an8855_write(priv, AN8855_PORTMATRIX_P(AN8855_CPU_PORT), + PORTMATRIX_MATRIX(dsa_user_ports(priv->ds))); + an8855_write(priv, AN8855_PVC_P(AN8855_CPU_PORT), + PORT_SPEC_REPLACE_MODE | PORT_SPEC_TAG | + PVC_EG_TAG(AN8855_VLAN_EG_CONSISTENT)); + } +} + +static void +an8855_port_set_vlan_aware(struct dsa_switch *ds, int port) +{ + struct an8855_priv *priv = ds->priv; + + /* Trapped into security mode allows packet forwarding through VLAN + * table lookup. CPU port is set to fallback mode to let untagged + * frames pass through. + */ + if (dsa_is_cpu_port(ds, port)) + an8855_rmw(priv, AN8855_PCR_P(port), PCR_PORT_VLAN_MASK, + AN8855_PORT_FALLBACK_MODE); + else + an8855_rmw(priv, AN8855_PCR_P(port), PCR_PORT_VLAN_MASK, + AN8855_PORT_SECURITY_MODE); + + /* Set the port as a user port which is to be able to recognize VID + * from incoming packets before fetching entry within the VLAN table. + */ + an8855_rmw(priv, AN8855_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK, + VLAN_ATTR(AN8855_VLAN_USER) | + PVC_EG_TAG(AN8855_VLAN_EG_DISABLED)); +} + +static void +an8855_port_bridge_leave(struct dsa_switch *ds, int port, + struct net_device *bridge) +{ + struct an8855_priv *priv = ds->priv; + int i; + + mutex_lock(&priv->reg_mutex); + + for (i = 0; i < AN8855_NUM_PORTS; i++) { + /* Remove this port from the port matrix of the other ports + * in the same bridge. If the port is disabled, port matrix + * is kept and not being setup until the port becomes enabled. + */ + if (dsa_is_user_port(ds, i) && i != port) { + if (dsa_to_port(ds, i)->bridge_dev != bridge) + continue; + if (priv->ports[i].enable) + an8855_clear(priv, AN8855_PORTMATRIX_P(i), + PORTMATRIX_MATRIX(BIT(port))); + priv->ports[i].pm &= PORTMATRIX_MATRIX(BIT(port)); + } + } + + /* Set the cpu port to be the only one in the port matrix of + * this port. + */ + if (priv->ports[port].enable) + an8855_rmw(priv, AN8855_PORTMATRIX_P(port), PORTMATRIX_MASK, + PORTMATRIX_MATRIX(BIT(AN8855_CPU_PORT))); + priv->ports[port].pm = PORTMATRIX_MATRIX(BIT(AN8855_CPU_PORT)); + + mutex_unlock(&priv->reg_mutex); +} + +static int +an8855_port_fdb_add(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid) +{ + struct an8855_priv *priv = ds->priv; + int ret; + u8 port_mask = BIT(port); + + mutex_lock(&priv->reg_mutex); + an8855_fdb_write(priv, vid, port_mask, addr, 1); + ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL); + mutex_unlock(&priv->reg_mutex); + + return ret; +} + +static int +an8855_port_fdb_del(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid) +{ + struct an8855_priv *priv = ds->priv; + int ret; + u8 port_mask = BIT(port); + + mutex_lock(&priv->reg_mutex); + an8855_fdb_write(priv, vid, port_mask, addr, 0); + ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL); + mutex_unlock(&priv->reg_mutex); + + return ret; +} + +static int +an8855_port_fdb_dump(struct dsa_switch *ds, int port, + dsa_fdb_dump_cb_t *cb, void *data) +{ + struct an8855_priv *priv = ds->priv; + struct an8855_fdb _fdb = { 0 }; + int cnt = 512; + int num = 4; + int index = 0; + bool flag = false; + int banks = 0; + int i = 0; + int ret = 0; + u32 rsp = 0; + + mutex_lock(&priv->reg_mutex); + + an8855_write(priv, AN8855_ATWD2, (0x1 << port)); + ret = an8855_fdb_cmd(priv, ATC_MAT(0xc) | AN8855_FDB_START, &rsp); + if (ret < 0) + goto err; + + index = (rsp >> ATC_HASH) & ATC_HASH_MASK; + if (index == (cnt - 1)) + flag = true; + else + flag = false; + + banks = (rsp >> ATC_HIT) & ATC_HIT_MASK; + if (banks == 0) { + mutex_unlock(&priv->reg_mutex); + return 0; + } + for (i = 0; i < num; i++) { + if ((banks >> i) & 0x1) { + an8855_write(priv, AN8855_ATRDS, i); + udelay(1000); + an8855_fdb_read(priv, &_fdb); + if (!_fdb.live) + continue; + if (_fdb.port_mask & BIT(port)) { + ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp, data); + if (ret < 0) + continue; + } + } + } + while (1) { + if (flag == true) + break; + + ret = + an8855_fdb_cmd(priv, ATC_MAT(0xc) | AN8855_FDB_NEXT, &rsp); + index = (rsp >> ATC_HASH) & ATC_HASH_MASK; + if (index == (cnt - 1)) + flag = true; + else + flag = false; + + banks = (rsp >> ATC_HIT) & ATC_HIT_MASK; + if (banks == 0) { + mutex_unlock(&priv->reg_mutex); + return 0; + } + for (i = 0; i < num; i++) { + if ((banks >> i) & 0x1) { + an8855_write(priv, AN8855_ATRDS, i); + udelay(1000); + an8855_fdb_read(priv, &_fdb); + if (!_fdb.live) + continue; + if (_fdb.port_mask & BIT(port)) { + ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp, + data); + if (ret < 0) + continue; + } + } + } + } + +err: + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +an8855_vlan_cmd(struct an8855_priv *priv, enum an8855_vlan_cmd cmd, u16 vid) +{ + struct an8855_dummy_poll p; + u32 val; + int ret; + + if (vid > 0xFFF) { + dev_err(priv->dev, "vid number invalid\n"); + return -EINVAL; + } + + val = VTCR_BUSY | VTCR_FUNC(cmd) | vid; + an8855_write(priv, AN8855_VTCR, val); + + INIT_AN8855_DUMMY_POLL(&p, priv, AN8855_VTCR); + ret = readx_poll_timeout(_an8855_read, &p, val, + !(val & VTCR_BUSY), 20, 200000); + if (ret < 0) { + dev_err(priv->dev, "poll timeout\n"); + return ret; + } + + return 0; +} + +static int +an8855_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) +{ + if (vlan_filtering) { + /* The port is being kept as VLAN-unaware port when bridge is + * set up with vlan_filtering not being set, Otherwise, the + * port and the corresponding CPU port is required the setup + * for becoming a VLAN-aware port. + */ + an8855_port_set_vlan_aware(ds, port); + an8855_port_set_vlan_aware(ds, AN8855_CPU_PORT); + } else { + an8855_port_set_vlan_unaware(ds, port); + } + + return 0; +} + +static int +an8855_port_vlan_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + /* nothing needed */ + return 0; +} + +static void +an8855_hw_vlan_add(struct an8855_priv *priv, struct an8855_hw_vlan_entry *entry) +{ + u8 new_members; + u32 val; + + new_members = entry->old_members | BIT(entry->port) | + BIT(AN8855_CPU_PORT); + + /* Validate the entry with independent learning, create egress tag per + * VLAN and joining the port as one of the port members. + */ + val = + an8855_read(priv, + AN8855_VARD0) & (ETAG_CTRL_MASK << PORT_EG_CTRL_SHIFT); + val |= (IVL_MAC | VTAG_EN | PORT_MEM(new_members) | VLAN_VALID); + an8855_write(priv, AN8855_VAWD0, val); + an8855_write(priv, AN8855_VAWD1, 0); + + /* Decide whether adding tag or not for those outgoing packets from the + * port inside the VLAN. + */ + val = + entry->untagged ? AN8855_VLAN_EGRESS_UNTAG : AN8855_VLAN_EGRESS_TAG; + an8855_rmw(priv, AN8855_VAWD0, + ETAG_CTRL_P_MASK(entry->port) << PORT_EG_CTRL_SHIFT, + ETAG_CTRL_P(entry->port, val) << PORT_EG_CTRL_SHIFT); + + /* CPU port is always taken as a tagged port for serving more than one + * VLANs across and also being applied with egress type stack mode for + * that VLAN tags would be appended after hardware special tag used as + * DSA tag. + */ + an8855_rmw(priv, AN8855_VAWD0, + ETAG_CTRL_P_MASK(AN8855_CPU_PORT) << PORT_EG_CTRL_SHIFT, + ETAG_CTRL_P(AN8855_CPU_PORT, + AN8855_VLAN_EGRESS_STACK) << PORT_EG_CTRL_SHIFT); +} + +static void +an8855_hw_vlan_del(struct an8855_priv *priv, struct an8855_hw_vlan_entry *entry) +{ + u8 new_members; + u32 val; + + new_members = entry->old_members & ~BIT(entry->port); + + val = an8855_read(priv, AN8855_VARD0); + if (!(val & VLAN_VALID)) { + dev_err(priv->dev, "Cannot be deleted due to invalid entry\n"); + return; + } + + /* If certain member apart from CPU port is still alive in the VLAN, + * the entry would be kept valid. Otherwise, the entry is got to be + * disabled. + */ + if (new_members && new_members != BIT(AN8855_CPU_PORT)) { + val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | VLAN_VALID; + an8855_write(priv, AN8855_VAWD0, val); + } else { + an8855_write(priv, AN8855_VAWD0, 0); + an8855_write(priv, AN8855_VAWD1, 0); + } +} + +static void +an8855_hw_vlan_update(struct an8855_priv *priv, u16 vid, + struct an8855_hw_vlan_entry *entry, + an8855_vlan_op vlan_op) +{ + u32 val; + + /* Fetch entry */ + an8855_vlan_cmd(priv, AN8855_VTCR_RD_VID, vid); + + val = an8855_read(priv, AN8855_VARD0); + + entry->old_members = (val >> PORT_MEM_SHFT) & PORT_MEM_MASK; + + /* Manipulate entry */ + vlan_op(priv, entry); + + /* Flush result to hardware */ + an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, vid); +} + +static void +an8855_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + struct an8855_hw_vlan_entry new_entry; + struct an8855_priv *priv = ds->priv; + u16 vid; + + mutex_lock(&priv->reg_mutex); + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { + an8855_hw_vlan_entry_init(&new_entry, port, untagged); + an8855_hw_vlan_update(priv, vid, &new_entry, + an8855_hw_vlan_add); + } + + if (pvid) { + an8855_rmw(priv, AN8855_PVID_P(port), G0_PORT_VID_MASK, + G0_PORT_VID(vlan->vid_end)); + priv->ports[port].pvid = vlan->vid_end; + } + + mutex_unlock(&priv->reg_mutex); +} + +static int +an8855_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct an8855_hw_vlan_entry target_entry; + struct an8855_priv *priv = ds->priv; + u16 vid, pvid; + + mutex_lock(&priv->reg_mutex); + + pvid = priv->ports[port].pvid; + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { + an8855_hw_vlan_entry_init(&target_entry, port, 0); + an8855_hw_vlan_update(priv, vid, &target_entry, + an8855_hw_vlan_del); + + /* PVID is being restored to the default whenever the PVID port + * is being removed from the VLAN. + */ + if (pvid == vid) + pvid = G0_PORT_VID_DEF; + } + + an8855_rmw(priv, AN8855_PVID_P(port), G0_PORT_VID_MASK, pvid); + priv->ports[port].pvid = pvid; + + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int an8855_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) +{ + struct an8855_priv *priv = ds->priv; + int monitor_port; + u32 val; + + /* Check for existent entry */ + if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port)) + return -EEXIST; + + val = an8855_read(priv, AN8855_MIR); + + /* AN8855 supports 4 monitor port, but only use first group */ + monitor_port = AN8855_MIRROR_PORT_GET(val); + if (val & AN8855_MIRROR_EN && monitor_port != mirror->to_local_port) + return -EEXIST; + + val |= AN8855_MIRROR_EN; + val &= ~AN8855_MIRROR_MASK; + val |= AN8855_MIRROR_PORT_SET(mirror->to_local_port); + an8855_write(priv, AN8855_MIR, val); + + val = an8855_read(priv, AN8855_PCR_P(port)); + if (ingress) { + val |= PORT_RX_MIR; + priv->mirror_rx |= BIT(port); + } else { + val |= PORT_TX_MIR; + priv->mirror_tx |= BIT(port); + } + an8855_write(priv, AN8855_PCR_P(port), val); + + return 0; +} + +static void an8855_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) +{ + struct an8855_priv *priv = ds->priv; + u32 val; + + val = an8855_read(priv, AN8855_PCR_P(port)); + if (mirror->ingress) { + val &= ~PORT_RX_MIR; + priv->mirror_rx &= ~BIT(port); + } else { + val &= ~PORT_TX_MIR; + priv->mirror_tx &= ~BIT(port); + } + an8855_write(priv, AN8855_PCR_P(port), val); + + if (!priv->mirror_rx && !priv->mirror_tx) { + val = an8855_read(priv, AN8855_MIR); + val &= ~AN8855_MIRROR_EN; + an8855_write(priv, AN8855_MIR, val); + } +} + +static enum dsa_tag_protocol +air_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol mp) +{ + struct an8855_priv *priv = ds->priv; + + if (port != AN8855_CPU_PORT) { + dev_warn(priv->dev, "port not matched with tagging CPU port\n"); + return DSA_TAG_PROTO_NONE; + } else { + return DSA_TAG_PROTO_ARHT; + } +} + +static int +setup_unused_ports(struct dsa_switch *ds, u32 pm) +{ + struct an8855_priv *priv = ds->priv; + u32 egtag_mask = 0; + u32 egtag_val = 0; + int i; + + if (!pm) + return 0; + + for (i = 0; i < AN8855_NUM_PORTS; i++) { + if (!dsa_is_unused_port(ds, i)) + continue; + + /* Setup MAC port with maximum capability. */ + if (i == 5) + if (priv->info->cpu_port_config) + priv->info->cpu_port_config(ds, i); + + an8855_rmw(priv, AN8855_PORTMATRIX_P(i), PORTMATRIX_MASK, + AN8855_PORTMATRIX_P(pm)); + an8855_rmw(priv, AN8855_PCR_P(i), PCR_PORT_VLAN_MASK, + AN8855_PORT_SECURITY_MODE); + egtag_mask |= ETAG_CTRL_P_MASK(i); + egtag_val |= ETAG_CTRL_P(i, AN8855_VLAN_EGRESS_UNTAG); + } + + /* Add unused ports to VLAN2 group for using IVL fdb. */ + an8855_write(priv, AN8855_VAWD0, + IVL_MAC | VTAG_EN | PORT_MEM(pm) | VLAN_VALID); + an8855_rmw(priv, AN8855_VAWD0, egtag_mask << PORT_EG_CTRL_SHIFT, + egtag_val << PORT_EG_CTRL_SHIFT); + an8855_write(priv, AN8855_VAWD1, 0); + an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, AN8855_RESERVED_VLAN); + + for (i = 0; i < AN8855_NUM_PORTS; i++) { + if (!dsa_is_unused_port(ds, i)) + continue; + + an8855_rmw(priv, AN8855_PVID_P(i), G0_PORT_VID_MASK, + G0_PORT_VID(AN8855_RESERVED_VLAN)); + an8855_rmw(priv, AN8855_SSP_P(i), FID_PST_MASK, + AN8855_STP_FORWARDING); + + dev_dbg(ds->dev, "Add unused port%d to reserved VLAN%d group\n", + i, AN8855_RESERVED_VLAN); + } + + return 0; +} + +static int +an8855_setup(struct dsa_switch *ds) +{ + struct an8855_priv *priv = ds->priv; + struct an8855_dummy_poll p; + u32 unused_pm = 0; + u32 val, id; + int ret, i; + + /* Reset whole chip through gpio pin or memory-mapped registers for + * different type of hardware + */ + gpiod_set_value_cansleep(priv->reset, 0); + usleep_range(100000, 150000); + gpiod_set_value_cansleep(priv->reset, 1); + usleep_range(100000, 150000); + + /* Waiting for AN8855 got to stable */ + INIT_AN8855_DUMMY_POLL(&p, priv, 0x1000009c); + ret = readx_poll_timeout(_an8855_read, &p, val, val != 0, 20, 1000000); + if (ret < 0) { + dev_err(priv->dev, "reset timeout\n"); + return ret; + } + + id = an8855_read(priv, AN8855_CREV); + if (id != AN8855_ID) { + dev_err(priv->dev, "chip %x can't be supported\n", id); + return -ENODEV; + } + + /* Reset the switch through internal reset */ + an8855_write(priv, AN8855_RST_CTRL, SYS_CTRL_SYS_RST); + usleep_range(100000, 110000); + + /* change gphy smi address */ + if (priv->phy_base_new > 0) { + an8855_write(priv, RG_GPHY_SMI_ADDR, priv->phy_base_new); + priv->phy_base = priv->phy_base_new; + } + + /* Let phylink decide the interface later. */ + priv->p5_interface = PHY_INTERFACE_MODE_NA; + + /* BPDU to CPU port */ + //an8855_rmw(priv, AN8855_CFC, AN8855_CPU_PMAP_MASK, + // BIT(AN8855_CPU_PORT)); + an8855_rmw(priv, AN8855_BPC, AN8855_BPDU_PORT_FW_MASK, + AN8855_BPDU_CPU_ONLY); + + /* Enable and reset MIB counters */ + an8855_mib_reset(ds); + + for (i = 0; i < AN8855_NUM_PORTS; i++) { + /* Disable forwarding by default on all ports */ + an8855_rmw(priv, AN8855_PORTMATRIX_P(i), PORTMATRIX_MASK, + PORTMATRIX_CLR); + if (dsa_is_unused_port(ds, i)) + unused_pm |= BIT(i); + else if (dsa_is_cpu_port(ds, i)) + an8855_cpu_port_enable(ds, i); + else + an8855_port_disable(ds, i); + /* Enable consistent egress tag */ + an8855_rmw(priv, AN8855_PVC_P(i), PVC_EG_TAG_MASK, + PVC_EG_TAG(AN8855_VLAN_EG_CONSISTENT)); + } + + an8855_phy_setup(ds); + + /* Group and enable unused ports as a standalone dumb switch. */ + setup_unused_ports(ds, unused_pm); + + ds->configure_vlan_while_not_filtering = true; + + /* Flush the FDB table */ + ret = an8855_fdb_cmd(priv, AN8855_FDB_FLUSH, NULL); + if (ret < 0) + return ret; + + return 0; +} + +static bool +an8855_phy_supported(struct dsa_switch *ds, int port, + const struct phylink_link_state *state) +{ + struct an8855_priv *priv = ds->priv; + + switch (port) { + case 0: /* Internal phy */ + case 1: + case 2: + case 3: + case 4: + if (state->interface != PHY_INTERFACE_MODE_GMII) + goto unsupported; + break; + case 5: + if (state->interface != PHY_INTERFACE_MODE_SGMII + && state->interface != PHY_INTERFACE_MODE_RGMII + && state->interface != PHY_INTERFACE_MODE_2500BASEX) + goto unsupported; + break; + default: + dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, + port); + goto unsupported; + } + + return true; + +unsupported: + return false; +} + +static bool +an8855_phy_mode_supported(struct dsa_switch *ds, int port, + const struct phylink_link_state *state) +{ + struct an8855_priv *priv = ds->priv; + + return priv->info->phy_mode_supported(ds, port, state); +} + +static int +an8855_rgmii_setup(struct an8855_priv *priv, u32 port, + phy_interface_t interface, + struct phy_device *phydev) +{ + return 0; +} + +static void +an8855_sgmii_validate(struct an8855_priv *priv, int port, + unsigned long *supported) +{ + switch (port) { + case 5: + phylink_set(supported, 1000baseX_Full); + phylink_set(supported, 2500baseX_Full); + } +} + +static void +an8855_sgmii_link_up_force(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface, + int speed, int duplex) +{ + /* For adjusting speed and duplex of SGMII force mode. */ + if (interface != PHY_INTERFACE_MODE_SGMII || + phylink_autoneg_inband(mode)) + return; +} + +static bool +an8855_is_mac_port(u32 port) +{ + return (port == 5); +} + +static int +an8855_set_hsgmii_mode(struct an8855_priv *priv) +{ + u32 val = 0; + + /* PLL */ + val = an8855_read(priv, QP_DIG_MODE_CTRL_1); + val &= ~(0x3 << 2); + val |= (0x1 << 2); + an8855_write(priv, QP_DIG_MODE_CTRL_1, val); + + /* PLL - LPF */ + val = an8855_read(priv, PLL_CTRL_2); + val &= ~(0x3 << 0); + val |= (0x1 << 0); + val &= ~(0x7 << 2); + val |= (0x5 << 2); + val &= ~BITS(6, 7); + val &= ~(0x7 << 8); + val |= (0x3 << 8); + val |= BIT(29); + val &= ~BITS(12, 13); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - ICO */ + val = an8855_read(priv, PLL_CTRL_4); + val |= BIT(2); + an8855_write(priv, PLL_CTRL_4, val); + + val = an8855_read(priv, PLL_CTRL_2); + val &= ~BIT(14); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - CHP */ + val = an8855_read(priv, PLL_CTRL_2); + val &= ~(0xf << 16); + val |= (0x6 << 16); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - PFD */ + val = an8855_read(priv, PLL_CTRL_2); + val &= ~(0x3 << 20); + val |= (0x1 << 20); + val &= ~(0x3 << 24); + val |= (0x1 << 24); + val &= ~BIT(26); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - POSTDIV */ + val = an8855_read(priv, PLL_CTRL_2); + val |= BIT(22); + val &= ~BIT(27); + val &= ~BIT(28); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - SDM */ + val = an8855_read(priv, PLL_CTRL_4); + val &= ~BITS(3, 4); + an8855_write(priv, PLL_CTRL_4, val); + + val = an8855_read(priv, PLL_CTRL_2); + val &= ~BIT(30); + an8855_write(priv, PLL_CTRL_2, val); + + val = an8855_read(priv, SS_LCPLL_PWCTL_SETTING_2); + val &= ~(0x3 << 16); + val |= (0x1 << 16); + an8855_write(priv, SS_LCPLL_PWCTL_SETTING_2, val); + + an8855_write(priv, SS_LCPLL_TDC_FLT_2, 0x7a000000); + an8855_write(priv, SS_LCPLL_TDC_PCW_1, 0x7a000000); + + val = an8855_read(priv, SS_LCPLL_TDC_FLT_5); + val &= ~BIT(24); + an8855_write(priv, SS_LCPLL_TDC_FLT_5, val); + + val = an8855_read(priv, PLL_CK_CTRL_0); + val &= ~BIT(8); + an8855_write(priv, PLL_CK_CTRL_0, val); + + /* PLL - SS */ + val = an8855_read(priv, PLL_CTRL_3); + val &= ~BITS(0, 15); + an8855_write(priv, PLL_CTRL_3, val); + + val = an8855_read(priv, PLL_CTRL_4); + val &= ~BITS(0, 1); + an8855_write(priv, PLL_CTRL_4, val); + + val = an8855_read(priv, PLL_CTRL_3); + val &= ~BITS(16, 31); + an8855_write(priv, PLL_CTRL_3, val); + + /* PLL - TDC */ + val = an8855_read(priv, PLL_CK_CTRL_0); + val &= ~BIT(9); + an8855_write(priv, PLL_CK_CTRL_0, val); + + val = an8855_read(priv, RG_QP_PLL_SDM_ORD); + val |= BIT(3); + val |= BIT(4); + an8855_write(priv, RG_QP_PLL_SDM_ORD, val); + + val = an8855_read(priv, RG_QP_RX_DAC_EN); + val &= ~(0x3 << 16); + val |= (0x2 << 16); + an8855_write(priv, RG_QP_RX_DAC_EN, val); + + /* TCL Disable (only for Co-SIM) */ + val = an8855_read(priv, PON_RXFEDIG_CTRL_0); + val &= ~BIT(12); + an8855_write(priv, PON_RXFEDIG_CTRL_0, val); + + /* TX Init */ + val = an8855_read(priv, RG_QP_TX_MODE_16B_EN); + val &= ~BIT(0); + val &= ~(0xffff << 16); + val |= (0x4 << 16); + an8855_write(priv, RG_QP_TX_MODE_16B_EN, val); + + /* RX Control */ + val = an8855_read(priv, RG_QP_RXAFE_RESERVE); + val |= BIT(11); + an8855_write(priv, RG_QP_RXAFE_RESERVE, val); + + val = an8855_read(priv, RG_QP_CDR_LPF_MJV_LIM); + val &= ~(0x3 << 4); + val |= (0x1 << 4); + an8855_write(priv, RG_QP_CDR_LPF_MJV_LIM, val); + + val = an8855_read(priv, RG_QP_CDR_LPF_SETVALUE); + val &= ~(0xf << 25); + val |= (0x1 << 25); + val &= ~(0x7 << 29); + val |= (0x3 << 29); + an8855_write(priv, RG_QP_CDR_LPF_SETVALUE, val); + + val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1); + val &= ~(0x1f << 8); + val |= (0xf << 8); + an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val); + + val = an8855_read(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE); + val &= ~(0x3f << 0); + val |= (0x19 << 0); + val &= ~BIT(6); + an8855_write(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE, val); + + val = an8855_read(priv, RG_QP_CDR_FORCE_IBANDLPF_R_OFF); + val &= ~(0x7f << 6); + val |= (0x21 << 6); + val &= ~(0x3 << 16); + val |= (0x2 << 16); + val &= ~BIT(13); + an8855_write(priv, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, val); + + val = an8855_read(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE); + val &= ~BIT(30); + an8855_write(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE, val); + + val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1); + val &= ~(0x7 << 24); + val |= (0x4 << 24); + an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val); + + val = an8855_read(priv, PLL_CTRL_0); + val |= BIT(0); + an8855_write(priv, PLL_CTRL_0, val); + + val = an8855_read(priv, RX_CTRL_26); + val &= ~BIT(23); + val |= BIT(26); + an8855_write(priv, RX_CTRL_26, val); + + val = an8855_read(priv, RX_DLY_0); + val &= ~(0xff << 0); + val |= (0x6f << 0); + val |= BITS(8, 13); + an8855_write(priv, RX_DLY_0, val); + + val = an8855_read(priv, RX_CTRL_42); + val &= ~(0x1fff << 0); + val |= (0x150 << 0); + an8855_write(priv, RX_CTRL_42, val); + + val = an8855_read(priv, RX_CTRL_2); + val &= ~(0x1fff << 16); + val |= (0x150 << 16); + an8855_write(priv, RX_CTRL_2, val); + + val = an8855_read(priv, PON_RXFEDIG_CTRL_9); + val &= ~(0x7 << 0); + val |= (0x1 << 0); + an8855_write(priv, PON_RXFEDIG_CTRL_9, val); + + val = an8855_read(priv, RX_CTRL_8); + val &= ~(0xfff << 16); + val |= (0x200 << 16); + val &= ~(0x7fff << 14); + val |= (0xfff << 14); + an8855_write(priv, RX_CTRL_8, val); + + /* Frequency memter */ + val = an8855_read(priv, RX_CTRL_5); + val &= ~(0xfffff << 10); + val |= (0x10 << 10); + an8855_write(priv, RX_CTRL_5, val); + + val = an8855_read(priv, RX_CTRL_6); + val &= ~(0xfffff << 0); + val |= (0x64 << 0); + an8855_write(priv, RX_CTRL_6, val); + + val = an8855_read(priv, RX_CTRL_7); + val &= ~(0xfffff << 0); + val |= (0x2710 << 0); + an8855_write(priv, RX_CTRL_7, val); + + /* PCS Init */ + val = an8855_read(priv, RG_HSGMII_PCS_CTROL_1); + val &= ~BIT(30); + an8855_write(priv, RG_HSGMII_PCS_CTROL_1, val); + + /* Rate Adaption */ + val = an8855_read(priv, RATE_ADP_P0_CTRL_0); + val &= ~BIT(31); + an8855_write(priv, RATE_ADP_P0_CTRL_0, val); + + val = an8855_read(priv, RG_RATE_ADAPT_CTRL_0); + val |= BIT(0); + val |= BIT(4); + val |= BITS(26, 27); + an8855_write(priv, RG_RATE_ADAPT_CTRL_0, val); + + /* Disable AN */ + val = an8855_read(priv, SGMII_REG_AN0); + val &= ~BIT(12); + an8855_write(priv, SGMII_REG_AN0, val); + + /* Force Speed */ + val = an8855_read(priv, SGMII_STS_CTRL_0); + val |= BIT(2); + val |= BITS(4, 5); + an8855_write(priv, SGMII_STS_CTRL_0, val); + + /* bypass flow control to MAC */ + an8855_write(priv, MSG_RX_LIK_STS_0, 0x01010107); + an8855_write(priv, MSG_RX_LIK_STS_2, 0x00000EEF); + + return 0; +} + +static int +an8855_sgmii_setup(struct an8855_priv *priv, int mode) +{ + u32 val = 0; + + /* PMA Init */ + /* PLL */ + val = an8855_read(priv, QP_DIG_MODE_CTRL_1); + val &= ~BITS(2, 3); + an8855_write(priv, QP_DIG_MODE_CTRL_1, val); + + /* PLL - LPF */ + val = an8855_read(priv, PLL_CTRL_2); + val &= ~(0x3 << 0); + val |= (0x1 << 0); + val &= ~(0x7 << 2); + val |= (0x5 << 2); + val &= ~BITS(6, 7); + val &= ~(0x7 << 8); + val |= (0x3 << 8); + val |= BIT(29); + val &= ~BITS(12, 13); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - ICO */ + val = an8855_read(priv, PLL_CTRL_4); + val |= BIT(2); + an8855_write(priv, PLL_CTRL_4, val); + + val = an8855_read(priv, PLL_CTRL_2); + val &= ~BIT(14); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - CHP */ + val = an8855_read(priv, PLL_CTRL_2); + val &= ~(0xf << 16); + val |= (0x4 << 16); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - PFD */ + val = an8855_read(priv, PLL_CTRL_2); + val &= ~(0x3 << 20); + val |= (0x1 << 20); + val &= ~(0x3 << 24); + val |= (0x1 << 24); + val &= ~BIT(26); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - POSTDIV */ + val = an8855_read(priv, PLL_CTRL_2); + val |= BIT(22); + val &= ~BIT(27); + val &= ~BIT(28); + an8855_write(priv, PLL_CTRL_2, val); + + /* PLL - SDM */ + val = an8855_read(priv, PLL_CTRL_4); + val &= ~BITS(3, 4); + an8855_write(priv, PLL_CTRL_4, val); + + val = an8855_read(priv, PLL_CTRL_2); + val &= ~BIT(30); + an8855_write(priv, PLL_CTRL_2, val); + + val = an8855_read(priv, SS_LCPLL_PWCTL_SETTING_2); + val &= ~(0x3 << 16); + val |= (0x1 << 16); + an8855_write(priv, SS_LCPLL_PWCTL_SETTING_2, val); + + an8855_write(priv, SS_LCPLL_TDC_FLT_2, 0x48000000); + an8855_write(priv, SS_LCPLL_TDC_PCW_1, 0x48000000); + + val = an8855_read(priv, SS_LCPLL_TDC_FLT_5); + val &= ~BIT(24); + an8855_write(priv, SS_LCPLL_TDC_FLT_5, val); + + val = an8855_read(priv, PLL_CK_CTRL_0); + val &= ~BIT(8); + an8855_write(priv, PLL_CK_CTRL_0, val); + + /* PLL - SS */ + val = an8855_read(priv, PLL_CTRL_3); + val &= ~BITS(0, 15); + an8855_write(priv, PLL_CTRL_3, val); + + val = an8855_read(priv, PLL_CTRL_4); + val &= ~BITS(0, 1); + an8855_write(priv, PLL_CTRL_4, val); + + val = an8855_read(priv, PLL_CTRL_3); + val &= ~BITS(16, 31); + an8855_write(priv, PLL_CTRL_3, val); + + /* PLL - TDC */ + val = an8855_read(priv, PLL_CK_CTRL_0); + val &= ~BIT(9); + an8855_write(priv, PLL_CK_CTRL_0, val); + + val = an8855_read(priv, RG_QP_PLL_SDM_ORD); + val |= BIT(3); + val |= BIT(4); + an8855_write(priv, RG_QP_PLL_SDM_ORD, val); + + val = an8855_read(priv, RG_QP_RX_DAC_EN); + val &= ~(0x3 << 16); + val |= (0x2 << 16); + an8855_write(priv, RG_QP_RX_DAC_EN, val); + + /* PLL - TCL Disable (only for Co-SIM) */ + val = an8855_read(priv, PON_RXFEDIG_CTRL_0); + val &= ~BIT(12); + an8855_write(priv, PON_RXFEDIG_CTRL_0, val); + + /* TX Init */ + val = an8855_read(priv, RG_QP_TX_MODE_16B_EN); + val &= ~BIT(0); + val &= ~BITS(16, 31); + an8855_write(priv, RG_QP_TX_MODE_16B_EN, val); + + /* RX Init */ + val = an8855_read(priv, RG_QP_RXAFE_RESERVE); + val |= BIT(11); + an8855_write(priv, RG_QP_RXAFE_RESERVE, val); + + val = an8855_read(priv, RG_QP_CDR_LPF_MJV_LIM); + val &= ~(0x3 << 4); + val |= (0x2 << 4); + an8855_write(priv, RG_QP_CDR_LPF_MJV_LIM, val); + + val = an8855_read(priv, RG_QP_CDR_LPF_SETVALUE); + val &= ~(0xf << 25); + val |= (0x1 << 25); + val &= ~(0x7 << 29); + val |= (0x6 << 29); + an8855_write(priv, RG_QP_CDR_LPF_SETVALUE, val); + + val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1); + val &= ~(0x1f << 8); + val |= (0xc << 8); + an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val); + + val = an8855_read(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE); + val &= ~(0x3f << 0); + val |= (0x19 << 0); + val &= ~BIT(6); + an8855_write(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE, val); + + val = an8855_read(priv, RG_QP_CDR_FORCE_IBANDLPF_R_OFF); + val &= ~(0x7f << 6); + val |= (0x21 << 6); + val &= ~(0x3 << 16); + val |= (0x2 << 16); + val &= ~BIT(13); + an8855_write(priv, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, val); + + val = an8855_read(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE); + val &= ~BIT(30); + an8855_write(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE, val); + + val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1); + val &= ~(0x7 << 24); + val |= (0x4 << 24); + an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val); + + val = an8855_read(priv, PLL_CTRL_0); + val |= BIT(0); + an8855_write(priv, PLL_CTRL_0, val); + + val = an8855_read(priv, RX_CTRL_26); + val &= ~BIT(23); + if (mode == SGMII_MODE_AN) + val |= BIT(26); + + an8855_write(priv, RX_CTRL_26, val); + + val = an8855_read(priv, RX_DLY_0); + val &= ~(0xff << 0); + val |= (0x6f << 0); + val |= BITS(8, 13); + an8855_write(priv, RX_DLY_0, val); + + val = an8855_read(priv, RX_CTRL_42); + val &= ~(0x1fff << 0); + val |= (0x150 << 0); + an8855_write(priv, RX_CTRL_42, val); + + val = an8855_read(priv, RX_CTRL_2); + val &= ~(0x1fff << 16); + val |= (0x150 << 16); + an8855_write(priv, RX_CTRL_2, val); + + val = an8855_read(priv, PON_RXFEDIG_CTRL_9); + val &= ~(0x7 << 0); + val |= (0x1 << 0); + an8855_write(priv, PON_RXFEDIG_CTRL_9, val); + + val = an8855_read(priv, RX_CTRL_8); + val &= ~(0xfff << 16); + val |= (0x200 << 16); + val &= ~(0x7fff << 0); + val |= (0xfff << 0); + an8855_write(priv, RX_CTRL_8, val); + + /* Frequency memter */ + val = an8855_read(priv, RX_CTRL_5); + val &= ~(0xfffff << 10); + val |= (0x28 << 10); + an8855_write(priv, RX_CTRL_5, val); + + val = an8855_read(priv, RX_CTRL_6); + val &= ~(0xfffff << 0); + val |= (0x64 << 0); + an8855_write(priv, RX_CTRL_6, val); + + val = an8855_read(priv, RX_CTRL_7); + val &= ~(0xfffff << 0); + val |= (0x2710 << 0); + an8855_write(priv, RX_CTRL_7, val); + + if (mode == SGMII_MODE_FORCE) { + /* PCS Init */ + val = an8855_read(priv, QP_DIG_MODE_CTRL_0); + val &= ~BIT(0); + val &= ~BITS(4, 5); + an8855_write(priv, QP_DIG_MODE_CTRL_0, val); + + val = an8855_read(priv, RG_HSGMII_PCS_CTROL_1); + val &= ~BIT(30); + an8855_write(priv, RG_HSGMII_PCS_CTROL_1, val); + + /* Rate Adaption - GMII path config. */ + val = an8855_read(priv, RG_AN_SGMII_MODE_FORCE); + val |= BIT(0); + val &= ~BITS(4, 5); + an8855_write(priv, RG_AN_SGMII_MODE_FORCE, val); + + val = an8855_read(priv, SGMII_STS_CTRL_0); + val |= BIT(2); + val &= ~(0x3 << 4); + val |= (0x2 << 4); + an8855_write(priv, SGMII_STS_CTRL_0, val); + + val = an8855_read(priv, SGMII_REG_AN0); + val &= ~BIT(12); + an8855_write(priv, SGMII_REG_AN0, val); + + val = an8855_read(priv, PHY_RX_FORCE_CTRL_0); + val |= BIT(4); + an8855_write(priv, PHY_RX_FORCE_CTRL_0, val); + + val = an8855_read(priv, RATE_ADP_P0_CTRL_0); + val &= ~BITS(0, 3); + val |= BIT(28); + an8855_write(priv, RATE_ADP_P0_CTRL_0, val); + + val = an8855_read(priv, RG_RATE_ADAPT_CTRL_0); + val |= BIT(0); + val |= BIT(4); + val |= BITS(26, 27); + an8855_write(priv, RG_RATE_ADAPT_CTRL_0, val); + } else { + /* PCS Init */ + val = an8855_read(priv, RG_HSGMII_PCS_CTROL_1); + val &= ~BIT(30); + an8855_write(priv, RG_HSGMII_PCS_CTROL_1, val); + + /* Set AN Ability - Interrupt */ + val = an8855_read(priv, SGMII_REG_AN_FORCE_CL37); + val |= BIT(0); + an8855_write(priv, SGMII_REG_AN_FORCE_CL37, val); + + val = an8855_read(priv, SGMII_REG_AN_13); + val &= ~(0x3f << 0); + val |= (0xb << 0); + val |= BIT(8); + an8855_write(priv, SGMII_REG_AN_13, val); + + /* Rate Adaption - GMII path config. */ + val = an8855_read(priv, SGMII_REG_AN0); + val |= BIT(12); + an8855_write(priv, SGMII_REG_AN0, val); + + val = an8855_read(priv, MII_RA_AN_ENABLE); + val |= BIT(0); + an8855_write(priv, MII_RA_AN_ENABLE, val); + + val = an8855_read(priv, RATE_ADP_P0_CTRL_0); + val |= BIT(28); + an8855_write(priv, RATE_ADP_P0_CTRL_0, val); + + val = an8855_read(priv, RG_RATE_ADAPT_CTRL_0); + val |= BIT(0); + val |= BIT(4); + val |= BITS(26, 27); + an8855_write(priv, RG_RATE_ADAPT_CTRL_0, val); + + /* Only for Co-SIM */ + + /* AN Speed up (Only for Co-SIM) */ + + /* Restart AN */ + val = an8855_read(priv, SGMII_REG_AN0); + val |= BIT(9); + val |= BIT(15); + an8855_write(priv, SGMII_REG_AN0, val); + } + + /* bypass flow control to MAC */ + an8855_write(priv, MSG_RX_LIK_STS_0, 0x01010107); + an8855_write(priv, MSG_RX_LIK_STS_2, 0x00000EEF); + + return 0; +} + +static int +an8855_sgmii_setup_mode_force(struct an8855_priv *priv, u32 port, + phy_interface_t interface) +{ + return an8855_sgmii_setup(priv, SGMII_MODE_FORCE); +} + +static int +an8855_sgmii_setup_mode_an(struct an8855_priv *priv, int port, + phy_interface_t interface) +{ + return an8855_sgmii_setup(priv, SGMII_MODE_AN); +} + +static int +an8855_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + phy_interface_t interface) +{ + struct an8855_priv *priv = ds->priv; + struct phy_device *phydev; + const struct dsa_port *dp; + + if (!an8855_is_mac_port(port)) { + dev_err(priv->dev, "port %d is not a MAC port\n", port); + return -EINVAL; + } + + switch (interface) { + case PHY_INTERFACE_MODE_RGMII: + dp = dsa_to_port(ds, port); + phydev = (dp->slave) ? dp->slave->phydev : NULL; + return an8855_rgmii_setup(priv, port, interface, phydev); + case PHY_INTERFACE_MODE_SGMII: + return an8855_sgmii_setup_mode_an(priv, port, interface); + case PHY_INTERFACE_MODE_2500BASEX: + if (phylink_autoneg_inband(mode)) + return -EINVAL; + return an8855_set_hsgmii_mode(priv); + default: + return -EINVAL; + } + + return -EINVAL; +} + +static int +an8855_sw_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state) +{ + struct an8855_priv *priv = ds->priv; + + return priv->info->mac_port_config(ds, port, mode, state->interface); +} + +static void +an8855_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state) +{ + struct an8855_priv *priv = ds->priv; + u32 mcr_cur, mcr_new; + + if (!an8855_phy_mode_supported(ds, port, state)) + goto unsupported; + + switch (port) { + case 0: /* Internal phy */ + case 1: + case 2: + case 3: + case 4: + if (state->interface != PHY_INTERFACE_MODE_GMII) + goto unsupported; + break; + case 5: + if (priv->p5_interface == state->interface) + break; + + if (an8855_sw_mac_config(ds, port, mode, state) < 0) + goto unsupported; + + priv->p5_interface = state->interface; + break; + default: +unsupported: + dev_err(ds->dev, "%s: unsupported %s port: %i\n", + __func__, phy_modes(state->interface), port); + return; + } + + if (phylink_autoneg_inband(mode) && + state->interface != PHY_INTERFACE_MODE_SGMII) { + dev_err(ds->dev, "%s: in-band negotiation unsupported\n", + __func__); + return; + } + + mcr_cur = an8855_read(priv, AN8855_PMCR_P(port)); + mcr_new = mcr_cur; + mcr_new &= ~PMCR_LINK_SETTINGS_MASK; + mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | + PMCR_BACKPR_EN | AN8855_FORCE_MODE; + + if (mcr_new != mcr_cur) + an8855_write(priv, AN8855_PMCR_P(port), mcr_new); +} + +static void +an8855_phylink_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) +{ + struct an8855_priv *priv = ds->priv; + + an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); +} + +static void +an8855_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, + struct phy_device *phydev, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct an8855_priv *priv = ds->priv; + u32 mcr; + + mcr = an8855_read(priv, AN8855_PMCR_P(port)); + mcr |= PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; + mcr &= + ~(PMCR_FORCE_FDX | PMCR_SPEED_MASK | PMCR_TX_FC_EN | PMCR_RX_FC_EN); + + if (interface == PHY_INTERFACE_MODE_RGMII + || interface == PHY_INTERFACE_MODE_SGMII) { + speed = SPEED_1000; + duplex = DUPLEX_FULL; + } else if (interface == PHY_INTERFACE_MODE_2500BASEX) { + speed = SPEED_2500; + duplex = DUPLEX_FULL; + } + + switch (speed) { + case SPEED_2500: + mcr |= PMCR_FORCE_SPEED_2500; + break; + case SPEED_1000: + mcr |= PMCR_FORCE_SPEED_1000; + if (priv->eee_enable & BIT(port)) + mcr |= PMCR_FORCE_EEE1G; + break; + case SPEED_100: + mcr |= PMCR_FORCE_SPEED_100; + if (priv->eee_enable & BIT(port)) + mcr |= PMCR_FORCE_EEE100; + break; + } + if (duplex == DUPLEX_FULL) { + mcr |= PMCR_FORCE_FDX; + if (tx_pause) + mcr |= PMCR_TX_FC_EN; + if (rx_pause) + mcr |= PMCR_RX_FC_EN; + } + + an8855_write(priv, AN8855_PMCR_P(port), mcr); +} + +static int +an8855_cpu_port_config(struct dsa_switch *ds, int port) +{ + struct an8855_priv *priv = ds->priv; + phy_interface_t interface = PHY_INTERFACE_MODE_NA; + int speed; + + switch (port) { + case 5: + interface = PHY_INTERFACE_MODE_2500BASEX; + + priv->p5_interface = interface; + break; + }; + if (interface == PHY_INTERFACE_MODE_NA) + dev_err(priv->dev, "invalid interface\n"); + + if (interface == PHY_INTERFACE_MODE_2500BASEX) + speed = SPEED_2500; + else + speed = SPEED_1000; + + an8855_mac_config(ds, port, MLO_AN_FIXED, interface); + an8855_write(priv, AN8855_PMCR_P(port), + PMCR_CPU_PORT_SETTING(priv->id)); + an8855_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL, + speed, DUPLEX_FULL, true, true); + + return 0; +} + +static void +an8855_mac_port_validate(struct dsa_switch *ds, int port, + unsigned long *supported) +{ + struct an8855_priv *priv = ds->priv; + + an8855_sgmii_validate(priv, port, supported); +} + +static void +an8855_phylink_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) +{ + struct an8855_priv *priv = ds->priv; + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = {0,}; + + if (state->interface != PHY_INTERFACE_MODE_NA && + !an8855_phy_mode_supported(ds, port, state)) { + linkmode_zero(supported); + return; + } + + phylink_set_port_modes(mask); + + if (state->interface != PHY_INTERFACE_MODE_TRGMII + || state->interface != PHY_INTERFACE_MODE_USXGMII + || state->interface != PHY_INTERFACE_MODE_10GKR + || !phy_interface_mode_is_8023z(state->interface)) { + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); + phylink_set(mask, Autoneg); + } + + /* This switch only supports 1G full-duplex. */ + if (state->interface != PHY_INTERFACE_MODE_MII) + phylink_set(mask, 1000baseT_Full); + + priv->info->mac_port_validate(ds, port, mask); + + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); + + /* We can only operate at 2500BaseX or 1000BaseX. If requested + * to advertise both, only report advertising at 2500BaseX. + */ + phylink_helper_basex_speed(state); +} + +static int +an8855_get_mac_eee(struct dsa_switch *ds, int port, + struct ethtool_eee *e) +{ + struct an8855_priv *priv = ds->priv; + u32 eeecr, pmsr, ckgcr; + + e->eee_enabled = !!(priv->eee_enable & BIT(port)); + + if (e->eee_enabled) { + eeecr = an8855_read(priv, AN8855_PMEEECR_P(port)); + e->tx_lpi_enabled = !(eeecr & LPI_MODE_EN); + ckgcr = an8855_read(priv, AN8855_CKGCR); + e->tx_lpi_timer = + ((ckgcr & LPI_TXIDLE_THD_MASK) >> LPI_TXIDLE_THD) / 500; + pmsr = an8855_read(priv, AN8855_PMSR_P(port)); + e->eee_active = e->eee_enabled + && !!(pmsr & (PMSR_EEE1G | PMSR_EEE100M)); + } else { + e->tx_lpi_enabled = 0; + e->tx_lpi_timer = 0; + e->eee_active = 0; + } + return 0; +} + +static int +an8855_set_mac_eee(struct dsa_switch *ds, int port, + struct ethtool_eee *e) +{ + struct an8855_priv *priv = ds->priv; + u32 eeecr; + + if (e->eee_enabled) { + priv->eee_enable |= BIT(port); + eeecr = an8855_read(priv, AN8855_PMEEECR_P(port)); + eeecr &= ~LPI_MODE_EN; + if (e->tx_lpi_enabled) + eeecr |= LPI_MODE_EN; + an8855_write(priv, AN8855_PMEEECR_P(port), eeecr); + } else { + priv->eee_enable &= ~(BIT(port)); + eeecr = an8855_read(priv, AN8855_PMEEECR_P(port)); + eeecr &= ~LPI_MODE_EN; + an8855_write(priv, AN8855_PMEEECR_P(port), eeecr); + } + + return 0; +} + +static int +an8855_phylink_mac_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +{ + struct an8855_priv *priv = ds->priv; + u32 pmsr; + + if (port < 0 || port >= AN8855_NUM_PORTS) + return -EINVAL; + + pmsr = an8855_read(priv, AN8855_PMSR_P(port)); + + state->link = (pmsr & PMSR_LINK); + state->an_complete = state->link; + state->duplex = !!(pmsr & PMSR_DPX); + + switch (pmsr & PMSR_SPEED_MASK) { + case PMSR_SPEED_10: + state->speed = SPEED_10; + break; + case PMSR_SPEED_100: + state->speed = SPEED_100; + break; + case PMSR_SPEED_1000: + state->speed = SPEED_1000; + break; + case PMSR_SPEED_2500: + state->speed = SPEED_2500; + break; + default: + state->speed = SPEED_UNKNOWN; + break; + } + + state->pause &= ~(MLO_PAUSE_RX | MLO_PAUSE_TX); + if (pmsr & PMSR_RX_FC) + state->pause |= MLO_PAUSE_RX; + if (pmsr & PMSR_TX_FC) + state->pause |= MLO_PAUSE_TX; + + return 1; +} + +static int +an8855_sw_phylink_mac_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +{ + struct an8855_priv *priv = ds->priv; + + return priv->info->mac_port_get_state(ds, port, state); +} + +static int +an8855_sw_setup(struct dsa_switch *ds) +{ + struct an8855_priv *priv = ds->priv; + + return priv->info->sw_setup(ds); +} + +static int +an8855_sw_phy_read(struct dsa_switch *ds, int port, int regnum) +{ + struct an8855_priv *priv = ds->priv; + + return priv->info->phy_read(ds, port, regnum); +} + +static int +an8855_sw_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) +{ + struct an8855_priv *priv = ds->priv; + + return priv->info->phy_write(ds, port, regnum, val); +} + +static const struct dsa_switch_ops an8855_switch_ops = { + .get_tag_protocol = air_get_tag_protocol, + .setup = an8855_sw_setup, + .get_strings = an8855_get_strings, + .phy_read = an8855_sw_phy_read, + .phy_write = an8855_sw_phy_write, + .get_ethtool_stats = an8855_get_ethtool_stats, + .get_sset_count = an8855_get_sset_count, + .port_enable = an8855_port_enable, + .port_disable = an8855_port_disable, + .port_stp_state_set = an8855_stp_state_set, + .port_bridge_join = an8855_port_bridge_join, + .port_bridge_leave = an8855_port_bridge_leave, + .port_fdb_add = an8855_port_fdb_add, + .port_fdb_del = an8855_port_fdb_del, + .port_fdb_dump = an8855_port_fdb_dump, + .port_vlan_filtering = an8855_port_vlan_filtering, + .port_vlan_prepare = an8855_port_vlan_prepare, + .port_vlan_add = an8855_port_vlan_add, + .port_vlan_del = an8855_port_vlan_del, + .port_mirror_add = an8855_port_mirror_add, + .port_mirror_del = an8855_port_mirror_del, + .phylink_validate = an8855_phylink_validate, + .phylink_mac_link_state = an8855_sw_phylink_mac_link_state, + .phylink_mac_config = an8855_phylink_mac_config, + .phylink_mac_link_down = an8855_phylink_mac_link_down, + .phylink_mac_link_up = an8855_phylink_mac_link_up, + .get_mac_eee = an8855_get_mac_eee, + .set_mac_eee = an8855_set_mac_eee, +}; + +static const struct an8855_dev_info an8855_table[] = { + [ID_AN8855] = { + .id = ID_AN8855, + .sw_setup = an8855_setup, + .phy_read = an8855_phy_read, + .phy_write = an8855_phy_write, + .pad_setup = an8855_pad_setup, + .cpu_port_config = an8855_cpu_port_config, + .phy_mode_supported = an8855_phy_supported, + .mac_port_validate = an8855_mac_port_validate, + .mac_port_get_state = an8855_phylink_mac_link_state, + .mac_port_config = an8855_mac_config, + }, +}; + +static const struct of_device_id an8855_of_match[] = { + {.compatible = "airoha,an8855", .data = &an8855_table[ID_AN8855], + }, + { /* sentinel */ }, +}; + +MODULE_DEVICE_TABLE(of, an8855_of_match); + +static int +an8855_probe(struct mdio_device *mdiodev) +{ + struct an8855_priv *priv; + struct device_node *dn; + struct device_node *switch_node = NULL; + int ret; + + dn = mdiodev->dev.of_node; + + priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->ds = dsa_switch_alloc(&mdiodev->dev, AN8855_NUM_PORTS); + if (!priv->ds) + return -ENOMEM; + + /* Get the hardware identifier from the devicetree node. + * We will need it for some of the clock and regulator setup. + */ + priv->info = of_device_get_match_data(&mdiodev->dev); + if (!priv->info) + return -EINVAL; + + /* Sanity check if these required device operations are filled + * properly. + */ + if (!priv->info->sw_setup || !priv->info->pad_setup || + !priv->info->phy_read || !priv->info->phy_write || + !priv->info->phy_mode_supported || + !priv->info->mac_port_validate || + !priv->info->mac_port_get_state || !priv->info->mac_port_config) + return -EINVAL; + + dev_info(&mdiodev->dev, "Airoha AN8855 DSA driver, version %s\n", + ARHT_AN8855_DSA_DRIVER_VER); + priv->phy_base = AN8855_GPHY_SMI_ADDR_DEFAULT; + priv->id = priv->info->id; + + priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(priv->reset)) { + dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); + return PTR_ERR(priv->reset); + } + + switch_node = of_find_node_by_name(NULL, "switch0"); + if (switch_node) { + priv->base = of_iomap(switch_node, 0); + if (priv->base == NULL) { + dev_err(&mdiodev->dev, "of_iomap failed\n"); + return -ENOMEM; + } + } + + ret = of_property_read_u32(dn, "changesmiaddr", &priv->phy_base_new); + if ((ret < 0) || (priv->phy_base_new > 0x1f)) + priv->phy_base_new = -1; + + priv->bus = mdiodev->bus; + priv->dev = &mdiodev->dev; + priv->ds->priv = priv; + priv->ds->ops = &an8855_switch_ops; + mutex_init(&priv->reg_mutex); + dev_set_drvdata(&mdiodev->dev, priv); + + ret = dsa_register_switch(priv->ds); + if (ret) { + if (priv->base) + iounmap(priv->base); + + return ret; + } + an8855_nl_init(&priv); + + return 0; +} + +static void +an8855_remove(struct mdio_device *mdiodev) +{ + struct an8855_priv *priv = dev_get_drvdata(&mdiodev->dev); + + dsa_unregister_switch(priv->ds); + mutex_destroy(&priv->reg_mutex); + + if (priv->base) + iounmap(priv->base); + + an8855_nl_exit(); +} + +static struct mdio_driver an8855_mdio_driver = { + .probe = an8855_probe, + .remove = an8855_remove, + .mdiodrv.driver = { + .name = "an8855", + .of_match_table = an8855_of_match, + }, +}; + +mdio_module_driver(an8855_mdio_driver); + +MODULE_AUTHOR("Min Yao "); +MODULE_DESCRIPTION("Driver for Airoha AN8855 Switch"); +MODULE_VERSION(ARHT_AN8855_DSA_DRIVER_VER); +MODULE_LICENSE("GPL"); diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.h new file mode 100644 index 000000000..531d9be8a --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.h @@ -0,0 +1,580 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 Min Yao + */ + +#ifndef __AN8855_H +#define __AN8855_H + +#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n))) + +#define AN8855_NUM_PORTS 6 +#define AN8855_CPU_PORT 5 +#define AN8855_NUM_FDB_RECORDS 2048 +#define AN8855_ALL_MEMBERS 0x3f +#define AN8855_RESERVED_VLAN 2 +#define AN8855_GPHY_SMI_ADDR_DEFAULT 1 + +enum an8855_id { + ID_AN8855 = 0, +}; + +enum sgmii_mode { + SGMII_MODE_AN, + SGMII_MODE_FORCE, +}; + +/* Registers to mac forward control for unknown frames */ +#define AN8855_MFC 0x10200010 +#define CPU_EN BIT(15) +#define CPU_PORT(x) ((x) << 8) +#define CPU_MASK (0x9f << 8) + +#define AN8855_UNUF 0x102000b4 +#define AN8855_UNMF 0x102000b8 +#define AN8855_BCF 0x102000bc + +/* Registers for mirror port control */ +#define AN8855_MIR 0x102000cc +#define AN8855_MIRROR_EN BIT(7) +#define AN8855_MIRROR_MASK (0x1f) +#define AN8855_MIRROR_PORT_GET(x) ((x) & AN8855_MIRROR_MASK) +#define AN8855_MIRROR_PORT_SET(x) ((x) & AN8855_MIRROR_MASK) + +/* Registers for BPDU and PAE frame control*/ +#define AN8855_BPC 0x102000D0 +#define AN8855_BPDU_PORT_FW_MASK GENMASK(2, 0) + +enum an8855_bpdu_port_fw { + AN8855_BPDU_FOLLOW_MFC, + AN8855_BPDU_CPU_EXCLUDE = 4, + AN8855_BPDU_CPU_INCLUDE = 5, + AN8855_BPDU_CPU_ONLY = 6, + AN8855_BPDU_DROP = 7, +}; + +/* Registers for address table access */ +#define AN8855_ATA1 0x10200304 +#define AN8855_ATA2 0x10200308 + +/* Register for address table write data */ +#define AN8855_ATWD 0x10200324 +#define AN8855_ATWD2 0x10200328 + +/* Register for address table control */ +#define AN8855_ATC 0x10200300 +#define ATC_BUSY BIT(31) +#define ATC_INVALID ~BIT(30) +#define ATC_HASH 16 +#define ATC_HASH_MASK 0x1ff +#define ATC_HIT 12 +#define ATC_HIT_MASK 0xf +#define ATC_MAT(x) (((x) & 0x1f) << 7) +#define ATC_MAT_MACTAB ATC_MAT(1) + +enum an8855_fdb_cmds { + AN8855_FDB_READ = 0, + AN8855_FDB_WRITE = 1, + AN8855_FDB_FLUSH = 2, + AN8855_FDB_START = 4, + AN8855_FDB_NEXT = 5, +}; + +/* Registers for table search read address */ +#define AN8855_ATRDS 0x10200330 +#define AN8855_ATRD0 0x10200334 +#define CVID 10 +#define CVID_MASK 0xfff + +enum an8855_fdb_type { + AN8855_MAC_TB_TY_MAC = 0, + AN8855_MAC_TB_TY_DIP = 1, + AN8855_MAC_TB_TY_DIP_SIP = 2, +}; + +#define AN8855_ATRD1 0x10200338 +#define MAC_BYTE_4 24 +#define MAC_BYTE_5 16 +#define AGE_TIMER 3 +#define AGE_TIMER_MASK 0x1ff + +#define AN8855_ATRD2 0x1020033c +#define MAC_BYTE_0 24 +#define MAC_BYTE_1 16 +#define MAC_BYTE_2 8 +#define MAC_BYTE_3 0 +#define MAC_BYTE_MASK 0xff + +#define AN8855_ATRD3 0x10200340 +#define PORT_MAP 4 +#define PORT_MAP_MASK 0xff + +/* Register for vlan table control */ +#define AN8855_VTCR 0x10200600 +#define VTCR_BUSY BIT(31) +#define VTCR_FUNC(x) (((x) & 0xf) << 12) +#define VTCR_VID ((x) & 0xfff) + +enum an8855_vlan_cmd { + /* Read/Write the specified VID entry from VAWD register based + * on VID. + */ + AN8855_VTCR_RD_VID = 0, + AN8855_VTCR_WR_VID = 1, +}; + +/* Register for setup vlan write data */ +#define AN8855_VAWD0 0x10200604 + +/* Independent VLAN Learning */ +#define IVL_MAC BIT(5) +/* Per VLAN Egress Tag Control */ +#define VTAG_EN BIT(10) +/* Egress Tag Control */ +#define PORT_EG_CTRL_SHIFT 12 +/* VLAN Member Control */ +#define PORT_MEM_SHFT 26 +#define PORT_MEM_MASK 0x7f +#define PORT_MEM(x) (((x) & PORT_MEM_MASK) << PORT_MEM_SHFT) +/* VLAN Entry Valid */ +#define VLAN_VALID BIT(0) + +#define AN8855_VAWD1 0x10200608 +#define PORT_STAG BIT(1) +/* Egress Tag Control */ +#define ETAG_CTRL_P(p, x) (((x) & 0x3) << ((p) << 1)) +#define ETAG_CTRL_P_MASK(p) ETAG_CTRL_P(p, 3) +#define ETAG_CTRL_MASK (0x3FFF) + +#define AN8855_VARD0 0x10200618 + +enum an8855_vlan_egress_attr { + AN8855_VLAN_EGRESS_UNTAG = 0, + AN8855_VLAN_EGRESS_TAG = 2, + AN8855_VLAN_EGRESS_STACK = 3, +}; + +/* Register for port STP state control */ +#define AN8855_SSP_P(x) (0x10208000 + ((x) * 0x200)) +#define FID_PST(x) ((x) & 0x3) +#define FID_PST_MASK FID_PST(0x3) + +enum an8855_stp_state { + AN8855_STP_DISABLED = 0, + AN8855_STP_BLOCKING = 1, + AN8855_STP_LISTENING = 1, + AN8855_STP_LEARNING = 2, + AN8855_STP_FORWARDING = 3 +}; + +/* Register for port control */ +#define AN8855_PCR_P(x) (0x10208004 + ((x) * 0x200)) +#define PORT_TX_MIR BIT(20) +#define PORT_RX_MIR BIT(16) +#define PORT_VLAN(x) ((x) & 0x3) + +enum an8855_port_mode { + /* Port Matrix Mode: Frames are forwarded by the PCR_MATRIX members. */ + AN8855_PORT_MATRIX_MODE = PORT_VLAN(0), + + /* Fallback Mode: Forward received frames with ingress ports that do + * not belong to the VLAN member. Frames whose VID is not listed on + * the VLAN table are forwarded by the PCR_MATRIX members. + */ + AN8855_PORT_FALLBACK_MODE = PORT_VLAN(1), + + /* Security Mode: Discard any frame due to ingress membership + * violation or VID missed on the VLAN table. + */ + AN8855_PORT_SECURITY_MODE = PORT_VLAN(3), +}; + +#define PORT_PRI(x) (((x) & 0x7) << 24) +#define EG_TAG(x) (((x) & 0x3) << 28) +#define PCR_PORT_VLAN_MASK PORT_VLAN(3) + +/* Register for port security control */ +#define AN8855_PSC_P(x) (0x1020800c + ((x) * 0x200)) +#define SA_DIS BIT(4) + +/* Register for port vlan control */ +#define AN8855_PVC_P(x) (0x10208010 + ((x) * 0x200)) +#define PORT_SPEC_REPLACE_MODE BIT(11) +#define PORT_SPEC_TAG BIT(5) +#define PVC_EG_TAG(x) (((x) & 0x7) << 8) +#define PVC_EG_TAG_MASK PVC_EG_TAG(7) +#define VLAN_ATTR(x) (((x) & 0x3) << 6) +#define VLAN_ATTR_MASK VLAN_ATTR(3) + +#define AN8855_PORTMATRIX_P(x) (0x10208044 + ((x) * 0x200)) +#define PORTMATRIX_MATRIX(x) ((x) & 0x3f) +#define PORTMATRIX_MASK PORTMATRIX_MATRIX(0x3f) +#define PORTMATRIX_CLR PORTMATRIX_MATRIX(0) + +enum an8855_vlan_port_eg_tag { + AN8855_VLAN_EG_DISABLED = 0, + AN8855_VLAN_EG_CONSISTENT = 1, +}; + +enum an8855_vlan_port_attr { + AN8855_VLAN_USER = 0, + AN8855_VLAN_TRANSPARENT = 3, +}; + +/* Register for port PVID */ +#define AN8855_PVID_P(x) (0x10208048 + ((x) * 0x200)) +#define G0_PORT_VID(x) (((x) & 0xfff) << 0) +#define G0_PORT_VID_MASK G0_PORT_VID(0xfff) +#define G0_PORT_VID_DEF G0_PORT_VID(1) + +/* Register for port MAC control register */ +#define AN8855_PMCR_P(x) (0x10210000 + ((x) * 0x200)) +#define PMCR_IFG_XMIT(x) (((x) & 0x3) << 20) +#define PMCR_EXT_PHY BIT(19) +#define PMCR_MAC_MODE BIT(18) +#define PMCR_FORCE_MODE BIT(31) +#define PMCR_TX_EN BIT(16) +#define PMCR_RX_EN BIT(15) +#define PMCR_BACKOFF_EN BIT(12) +#define PMCR_BACKPR_EN BIT(11) +#define PMCR_FORCE_EEE2P5G BIT(8) +#define PMCR_FORCE_EEE1G BIT(7) +#define PMCR_FORCE_EEE100 BIT(6) +#define PMCR_TX_FC_EN BIT(5) +#define PMCR_RX_FC_EN BIT(4) +#define PMCR_FORCE_SPEED_2500 (0x3 << 28) +#define PMCR_FORCE_SPEED_1000 (0x2 << 28) +#define PMCR_FORCE_SPEED_100 (0x1 << 28) +#define PMCR_FORCE_FDX BIT(25) +#define PMCR_FORCE_LNK BIT(24) +#define PMCR_SPEED_MASK BITS(28, 30) +#define AN8855_FORCE_LNK BIT(31) +#define AN8855_FORCE_MODE (AN8855_FORCE_LNK) +#define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | \ + PMCR_RX_EN | PMCR_FORCE_SPEED_2500 | \ + PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ + PMCR_FORCE_FDX | PMCR_FORCE_LNK) +#define PMCR_CPU_PORT_SETTING(id) (AN8855_FORCE_MODE | \ + PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ + PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \ + PMCR_TX_EN | PMCR_RX_EN | \ + PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ + PMCR_FORCE_SPEED_2500 | \ + PMCR_FORCE_FDX | PMCR_FORCE_LNK) + +#define AN8855_PMSR_P(x) (0x10210010 + (x) * 0x200) +#define PMSR_EEE1G BIT(7) +#define PMSR_EEE100M BIT(6) +#define PMSR_RX_FC BIT(5) +#define PMSR_TX_FC BIT(4) +#define PMSR_SPEED_2500 (0x3 << 28) +#define PMSR_SPEED_1000 (0x2 << 28) +#define PMSR_SPEED_100 (0x1 << 28) +#define PMSR_SPEED_10 (0x0 << 28) +#define PMSR_SPEED_MASK BITS(28, 30) +#define PMSR_DPX BIT(25) +#define PMSR_LINK BIT(24) + +#define AN8855_PMEEECR_P(x) (0x10210004 + (x) * 0x200) +#define WAKEUP_TIME_2500(x) ((x & 0xFF) << 16) +#define WAKEUP_TIME_1000(x) ((x & 0xFF) << 8) +#define WAKEUP_TIME_100(x) ((x & 0xFF) << 0) +#define LPI_MODE_EN BIT(31) +#define AN8855_PMEEECR2_P(x) (0x10210008 + (x) * 0x200) +#define WAKEUP_TIME_5000(x) ((x & 0xFF) << 0) + +#define AN8855_CKGCR (0x10213e1c) +#define LPI_TXIDLE_THD 14 +#define LPI_TXIDLE_THD_MASK BITS(14, 31) + +/* Register for MIB */ +#define AN8855_PORT_MIB_COUNTER(x) (0x10214000 + (x) * 0x200) +#define AN8855_MIB_CCR 0x10213e30 +#define CCR_MIB_ENABLE BIT(31) +#define CCR_RX_OCT_CNT_GOOD BIT(7) +#define CCR_RX_OCT_CNT_BAD BIT(6) +#define CCR_TX_OCT_CNT_GOOD BIT(5) +#define CCR_TX_OCT_CNT_BAD BIT(4) +#define CCR_RX_OCT_CNT_GOOD_2 BIT(3) +#define CCR_RX_OCT_CNT_BAD_2 BIT(2) +#define CCR_TX_OCT_CNT_GOOD_2 BIT(1) +#define CCR_TX_OCT_CNT_BAD_2 BIT(0) +#define CCR_MIB_FLUSH (CCR_RX_OCT_CNT_GOOD | \ + CCR_RX_OCT_CNT_BAD | \ + CCR_TX_OCT_CNT_GOOD | \ + CCR_TX_OCT_CNT_BAD | \ + CCR_RX_OCT_CNT_GOOD_2 | \ + CCR_RX_OCT_CNT_BAD_2 | \ + CCR_TX_OCT_CNT_GOOD_2 | \ + CCR_TX_OCT_CNT_BAD_2) +#define CCR_MIB_ACTIVATE (CCR_MIB_ENABLE | \ + CCR_RX_OCT_CNT_GOOD | \ + CCR_RX_OCT_CNT_BAD | \ + CCR_TX_OCT_CNT_GOOD | \ + CCR_TX_OCT_CNT_BAD | \ + CCR_RX_OCT_CNT_GOOD_2 | \ + CCR_RX_OCT_CNT_BAD_2 | \ + CCR_TX_OCT_CNT_GOOD_2 | \ + CCR_TX_OCT_CNT_BAD_2) + +/* AN8855 SGMII register group */ +#define AN8855_SGMII_REG_BASE 0x10220000 +#define AN8855_SGMII_REG(p, r) (AN8855_SGMII_REG_BASE + \ + ((p) - 5) * 0x1000 + (r)) + +/* Register forSGMII PCS_CONTROL_1 */ +#define AN8855_PCS_CONTROL_1(p) AN8855_SGMII_REG(p, 0x00) +#define AN8855_SGMII_AN_ENABLE BIT(12) +#define AN8855_SGMII_AN_RESTART BIT(9) + +/* Register for system reset */ +#define AN8855_RST_CTRL 0x100050c0 +#define SYS_CTRL_SYS_RST BIT(31) + +/* Register for hw trap status */ +#define AN8855_HWTRAP 0x1000009c + +#define AN8855_CREV 0x10005000 +#define AN8855_ID 0x8855 + +#define SCU_BASE 0x10000000 +#define RG_RGMII_TXCK_C (SCU_BASE + 0x1d0) + +#define HSGMII_AN_CSR_BASE 0x10220000 +#define SGMII_REG_AN0 (HSGMII_AN_CSR_BASE + 0x000) +#define SGMII_REG_AN_13 (HSGMII_AN_CSR_BASE + 0x034) +#define SGMII_REG_AN_FORCE_CL37 (HSGMII_AN_CSR_BASE + 0x060) + +#define HSGMII_CSR_PCS_BASE 0x10220000 +#define RG_HSGMII_PCS_CTROL_1 (HSGMII_CSR_PCS_BASE + 0xa00) +#define RG_AN_SGMII_MODE_FORCE (HSGMII_CSR_PCS_BASE + 0xa24) + +#define MULTI_SGMII_CSR_BASE 0x10224000 +#define SGMII_STS_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x018) +#define MSG_RX_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x100) +#define MSG_RX_LIK_STS_0 (MULTI_SGMII_CSR_BASE + 0x514) +#define MSG_RX_LIK_STS_2 (MULTI_SGMII_CSR_BASE + 0x51c) +#define PHY_RX_FORCE_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x520) + +#define XFI_CSR_PCS_BASE 0x10225000 +#define RG_USXGMII_AN_CONTROL_0 (XFI_CSR_PCS_BASE + 0xbf8) + +#define MULTI_PHY_RA_CSR_BASE 0x10226000 +#define RG_RATE_ADAPT_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x000) +#define RATE_ADP_P0_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x100) +#define MII_RA_AN_ENABLE (MULTI_PHY_RA_CSR_BASE + 0x300) + +#define QP_DIG_CSR_BASE 0x1022a000 +#define QP_CK_RST_CTRL_4 (QP_DIG_CSR_BASE + 0x310) +#define QP_DIG_MODE_CTRL_0 (QP_DIG_CSR_BASE + 0x324) +#define QP_DIG_MODE_CTRL_1 (QP_DIG_CSR_BASE + 0x330) + +#define SERDES_WRAPPER_BASE 0x1022c000 +#define USGMII_CTRL_0 (SERDES_WRAPPER_BASE + 0x000) + +#define QP_PMA_TOP_BASE 0x1022e000 +#define PON_RXFEDIG_CTRL_0 (QP_PMA_TOP_BASE + 0x100) +#define PON_RXFEDIG_CTRL_9 (QP_PMA_TOP_BASE + 0x124) + +#define SS_LCPLL_PWCTL_SETTING_2 (QP_PMA_TOP_BASE + 0x208) +#define SS_LCPLL_TDC_FLT_2 (QP_PMA_TOP_BASE + 0x230) +#define SS_LCPLL_TDC_FLT_5 (QP_PMA_TOP_BASE + 0x23c) +#define SS_LCPLL_TDC_PCW_1 (QP_PMA_TOP_BASE + 0x248) +#define INTF_CTRL_8 (QP_PMA_TOP_BASE + 0x320) +#define INTF_CTRL_9 (QP_PMA_TOP_BASE + 0x324) +#define PLL_CTRL_0 (QP_PMA_TOP_BASE + 0x400) +#define PLL_CTRL_2 (QP_PMA_TOP_BASE + 0x408) +#define PLL_CTRL_3 (QP_PMA_TOP_BASE + 0x40c) +#define PLL_CTRL_4 (QP_PMA_TOP_BASE + 0x410) +#define PLL_CK_CTRL_0 (QP_PMA_TOP_BASE + 0x414) +#define RX_DLY_0 (QP_PMA_TOP_BASE + 0x614) +#define RX_CTRL_2 (QP_PMA_TOP_BASE + 0x630) +#define RX_CTRL_5 (QP_PMA_TOP_BASE + 0x63c) +#define RX_CTRL_6 (QP_PMA_TOP_BASE + 0x640) +#define RX_CTRL_7 (QP_PMA_TOP_BASE + 0x644) +#define RX_CTRL_8 (QP_PMA_TOP_BASE + 0x648) +#define RX_CTRL_26 (QP_PMA_TOP_BASE + 0x690) +#define RX_CTRL_42 (QP_PMA_TOP_BASE + 0x6d0) + +#define QP_ANA_CSR_BASE 0x1022f000 +#define RG_QP_RX_DAC_EN (QP_ANA_CSR_BASE + 0x00) +#define RG_QP_RXAFE_RESERVE (QP_ANA_CSR_BASE + 0x04) +#define RG_QP_CDR_LPF_MJV_LIM (QP_ANA_CSR_BASE + 0x0c) +#define RG_QP_CDR_LPF_SETVALUE (QP_ANA_CSR_BASE + 0x14) +#define RG_QP_CDR_PR_CKREF_DIV1 (QP_ANA_CSR_BASE + 0x18) +#define RG_QP_CDR_PR_KBAND_DIV_PCIE (QP_ANA_CSR_BASE + 0x1c) +#define RG_QP_CDR_FORCE_IBANDLPF_R_OFF (QP_ANA_CSR_BASE + 0x20) +#define RG_QP_TX_MODE_16B_EN (QP_ANA_CSR_BASE + 0x28) +#define RG_QP_PLL_IPLL_DIG_PWR_SEL (QP_ANA_CSR_BASE + 0x3c) +#define RG_QP_PLL_SDM_ORD (QP_ANA_CSR_BASE + 0x40) + +#define ETHER_SYS_BASE 0x1028c800 +#define RG_GPHY_AFE_PWD (ETHER_SYS_BASE + 0x40) +#define RG_GPHY_SMI_ADDR (ETHER_SYS_BASE + 0x48) + +#define MIB_DESC(_s, _o, _n) \ + { \ + .size = (_s), \ + .offset = (_o), \ + .name = (_n), \ + } + +struct an8855_mib_desc { + unsigned int size; + unsigned int offset; + const char *name; +}; + +struct an8855_fdb { + u16 vid; + u8 port_mask; + u8 aging; + u8 mac[6]; + bool noarp; + u8 live; + u8 type; + u8 fid; + u8 ivl; +}; + +/* struct an8855_port - This is the main data structure for holding the state + * of the port. + * @enable: The status used for show port is enabled or not. + * @pm: The matrix used to show all connections with the port. + * @pvid: The VLAN specified is to be considered a PVID at ingress. Any + * untagged frames will be assigned to the related VLAN. + * @vlan_filtering: The flags indicating whether the port that can recognize + * VLAN-tagged frames. + */ +struct an8855_port { + bool enable; + u32 pm; + u16 pvid; +}; + +/* struct an8855_info - This is the main data structure for holding the specific + * part for each supported device + * @sw_setup: Holding the handler to a device initialization + * @phy_read: Holding the way reading PHY port + * @phy_write: Holding the way writing PHY port + * @pad_setup: Holding the way setting up the bus pad for a certain + * MAC port + * @phy_mode_supported: Check if the PHY type is being supported on a certain + * port + * @mac_port_validate: Holding the way to set addition validate type for a + * certan MAC port + * @mac_port_get_state: Holding the way getting the MAC/PCS state for a certain + * MAC port + * @mac_port_config: Holding the way setting up the PHY attribute to a + * certain MAC port + * @mac_pcs_an_restart Holding the way restarting PCS autonegotiation for a + * certain MAC port + * @mac_pcs_link_up: Holding the way setting up the PHY attribute to the pcs + * of the certain MAC port + */ +struct an8855_dev_info { + enum an8855_id id; + + int (*sw_setup)(struct dsa_switch *ds); + int (*phy_read)(struct dsa_switch *ds, int port, int regnum); + int (*phy_write)(struct dsa_switch *ds, int port, int regnum, + u16 val); + int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); + int (*cpu_port_config)(struct dsa_switch *ds, int port); + bool (*phy_mode_supported)(struct dsa_switch *ds, int port, + const struct phylink_link_state *state); + void (*mac_port_validate)(struct dsa_switch *ds, int port, + unsigned long *supported); + int (*mac_port_get_state)(struct dsa_switch *ds, int port, + struct phylink_link_state *state); + int (*mac_port_config)(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface); + void (*mac_pcs_an_restart)(struct dsa_switch *ds, int port); +}; + +/* struct an8855_priv - This is the main data structure for holding the state + * of the driver + * @dev: The device pointer + * @ds: The pointer to the dsa core structure + * @bus: The bus used for the device and built-in PHY + * @rstc: The pointer to reset control used by MCM + * @core_pwr: The power supplied into the core + * @io_pwr: The power supplied into the I/O + * @reset: The descriptor for GPIO line tied to its reset pin + * @mcm: Flag for distinguishing if standalone IC or module + * coupling + * @ports: Holding the state among ports + * @reg_mutex: The lock for protecting among process accessing + * registers + * @p6_interface Holding the current port 6 interface + * @p5_intf_sel: Holding the current port 5 interface select + */ +struct an8855_priv { + struct device *dev; + struct dsa_switch *ds; + struct mii_bus *bus; + struct reset_control *rstc; + struct regulator *core_pwr; + struct regulator *io_pwr; + struct gpio_desc *reset; + void __iomem *base; + const struct an8855_dev_info *info; + unsigned int phy_base; + int phy_base_new; + unsigned int id; + phy_interface_t p5_interface; + unsigned int p5_intf_sel; + u8 mirror_rx; + u8 mirror_tx; + u8 eee_enable; + + struct an8855_port ports[AN8855_NUM_PORTS]; + /* protect among processes for registers access */ + struct mutex reg_mutex; +}; + +struct an8855_hw_vlan_entry { + int port; + u8 old_members; + bool untagged; +}; + +static inline void an8855_hw_vlan_entry_init(struct an8855_hw_vlan_entry *e, + int port, bool untagged) +{ + e->port = port; + e->untagged = untagged; +} + +typedef void (*an8855_vlan_op) (struct an8855_priv *, + struct an8855_hw_vlan_entry *); + +struct an8855_hw_stats { + const char *string; + u16 reg; + u8 sizeof_stat; +}; + +struct an8855_dummy_poll { + struct an8855_priv *priv; + u32 reg; +}; + +static inline void INIT_AN8855_DUMMY_POLL(struct an8855_dummy_poll *p, + struct an8855_priv *priv, u32 reg) +{ + p->priv = priv; + p->reg = reg; +} + +int an8855_phy_setup(struct dsa_switch *ds); +u32 an8855_read(struct an8855_priv *priv, u32 reg); +void an8855_write(struct an8855_priv *priv, u32 reg, u32 val); +int an8855_phy_cl22_read(struct an8855_priv *priv, int port, int regnum); +int an8855_phy_cl22_write(struct an8855_priv *priv, int port, + int regnum, u16 val); +int an8855_phy_cl45_read(struct an8855_priv *priv, int port, int devad, + int regnum); +int an8855_phy_cl45_write(struct an8855_priv *priv, int port, int devad, + int regnum, u16 val); +#endif /* __AN8855_H */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.c new file mode 100644 index 000000000..b80ce6fa8 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "an8855.h" +#include "an8855_nl.h" + +struct an8855_nl_cmd_item { + enum an8855_cmd cmd; + bool require_dev; + int (*process)(struct genl_info *info); + u32 nr_required_attrs; + const enum an8855_attr *required_attrs; +}; + +struct an8855_priv *an8855_sw_priv; + +static DEFINE_MUTEX(an8855_devs_lock); + +void +an8855_put(void) +{ + mutex_unlock(&an8855_devs_lock); +} + +void +an8855_lock(void) +{ + mutex_lock(&an8855_devs_lock); +} + +static int an8855_nl_response(struct sk_buff *skb, struct genl_info *info); + +static const struct nla_policy an8855_nl_cmd_policy[] = { + [AN8855_ATTR_TYPE_MESG] = {.type = NLA_STRING}, + [AN8855_ATTR_TYPE_PHY] = {.type = NLA_S32}, + [AN8855_ATTR_TYPE_REG] = {.type = NLA_S32}, + [AN8855_ATTR_TYPE_VAL] = {.type = NLA_S32}, + [AN8855_ATTR_TYPE_DEV_NAME] = {.type = NLA_S32}, + [AN8855_ATTR_TYPE_DEV_ID] = {.type = NLA_S32}, + [AN8855_ATTR_TYPE_DEVAD] = {.type = NLA_S32}, +}; + +static const struct genl_ops an8855_nl_ops[] = { + { + .cmd = AN8855_CMD_REQUEST, + .doit = an8855_nl_response, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = AN8855_CMD_READ, + .doit = an8855_nl_response, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = AN8855_CMD_WRITE, + .doit = an8855_nl_response, + .flags = GENL_ADMIN_PERM, + }, +}; + +static struct genl_family an8855_nl_family = { + .name = AN8855_DSA_GENL_NAME, + .version = AN8855_GENL_VERSION, + .maxattr = AN8855_NR_ATTR_TYPE, + .ops = an8855_nl_ops, + .n_ops = ARRAY_SIZE(an8855_nl_ops), + .policy = an8855_nl_cmd_policy, +}; + +static int +an8855_nl_prepare_reply(struct genl_info *info, u8 cmd, + struct sk_buff **skbp) +{ + struct sk_buff *msg; + void *reply; + + if (!info) + return -EINVAL; + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + /* Construct send-back message header */ + reply = genlmsg_put(msg, info->snd_portid, info->snd_seq, + &an8855_nl_family, 0, cmd); + if (!reply) { + nlmsg_free(msg); + return -EINVAL; + } + + *skbp = msg; + return 0; +} + +static int +an8855_nl_send_reply(struct sk_buff *skb, struct genl_info *info) +{ + struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb)); + void *reply = genlmsg_data(genlhdr); + + /* Finalize a generic netlink message (update message header) */ + genlmsg_end(skb, reply); + + /* reply to a request */ + return genlmsg_reply(skb, info); +} + +static s32 +an8855_nl_get_s32(struct genl_info *info, enum an8855_attr attr, + s32 defval) +{ + struct nlattr *na; + + na = info->attrs[attr]; + if (na) + return nla_get_s32(na); + + return defval; +} + +static int +an8855_nl_get_u32(struct genl_info *info, enum an8855_attr attr, + u32 *val) +{ + struct nlattr *na; + + na = info->attrs[attr]; + if (na) { + *val = nla_get_u32(na); + return 0; + } + + return -1; +} + +static int +an8855_nl_reply_read(struct genl_info *info) +{ + struct sk_buff *rep_skb = NULL; + s32 phy, devad, reg; + int value; + int ret = 0; + + phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1); + devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1); + reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1); + + if (reg < 0) + goto err; + + ret = an8855_nl_prepare_reply(info, AN8855_CMD_READ, &rep_skb); + if (ret < 0) + goto err; + if (phy >= 0) { + if (devad < 0) + value = an8855_phy_cl22_read(an8855_sw_priv, phy, reg); + else + value = an8855_phy_cl45_read(an8855_sw_priv, phy, + devad, reg); + } else + value = an8855_read(an8855_sw_priv, reg); + ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg); + if (ret < 0) + goto err; + + ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value); + if (ret < 0) + goto err; + + return an8855_nl_send_reply(rep_skb, info); + +err: + if (rep_skb) + nlmsg_free(rep_skb); + + return ret; +} + +static int +an8855_nl_reply_write(struct genl_info *info) +{ + struct sk_buff *rep_skb = NULL; + s32 phy, devad, reg; + u32 value; + int ret = 0; + + phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1); + devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1); + reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1); + + if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value)) + goto err; + + if (reg < 0) + goto err; + + ret = an8855_nl_prepare_reply(info, AN8855_CMD_WRITE, &rep_skb); + if (ret < 0) + goto err; + if (phy >= 0) { + if (devad < 0) + an8855_phy_cl22_write(an8855_sw_priv, phy, reg, value); + else + an8855_phy_cl45_write(an8855_sw_priv, phy, devad, reg, + value); + } else + an8855_write(an8855_sw_priv, reg, value); + ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg); + if (ret < 0) + goto err; + + ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value); + if (ret < 0) + goto err; + + return an8855_nl_send_reply(rep_skb, info); + +err: + if (rep_skb) + nlmsg_free(rep_skb); + + return ret; +} + +static const enum an8855_attr an8855_nl_cmd_read_attrs[] = { + AN8855_ATTR_TYPE_REG +}; + +static const enum an8855_attr an8855_nl_cmd_write_attrs[] = { + AN8855_ATTR_TYPE_REG, + AN8855_ATTR_TYPE_VAL +}; + +static const struct an8855_nl_cmd_item an8855_nl_cmds[] = { + { + .cmd = AN8855_CMD_READ, + .require_dev = true, + .process = an8855_nl_reply_read, + .required_attrs = an8855_nl_cmd_read_attrs, + .nr_required_attrs = ARRAY_SIZE(an8855_nl_cmd_read_attrs), + }, + { + .cmd = AN8855_CMD_WRITE, + .require_dev = true, + .process = an8855_nl_reply_write, + .required_attrs = an8855_nl_cmd_write_attrs, + .nr_required_attrs = ARRAY_SIZE(an8855_nl_cmd_write_attrs), + } +}; + +static int +an8855_nl_response(struct sk_buff *skb, struct genl_info *info) +{ + struct genlmsghdr *hdr = nlmsg_data(info->nlhdr); + const struct an8855_nl_cmd_item *cmditem = NULL; + u32 sat_req_attrs = 0; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(an8855_nl_cmds); i++) { + if (hdr->cmd == an8855_nl_cmds[i].cmd) { + cmditem = &an8855_nl_cmds[i]; + break; + } + } + + if (!cmditem) { + pr_info("an8855-nl: unknown cmd %u\n", hdr->cmd); + return -EINVAL; + } + + for (i = 0; i < cmditem->nr_required_attrs; i++) { + if (info->attrs[cmditem->required_attrs[i]]) + sat_req_attrs++; + } + + if (sat_req_attrs != cmditem->nr_required_attrs) { + pr_info("an8855-nl: missing required attr(s) for cmd %u\n", + hdr->cmd); + return -EINVAL; + } + + ret = cmditem->process(info); + + an8855_put(); + + return ret; +} + +int +an8855_nl_init(struct an8855_priv **priv) +{ + int ret; + + pr_info("an8855-nl: genl_register_family_with_ops\n"); + + an8855_sw_priv = *priv; + ret = genl_register_family(&an8855_nl_family); + if (ret) + return ret; + + return 0; +} + +void +an8855_nl_exit(void) +{ + an8855_sw_priv = NULL; + genl_unregister_family(&an8855_nl_family); +} diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.h new file mode 100644 index 000000000..f8a462d5d --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#ifndef _AN8855_NL_H_ +#define _AN8855_NL_H_ + +#define AN8855_DSA_GENL_NAME "an8855_dsa" +#define AN8855_GENL_VERSION 0x1 + +enum an8855_cmd { + AN8855_CMD_UNSPEC = 0, + AN8855_CMD_REQUEST, + AN8855_CMD_REPLY, + AN8855_CMD_READ, + AN8855_CMD_WRITE, + + __AN8855_CMD_MAX, +}; + +enum an8855_attr { + AN8855_ATTR_TYPE_UNSPEC = 0, + AN8855_ATTR_TYPE_MESG, + AN8855_ATTR_TYPE_PHY, + AN8855_ATTR_TYPE_DEVAD, + AN8855_ATTR_TYPE_REG, + AN8855_ATTR_TYPE_VAL, + AN8855_ATTR_TYPE_DEV_NAME, + AN8855_ATTR_TYPE_DEV_ID, + + __AN8855_ATTR_TYPE_MAX, +}; + +#define AN8855_NR_ATTR_TYPE (__AN8855_ATTR_TYPE_MAX - 1) + +#ifdef __KERNEL__ +int an8855_nl_init(struct an8855_priv **priv); +void an8855_nl_exit(void); +#endif /* __KERNEL__ */ + +#endif /* _AN8855_NL_H_ */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.c new file mode 100644 index 000000000..5499312e9 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Common part for Airoha AN8855 gigabit switch + * + * Copyright (C) 2023 Airoha Inc. All Rights Reserved. + * + * Author: Min Yao + */ + +#include +#include +#include +#include +#include "an8855.h" +#include "an8855_phy.h" + +#define AN8855_NUM_PHYS 5 + +static u32 +an8855_phy_read_dev_reg(struct dsa_switch *ds, u32 port_num, + u32 dev_addr, u32 reg_addr) +{ + struct an8855_priv *priv = ds->priv; + u32 phy_val; + u32 addr; + + addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff); + phy_val = priv->info->phy_read(ds, port_num, addr); + + return phy_val; +} + +static void +an8855_phy_write_dev_reg(struct dsa_switch *ds, u32 port_num, + u32 dev_addr, u32 reg_addr, u32 write_data) +{ + struct an8855_priv *priv = ds->priv; + u32 addr; + + addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff); + + priv->info->phy_write(ds, port_num, addr, write_data); +} + +static void +an8855_switch_phy_write(struct dsa_switch *ds, u32 port_num, + u32 reg_addr, u32 write_data) +{ + struct an8855_priv *priv = ds->priv; + + priv->info->phy_write(ds, port_num, reg_addr, write_data); +} + +static u32 +an8855_switch_phy_read(struct dsa_switch *ds, u32 port_num, + u32 reg_addr) +{ + struct an8855_priv *priv = ds->priv; + + return priv->info->phy_read(ds, port_num, reg_addr); +} + +static void +an8855_phy_setting(struct dsa_switch *ds) +{ + struct an8855_priv *priv = ds->priv; + int i; + u32 val; + + /* Release power down */ + an8855_write(priv, RG_GPHY_AFE_PWD, 0x0); + for (i = 0; i < AN8855_NUM_PHYS; i++) { + /* Enable HW auto downshift */ + an8855_switch_phy_write(ds, i, 0x1f, 0x1); + val = an8855_switch_phy_read(ds, i, PHY_EXT_REG_14); + val |= PHY_EN_DOWN_SHFIT; + an8855_switch_phy_write(ds, i, PHY_EXT_REG_14, val); + an8855_switch_phy_write(ds, i, 0x1f, 0x0); + + /* Enable Asymmetric Pause Capability */ + val = an8855_switch_phy_read(ds, i, MII_ADVERTISE); + val |= ADVERTISE_PAUSE_ASYM; + an8855_switch_phy_write(ds, i, MII_ADVERTISE, val); + } +} + +static void +an8855_low_power_setting(struct dsa_switch *ds) +{ + int port, addr; + + for (port = 0; port < AN8855_NUM_PHYS; port++) { + an8855_phy_write_dev_reg(ds, port, 0x1e, 0x11, 0x0f00); + an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3c, 0x0000); + an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3d, 0x0000); + an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3e, 0x0000); + an8855_phy_write_dev_reg(ds, port, 0x1e, 0xc6, 0x53aa); + } + + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x268, 0x07f1); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x269, 0x2111); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26a, 0x0000); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26b, 0x0074); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26e, 0x00f6); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26f, 0x6666); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x271, 0x2c02); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x272, 0x0c22); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x700, 0x0001); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x701, 0x0803); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x702, 0x01b6); + an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x703, 0x2111); + + an8855_phy_write_dev_reg(ds, 1, 0x1f, 0x700, 0x0001); + + for (addr = 0x200; addr <= 0x230; addr += 2) + an8855_phy_write_dev_reg(ds, 0, 0x1f, addr, 0x2020); + + for (addr = 0x201; addr <= 0x231; addr += 2) + an8855_phy_write_dev_reg(ds, 0, 0x1f, addr, 0x0020); +} + +static void +an8855_eee_setting(struct dsa_switch *ds, u32 port) +{ + /* Disable EEE */ + an8855_phy_write_dev_reg(ds, port, PHY_DEV07, PHY_DEV07_REG_03C, 0); +} + +int +an8855_phy_setup(struct dsa_switch *ds) +{ + int ret = 0; + int i; + + an8855_phy_setting(ds); + + for (i = 0; i < AN8855_NUM_PHYS; i++) + an8855_eee_setting(ds, i); + + return ret; +} diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.h new file mode 100644 index 000000000..63a03bbcd --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.h @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Common part for Airoha AN8855 gigabit switch + * + * Copyright (C) 2023 Airoha Inc. All Rights Reserved. + * + * Author: Min Yao + */ + +#ifndef _AN8855_PHY_H_ +#define _AN8855_PHY_H_ + +#include + +/*phy calibration use*/ +#define DEV_1E 0x1E +/*global device 0x1f, always set P0*/ +#define DEV_1F 0x1F + +/************IEXT/REXT CAL***************/ +/* bits range: for example BITS(16,23) = 0xFF0000*/ +#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n))) +#define ANACAL_INIT 0x01 +#define ANACAL_ERROR 0xFD +#define ANACAL_SATURATION 0xFE +#define ANACAL_FINISH 0xFF +#define ANACAL_PAIR_A 0 +#define ANACAL_PAIR_B 1 +#define ANACAL_PAIR_C 2 +#define ANACAL_PAIR_D 3 +#define DAC_IN_0V 0x00 +#define DAC_IN_2V 0xf0 +#define TX_AMP_OFFSET_0MV 0x20 +#define TX_AMP_OFFSET_VALID_BITS 6 + +#define R0 0 +#define PHY0 0 +#define PHY1 1 +#define PHY2 2 +#define PHY3 3 +#define PHY4 4 +#define ANA_TEST_MODE BITS(8, 15) +#define TST_TCLK_SEL BITs(6, 7) +#define ANA_TEST_VGA_RG 0x100 + +#define FORCE_MDI_CROSS_OVER BITS(3, 4) +#define T10_TEST_CTL_RG 0x145 +#define RG_185 0x185 +#define RG_TX_SLEW BIT(0) +#define ANA_CAL_0 0xdb +#define RG_CAL_CKINV BIT(12) +#define RG_ANA_CALEN BIT(8) +#define RG_REXT_CALEN BIT(4) +#define RG_ZCALEN_A BIT(0) +#define ANA_CAL_1 0xdc +#define RG_ZCALEN_B BIT(12) +#define RG_ZCALEN_C BIT(8) +#define RG_ZCALEN_D BIT(4) +#define RG_TXVOS_CALEN BIT(0) +#define ANA_CAL_6 0xe1 +#define RG_CAL_REFSEL BIT(4) +#define RG_CAL_COMP_PWD BIT(0) +#define ANA_CAL_5 0xe0 +#define RG_REXT_TRIM BITs(8, 13) +#define RG_ZCAL_CTRL BITs(0, 5) +#define RG_17A 0x17a +#define AD_CAL_COMP_OUT BIT(8) +#define RG_17B 0x17b +#define AD_CAL_CLK bit(0) +#define RG_17C 0x17c +#define DA_CALIN_FLAG bit(0) +/************R50 CAL****************************/ +#define RG_174 0x174 +#define RG_R50OHM_RSEL_TX_A_EN BIT[15] +#define CR_R50OHM_RSEL_TX_A BITS[8:14] +#define RG_R50OHM_RSEL_TX_B_EN BIT[7] +#define CR_R50OHM_RSEL_TX_B BITS[6:0] +#define RG_175 0x175 +#define RG_R50OHM_RSEL_TX_C_EN BITS[15] +#define CR_R50OHM_RSEL_TX_C BITS[8:14] +#define RG_R50OHM_RSEL_TX_D_EN BIT[7] +#define CR_R50OHM_RSEL_TX_D BITS[0:6] +/**********TX offset Calibration***************************/ +#define RG_95 0x96 +#define BYPASS_TX_OFFSET_CAL BIT(15) +#define RG_3E 0x3e +#define BYPASS_PD_TXVLD_A BIT(15) +#define BYPASS_PD_TXVLD_B BIT(14) +#define BYPASS_PD_TXVLD_C BIT(13) +#define BYPASS_PD_TXVLD_D BIT(12) +#define BYPASS_PD_TX_10M BIT(11) +#define POWER_DOWN_TXVLD_A BIT(7) +#define POWER_DOWN_TXVLD_B BIT(6) +#define POWER_DOWN_TXVLD_C BIT(5) +#define POWER_DOWN_TXVLD_D BIT(4) +#define POWER_DOWN_TX_10M BIT(3) +#define RG_DD 0xdd +#define RG_TXG_CALEN_A BIT(12) +#define RG_TXG_CALEN_B BIT(8) +#define RG_TXG_CALEN_C BIT(4) +#define RG_TXG_CALEN_D BIT(0) +#define RG_17D 0x17D +#define FORCE_DASN_DAC_IN0_A BIT(15) +#define DASN_DAC_IN0_A BITS(0, 9) +#define RG_17E 0x17E +#define FORCE_DASN_DAC_IN0_B BIT(15) +#define DASN_DAC_IN0_B BITS(0, 9) +#define RG_17F 0x17F + +#define FORCE_DASN_DAC_IN0_C BIT(15) +#define DASN_DAC_IN0_C BITS(0, 9) +#define RG_180 0x180 +#define FORCE_DASN_DAC_IN0_D BIT(15) +#define DASN_DAC_IN0_D BITS(0, 9) + +#define RG_181 0x181 +#define FORCE_DASN_DAC_IN1_A BIT(15) +#define DASN_DAC_IN1_A BITS(0, 9) +#define RG_182 0x182 +#define FORCE_DASN_DAC_IN1_B BIT(15) +#define DASN_DAC_IN1_B BITS(0, 9) +#define RG_183 0x183 +#define FORCE_DASN_DAC_IN1_C BIT(15) +#define DASN_DAC_IN1_C BITS(0, 9) +#define RG_184 0x184 +#define FORCE_DASN_DAC_IN1_D BIT(15) +#define DASN_DAC_IN1_D BITS(0, 9) +#define RG_172 0x172 +#define CR_TX_AMP_OFFSET_A BITS(8, 13) +#define CR_TX_AMP_OFFSET_B BITS(0, 5) +#define RG_173 0x173 +#define CR_TX_AMP_OFFSET_C BITS(8, 13) +#define CR_TX_AMP_OFFSET_D BITS(0, 5) +/**********TX Amp Calibration ***************************/ +#define RG_12 0x12 +#define DA_TX_I2MPB_A_GBE BITS(10, 15) +#define RG_17 0x17 +#define DA_TX_I2MPB_B_GBE BITS(8, 13) +#define RG_19 0x19 +#define DA_TX_I2MPB_C_GBE BITS(8, 13) +#define RG_21 0x21 +#define DA_TX_I2MPB_D_GBE BITS(8, 13) +#define TX_AMP_MAX 0x3f +#define TX_AMP_MAX_OFFSET 0xb +#define TX_AMP_HIGHEST_TS ((TX_AMP_MAX) + 3) +#define TX_AMP_LOWEST_TS (0 - 3) +#define TX_AMP_HIGH_TS (TX_AMP_MAX) +#define TX_AMP_LOW_TS 0 + +/* PHY Extend Register 0x14 bitmap of define */ +#define PHY_EXT_REG_14 0x14 + +/* Fields of PHY_EXT_REG_14 */ +#define PHY_EN_DOWN_SHFIT BIT(4) + +/* PHY Extend Register 0x17 bitmap of define */ +#define PHY_EXT_REG_17 0x17 + +/* Fields of PHY_EXT_REG_17 */ +#define PHY_LINKDOWN_POWER_SAVING_EN BIT(4) + +/* PHY PMA Register 0x17 bitmap of define */ +#define SLV_DSP_READY_TIME_S 15 +#define SLV_DSP_READY_TIME_M (0xff << SLV_DSP_READY_TIME_S) + +/* PHY PMA Register 0x18 bitmap of define */ +#define ENABLE_RANDOM_UPDATE_TRIGGER BIT(8) + +/* PHY EEE Register bitmap of define */ +#define PHY_DEV07 0x07 +#define PHY_DEV07_REG_03C 0x3c + +/* PHY DEV 0x1e Register bitmap of define */ +#define PHY_DEV1E 0x1e +#define PHY_DEV1F 0x1f + +/* Proprietory Control Register of Internal Phy device 0x1e */ +#define PHY_TX_MLT3_BASE 0x0 +#define PHY_DEV1E_REG_13 0x13 +#define PHY_DEV1E_REG_14 0x14 +#define PHY_DEV1E_REG_41 0x41 +#define PHY_DEV1E_REG_A6 0xa6 +#define RXADC_CONTROL_3 0xc2 +#define PHY_DEV1E_REG_0C6 0xc6 +#define RXADC_LDO_CONTROL_2 0xd3 +#define PHY_DEV1E_REG_0FE 0xfe +#define PHY_DEV1E_REG_123 0x123 +#define PHY_DEV1E_REG_189 0x189 +#define PHY_DEV1E_REG_234 0x234 + +/* Proprietory Control Register of Internal Phy device 0x1f */ +#define PHY_DEV1F_REG_44 0x44 +#define PHY_DEV1F_REG_268 0x268 +#define PHY_DEV1F_REG_269 0x269 +#define PHY_DEV1F_REG_26A 0x26A +#define TXVLD_DA_271 0x271 +#define TXVLD_DA_272 0x272 +#define TXVLD_DA_273 0x273 + +/* Fields of PHY_DEV1E_REG_0C6 */ +#define PHY_POWER_SAVING_S 8 +#define PHY_POWER_SAVING_M 0x300 +#define PHY_POWER_SAVING_TX 0x0 + +/* Fields of PHY_DEV1E_REG_189 */ +#define DESCRAMBLER_CLEAR_EN 0x1 + +/* Fields of PHY_DEV1E_REG_234 */ +#define TR_OPEN_LOOP_EN BIT(0) + +/* Internal GPHY Page Control Register */ +#define PHY_CL22_PAGE_CTRL 0x1f +#define PHY_TR_PAGE 0x52b5 + +/* Internal GPHY Token Ring Access Registers */ +#define PHY_TR_CTRL 0x10 +#define PHY_TR_LOW_DATA 0x11 +#define PHY_TR_HIGH_DATA 0x12 + +/* Fields of PHY_TR_CTRL */ +#define PHY_TR_PKT_XMT_STA BIT(15) +#define PHY_TR_WR_S 13 +#define PHY_TR_CH_ADDR_S 11 +#define PHY_TR_NODE_ADDR_S 7 +#define PHY_TR_DATA_ADDR_S 1 + +enum phy_tr_wr { + PHY_TR_WRITE = 0, + PHY_TR_READ = 1, +}; + +/* Helper macro for GPHY Token Ring Access */ +#define PHY_TR_LOW_VAL(x) ((x) & 0xffff) +#define PHY_TR_HIGH_VAL(x) (((x) & 0xff0000) >> 16) + +/* Token Ring Channels */ +#define PMA_CH 0x1 +#define DSP_CH 0x2 + +/* Token Ring Nodes */ +#define PMA_NOD 0xf +#define DSP_NOD 0xd + +/* Token Ring register range */ +enum tr_pma_reg_addr { + PMA_MIN = 0x0, + PMA_01 = 0x1, + PMA_17 = 0x17, + PMA_18 = 0x18, + PMA_MAX = 0x3d, +}; + +enum tr_dsp_reg_addr { + DSP_MIN = 0x0, + DSP_06 = 0x6, + DSP_08 = 0x8, + DSP_0f = 0xf, + DSP_10 = 0x10, + DSP_MAX = 0x3e, +}; +#endif /* _AN8855_REGS_H_ */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c index f9029894d..d8b2922cd 100755 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c @@ -885,9 +885,11 @@ int tx_ring_read(struct seq_file *seq, void *v) int i = 0; seq_printf(seq, "free count = %d\n", (int)atomic_read(&ring->free_count)); - seq_printf(seq, "cpu next free: %d\n", (int)(ring->next_free - ring->dma)); - seq_printf(seq, "cpu last free: %d\n", (int)(ring->last_free - ring->dma)); - for (i = 0; i < MTK_DMA_SIZE; i++) { + seq_printf(seq, "cpu next free: %d\n", + (int)(ring->next_free - ring->dma) / eth->soc->txrx.txd_size); + seq_printf(seq, "cpu last free: %d\n", + (int)(ring->last_free - ring->dma) / eth->soc->txrx.txd_size); + for (i = 0; i < eth->soc->txrx.tx_dma_size; i++) { dma_addr_t tmp = ring->phys + i * (dma_addr_t)eth->soc->txrx.txd_size; @@ -929,7 +931,7 @@ int hwtx_ring_read(struct seq_file *seq, void *v) struct mtk_tx_dma_v2 *hwtx_ring; int i = 0; - for (i = 0; i < MTK_DMA_SIZE; i++) { + for (i = 0; i < eth->soc->txrx.fq_dma_size; i++) { dma_addr_t addr = eth->phy_scratch_ring + i * (dma_addr_t)eth->soc->txrx.txd_size; @@ -978,7 +980,7 @@ int rx_ring_read(struct seq_file *seq, void *v) continue; seq_printf(seq, "[Ring%d] next to read: %d\n", j, - NEXT_DESP_IDX(ring->calc_idx, MTK_DMA_SIZE)); + NEXT_DESP_IDX(ring->calc_idx, eth->soc->txrx.rx_dma_size)); for (i = 0; i < ring->dma_size; i++) { rx_ring = ring->dma + i * eth->soc->txrx.rxd_size; @@ -1155,7 +1157,16 @@ int dbg_regs_read(struct seq_file *seq, void *v) seq_printf(seq, "| MAC_P3_FSM : %08x |\n", mtk_r32(eth, MTK_MAC_FSM(2))); } - + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { + seq_printf(seq, "| XMAC_P1_MCR : %08x |\n", + mtk_r32(eth, MTK_XMAC_MCR(1))); + seq_printf(seq, "| XMAC_P2_MCR : %08x |\n", + mtk_r32(eth, MTK_XMAC_MCR(2))); + seq_printf(seq, "| XMAC_P1_STS : %08x |\n", + mtk_r32(eth, MTK_XGMAC_STS(1))); + seq_printf(seq, "| XMAC_P2_STS : %08x |\n", + mtk_r32(eth, MTK_XGMAC_STS(2))); + } if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) || MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { seq_printf(seq, "| FE_CDM1_FSM : %08x |\n", diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c index 8f947a300..5a219e198 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c @@ -194,6 +194,27 @@ static void mtk_dump_reg(void *_eth, char *name, u32 offset, u32 range) } } +static void mtk_dump_regmap(struct regmap *pmap, char *name, + u32 offset, u32 range) +{ + unsigned int cur = offset; + unsigned int val1 = 0, val2 = 0, val3 = 0, val4 = 0; + + if (!pmap) + return; + + pr_info("\n============ %s ============\n", name); + while (cur < offset + range) { + regmap_read(pmap, cur, &val1); + regmap_read(pmap, cur + 0x4, &val2); + regmap_read(pmap, cur + 0x8, &val3); + regmap_read(pmap, cur + 0xc, &val4); + pr_info("0x%x: %08x %08x %08x %08x\n", + cur, val1, val2, val3, val4); + cur += 0x10; + } +} + void mtk_dump_netsys_info(void *_eth) { struct mtk_eth *eth = _eth; @@ -211,13 +232,17 @@ void mtk_dump_netsys_info(void *_eth) mtk_dump_reg(eth, "WDMA", WDMA_BASE(0), 0x600); mtk_dump_reg(eth, "PPE", 0x2200, 0x200); mtk_dump_reg(eth, "GMAC", 0x10000, 0x300); + mtk_dump_regmap(eth->sgmii->pcs[0].regmap, + "SGMII0", 0, 0x1a0); + mtk_dump_regmap(eth->sgmii->pcs[1].regmap, + "SGMII1", 0, 0x1a0); if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { mtk_dump_reg(eth, "XGMAC0", 0x12000, 0x300); mtk_dump_reg(eth, "XGMAC1", 0x13000, 0x300); - mtk_dump_usxgmii(eth->usxgmii->pcs[0].regmap, - "USXGMII0", 0, 0x1000); - mtk_dump_usxgmii(eth->usxgmii->pcs[1].regmap, - "USXGMII1", 0, 0x1000); + mtk_dump_regmap(eth->usxgmii->pcs[0].regmap, + "USXGMII0", 0, 0x1000); + mtk_dump_regmap(eth->usxgmii->pcs[1].regmap, + "USXGMII1", 0, 0x1000); } } diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c index f3e0b0639..9e64a1374 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -816,9 +816,12 @@ static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, /* Enable SGMII */ if (interface == PHY_INTERFACE_MODE_SGMII || - phy_interface_mode_is_8023z(interface)) + phy_interface_mode_is_8023z(interface)) { + spin_lock(ð->syscfg0_lock); regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, SYSCFG0_SGMII_MASK, mac->syscfg0); + spin_unlock(ð->syscfg0_lock); + } return 0; } @@ -967,10 +970,28 @@ static void mtk_gdm_fsm_poll(struct mtk_mac *mac) pr_info("%s fsm invalid", __func__); } -static void mtk_pse_port_link_set(struct mtk_mac *mac, bool up) +static void mtk_pse_port_link_set(struct mtk_mac *mac, bool up, + phy_interface_t interface) { u32 fe_glo_cfg, val = 0; + if (!up && interface == PHY_INTERFACE_MODE_XGMII) { + void __iomem *base; + + base = ioremap(0x0F0CFB00, SZ_4K); + if (base) { + /* wait for internal 2.5G PHY to turn off */ + usleep_range(100, 1000); + /* enable the XGMAC clock for 10 msecs to + * flush the packets. + */ + writel(readl(base) | BIT(9), base); + usleep_range(10000, 11000); + writel(readl(base) & ~BIT(9), base); + iounmap(base); + } + } + fe_glo_cfg = mtk_r32(mac->hw, MTK_FE_GLO_CFG(mac->id)); switch (mac->id) { case MTK_GMAC1_ID: @@ -1002,7 +1023,7 @@ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, unsigned int id; u32 mcr, sts; - mtk_pse_port_link_set(mac, false); + mtk_pse_port_link_set(mac, false, interface); if (mac->type == MTK_GDM_TYPE) { mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK); @@ -1140,6 +1161,8 @@ static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode, if (duplex == DUPLEX_FULL || interface == PHY_INTERFACE_MODE_SGMII) mcr |= MAC_MCR_FORCE_DPX; + else if (interface == PHY_INTERFACE_MODE_GMII) + mcr |= MAC_MCR_PRMBL_LMT_EN; /* Configure pause modes - * phylink will avoid these for half duplex @@ -1184,7 +1207,7 @@ static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode, mcr &= ~(XMAC_MCR_TRX_DISABLE); mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id)); } - mtk_pse_port_link_set(mac, true); + mtk_pse_port_link_set(mac, true, interface); } static void mtk_validate(struct phylink_config *config, @@ -1700,10 +1723,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) { const struct mtk_soc_data *soc = eth->soc; dma_addr_t phy_ring_tail; - int cnt = MTK_DMA_SIZE; + int cnt = soc->txrx.fq_dma_size; dma_addr_t dma_addr; u64 addr64 = 0; - int i; + int i, j, len; if (!eth->soc->has_sram) { eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, @@ -1717,40 +1740,44 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) if (unlikely(!eth->scratch_ring)) return -ENOMEM; - eth->scratch_head = kcalloc(cnt, MTK_QDMA_PAGE_SIZE, GFP_KERNEL); - if (unlikely(!eth->scratch_head)) - return -ENOMEM; - - dma_addr = dma_map_single(eth->dma_dev, - eth->scratch_head, cnt * MTK_QDMA_PAGE_SIZE, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) - return -ENOMEM; - phy_ring_tail = eth->phy_scratch_ring + (dma_addr_t)soc->txrx.txd_size * (cnt - 1); - for (i = 0; i < cnt; i++) { - struct mtk_tx_dma_v2 *txd; + for (j = 0; j < DIV_ROUND_UP(soc->txrx.fq_dma_size, MTK_FQ_DMA_LENGTH); j++) { + len = min_t(int, cnt - j * MTK_FQ_DMA_LENGTH, MTK_FQ_DMA_LENGTH); - txd = eth->scratch_ring + i * soc->txrx.txd_size; - txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; - if (i < cnt - 1) - txd->txd2 = eth->phy_scratch_ring + - (i + 1) * soc->txrx.txd_size; + eth->scratch_head[j] = kcalloc(len, MTK_QDMA_PAGE_SIZE, GFP_KERNEL); + if (unlikely(!eth->scratch_head[j])) + return -ENOMEM; - addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ? - TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0; + dma_addr = dma_map_single(eth->dma_dev, + eth->scratch_head[j], len * MTK_QDMA_PAGE_SIZE, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; - txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64; - txd->txd4 = 0; + for (i = 0; i < len; i++) { + struct mtk_tx_dma_v2 *txd; - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) || - MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { - txd->txd5 = 0; - txd->txd6 = 0; - txd->txd7 = 0; - txd->txd8 = 0; + txd = eth->scratch_ring + (j * MTK_FQ_DMA_LENGTH + i) * soc->txrx.txd_size; + txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; + if (j * MTK_FQ_DMA_LENGTH + i < cnt) + txd->txd2 = eth->phy_scratch_ring + + (j * MTK_FQ_DMA_LENGTH + i + 1) * soc->txrx.txd_size; + + addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ? + TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0; + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64; + txd->txd4 = 0; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) || + MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { + txd->txd5 = 0; + txd->txd6 = 0; + txd->txd7 = 0; + txd->txd8 = 0; + } } } @@ -2779,25 +2806,25 @@ static int mtk_tx_alloc(struct mtk_eth *eth) int i, sz = soc->txrx.txd_size; struct mtk_tx_dma_v2 *txd, *pdma_txd; - ring->buf = kcalloc(MTK_DMA_SIZE, sizeof(*ring->buf), + ring->buf = kcalloc(soc->txrx.tx_dma_size, sizeof(*ring->buf), GFP_KERNEL); if (!ring->buf) goto no_tx_mem; if (!eth->soc->has_sram) - ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, + ring->dma = dma_alloc_coherent(eth->dma_dev, soc->txrx.tx_dma_size * sz, &ring->phys, GFP_KERNEL); else { - ring->dma = eth->sram_base + MTK_DMA_SIZE * sz; + ring->dma = eth->sram_base + soc->txrx.fq_dma_size * sz; ring->phys = eth->phy_scratch_ring + - MTK_DMA_SIZE * (dma_addr_t)sz; + soc->txrx.fq_dma_size * (dma_addr_t)sz; } if (!ring->dma) goto no_tx_mem; - for (i = 0; i < MTK_DMA_SIZE; i++) { - int next = (i + 1) % MTK_DMA_SIZE; + for (i = 0; i < soc->txrx.tx_dma_size; i++) { + int next = (i + 1) % soc->txrx.tx_dma_size; u32 next_ptr = ring->phys + next * sz; txd = ring->dma + i * sz; @@ -2820,12 +2847,12 @@ static int mtk_tx_alloc(struct mtk_eth *eth) */ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, - MTK_DMA_SIZE * sz, + soc->txrx.tx_dma_size * sz, &ring->phys_pdma, GFP_KERNEL); if (!ring->dma_pdma) goto no_tx_mem; - for (i = 0; i < MTK_DMA_SIZE; i++) { + for (i = 0; i < soc->txrx.tx_dma_size; i++) { pdma_txd = ring->dma_pdma + i * sz; pdma_txd->txd2 = TX_DMA_DESP2_DEF; @@ -2840,11 +2867,11 @@ static int mtk_tx_alloc(struct mtk_eth *eth) } } - ring->dma_size = MTK_DMA_SIZE; - atomic_set(&ring->free_count, MTK_DMA_SIZE - 2); + ring->dma_size = soc->txrx.tx_dma_size; + atomic_set(&ring->free_count, soc->txrx.tx_dma_size - 2); ring->next_free = ring->dma; ring->last_free = (void *)txd; - ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz)); + ring->last_free_ptr = (u32)(ring->phys + ((soc->txrx.tx_dma_size - 1) * sz)); ring->thresh = MAX_SKB_FRAGS; ring->cpu_idx = 0; @@ -2857,14 +2884,14 @@ static int mtk_tx_alloc(struct mtk_eth *eth) mtk_w32(eth, ring->phys, soc->reg_map->qdma.ctx_ptr); mtk_w32(eth, ring->phys, soc->reg_map->qdma.dtx_ptr); mtk_w32(eth, - ring->phys + ((MTK_DMA_SIZE - 1) * sz), + ring->phys + ((soc->txrx.tx_dma_size - 1) * sz), soc->reg_map->qdma.crx_ptr); mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES, soc->reg_map->qdma.qtx_cfg); } else { mtk_w32(eth, ring->phys_pdma, soc->reg_map->pdma.tx_ptr); - mtk_w32(eth, MTK_DMA_SIZE, soc->reg_map->pdma.tx_cnt_cfg); + mtk_w32(eth, soc->txrx.tx_dma_size, soc->reg_map->pdma.tx_cnt_cfg); mtk_w32(eth, ring->cpu_idx, soc->reg_map->pdma.pctx_ptr); mtk_w32(eth, MTK_PST_DTX_IDX_CFG(0), soc->reg_map->pdma.rst_idx); } @@ -2882,7 +2909,7 @@ static void mtk_tx_clean(struct mtk_eth *eth) int i; if (ring->buf) { - for (i = 0; i < MTK_DMA_SIZE; i++) + for (i = 0; i < soc->txrx.tx_dma_size; i++) mtk_tx_unmap(eth, &ring->buf[i], false); kfree(ring->buf); ring->buf = NULL; @@ -2890,14 +2917,14 @@ static void mtk_tx_clean(struct mtk_eth *eth) if (!eth->soc->has_sram && ring->dma) { dma_free_coherent(eth->dma_dev, - MTK_DMA_SIZE * soc->txrx.txd_size, + soc->txrx.tx_dma_size * soc->txrx.txd_size, ring->dma, ring->phys); ring->dma = NULL; } if (ring->dma_pdma) { dma_free_coherent(eth->dma_dev, - MTK_DMA_SIZE * soc->txrx.txd_size, + soc->txrx.tx_dma_size * soc->txrx.txd_size, ring->dma_pdma, ring->phys_pdma); ring->dma_pdma = NULL; } @@ -2906,6 +2933,7 @@ static void mtk_tx_clean(struct mtk_eth *eth) static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) { const struct mtk_reg_map *reg_map = eth->soc->reg_map; + const struct mtk_soc_data *soc = eth->soc; struct mtk_rx_ring *ring; int rx_data_len, rx_dma_size; int i; @@ -2924,7 +2952,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) rx_dma_size = MTK_HW_LRO_DMA_SIZE; } else { rx_data_len = ETH_DATA_LEN; - rx_dma_size = MTK_DMA_SIZE; + rx_dma_size = soc->txrx.rx_dma_size; } ring->frag_size = mtk_max_frag_size(rx_data_len); @@ -2950,10 +2978,12 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) &ring->phys, GFP_KERNEL); else { struct mtk_tx_ring *tx_ring = ð->tx_ring; - ring->dma = tx_ring->dma + MTK_DMA_SIZE * - eth->soc->txrx.txd_size * (ring_no + 1); - ring->phys = tx_ring->phys + MTK_DMA_SIZE * - eth->soc->txrx.txd_size * (ring_no + 1); + ring->dma = tx_ring->dma + + soc->txrx.tx_dma_size * (dma_addr_t)eth->soc->txrx.txd_size + + soc->txrx.rx_dma_size * (dma_addr_t)eth->soc->txrx.rxd_size * ring_no; + ring->phys = tx_ring->phys + + soc->txrx.tx_dma_size * (dma_addr_t)eth->soc->txrx.txd_size + + soc->txrx.rx_dma_size * (dma_addr_t)eth->soc->txrx.rxd_size * ring_no; } if (!ring->dma) @@ -3682,7 +3712,7 @@ static void mtk_dma_free(struct mtk_eth *eth) netdev_reset_queue(eth->netdev[i]); if ( !eth->soc->has_sram && eth->scratch_ring) { dma_free_coherent(eth->dma_dev, - MTK_DMA_SIZE * soc->txrx.txd_size, + soc->txrx.fq_dma_size * soc->txrx.txd_size, eth->scratch_ring, eth->phy_scratch_ring); eth->scratch_ring = NULL; eth->phy_scratch_ring = 0; @@ -3705,9 +3735,9 @@ static void mtk_dma_free(struct mtk_eth *eth) mtk_rx_clean(eth, ð->rx_ring[MTK_RSS_RING(i)], 1); } - if (eth->scratch_head) { - kfree(eth->scratch_head); - eth->scratch_head = NULL; + for (i = 0; i < DIV_ROUND_UP(soc->txrx.fq_dma_size, MTK_FQ_DMA_LENGTH); i++) { + kfree(eth->scratch_head[i]); + eth->scratch_head[i] = NULL; } } @@ -3838,8 +3868,16 @@ static int mtk_start_dma(struct mtk_eth *eth) if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { val = mtk_r32(eth, reg_map->qdma.glo_cfg); - if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) || - MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { + val &= ~(MTK_RESV_BUF_MASK | MTK_DMA_SIZE_MASK); + mtk_w32(eth, + val | MTK_TX_DMA_EN | MTK_RX_DMA_EN | + MTK_DMA_SIZE_16DWORDS | MTK_TX_WB_DDONE | + MTK_NDP_CO_PRO | MTK_MUTLI_CNT | + MTK_RESV_BUF | MTK_WCOMP_EN | + MTK_DMAD_WR_WDONE | MTK_CHK_DDONE_EN | + MTK_RX_2B_OFFSET, reg_map->qdma.glo_cfg); + } else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { val &= ~MTK_RESV_BUF_MASK; mtk_w32(eth, val | MTK_TX_DMA_EN | MTK_RX_DMA_EN | @@ -3848,8 +3886,7 @@ static int mtk_start_dma(struct mtk_eth *eth) MTK_RESV_BUF | MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | MTK_CHK_DDONE_EN | MTK_RX_2B_OFFSET, reg_map->qdma.glo_cfg); - } - else + } else mtk_w32(eth, val | MTK_TX_DMA_EN | MTK_DMA_SIZE_32DWORDS | MTK_NDP_CO_PRO | @@ -3958,9 +3995,6 @@ set_speed: if (s.base.speed == 0 || s.base.speed == ((__u32)-1)) return NOTIFY_DONE; - if (queue >= MTK_QDMA_TX_NUM) - return NOTIFY_DONE; - if (mac->speed > 0 && mac->speed < s.base.speed) s.base.speed = 0; @@ -4383,6 +4417,7 @@ static int mtk_hw_init(struct mtk_eth *eth, u32 type) mtk_w32(eth, 0x00600009, PSE_IQ_REV(8)); /* GDM and CDM Threshold */ + mtk_w32(eth, 0x00000004, MTK_CDM2_THRES); mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES); mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES); @@ -5439,6 +5474,8 @@ static int mtk_probe(struct platform_device *pdev) return -ENOMEM; eth->soc = of_device_get_match_data(&pdev->dev); + if (!eth->soc) + return -EINVAL; eth->dev = &pdev->dev; eth->dma_dev = &pdev->dev; @@ -5812,6 +5849,9 @@ static const struct mtk_soc_data mt2701_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), + .tx_dma_size = MTK_DMA_SIZE(2K), + .rx_dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), .rx_dma_l4_valid = RX_DMA_L4_VALID, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -5829,6 +5869,9 @@ static const struct mtk_soc_data mt7621_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rx_dma_l4_valid = RX_DMA_L4_VALID, + .tx_dma_size = MTK_DMA_SIZE(2K), + .rx_dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), .rxd_size = sizeof(struct mtk_rx_dma), .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -5847,6 +5890,9 @@ static const struct mtk_soc_data mt7622_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), + .tx_dma_size = MTK_DMA_SIZE(2K), + .rx_dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), .rx_dma_l4_valid = RX_DMA_L4_VALID, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -5864,6 +5910,9 @@ static const struct mtk_soc_data mt7623_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), + .tx_dma_size = MTK_DMA_SIZE(2K), + .rx_dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), .rx_dma_l4_valid = RX_DMA_L4_VALID, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -5882,6 +5931,9 @@ static const struct mtk_soc_data mt7629_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), + .tx_dma_size = MTK_DMA_SIZE(2K), + .rx_dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), .rx_dma_l4_valid = RX_DMA_L4_VALID, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -5900,6 +5952,9 @@ static const struct mtk_soc_data mt7986_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), .rxd_size = sizeof(struct mtk_rx_dma), + .tx_dma_size = MTK_DMA_SIZE(4K), + .rx_dma_size = MTK_DMA_SIZE(1K), + .fq_dma_size = MTK_DMA_SIZE(2K), .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2, @@ -5918,6 +5973,9 @@ static const struct mtk_soc_data mt7981_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), .rxd_size = sizeof(struct mtk_rx_dma), + .tx_dma_size = MTK_DMA_SIZE(4K), + .rx_dma_size = MTK_DMA_SIZE(1K), + .fq_dma_size = MTK_DMA_SIZE(2K), .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2, @@ -5936,6 +5994,9 @@ static const struct mtk_soc_data mt7988_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), .rxd_size = sizeof(struct mtk_rx_dma_v2), + .tx_dma_size = MTK_DMA_SIZE(4K), + .rx_dma_size = MTK_DMA_SIZE(1K), + .fq_dma_size = MTK_DMA_SIZE(4K), .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2, @@ -5953,6 +6014,9 @@ static const struct mtk_soc_data rt5350_data = { .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), + .tx_dma_size = MTK_DMA_SIZE(2K), + .rx_dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 23d384fbd..d2452bea5 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -19,7 +19,9 @@ #define MTK_QDMA_PAGE_SIZE 2048 #define MTK_MAX_RX_LENGTH 1536 #define MTK_MIN_TX_LENGTH 60 -#define MTK_DMA_SIZE 2048 +#define MTK_DMA_SIZE(x) (SZ_##x) +#define MTK_FQ_DMA_HEAD 32 +#define MTK_FQ_DMA_LENGTH 2048 #define MTK_NAPI_WEIGHT 256 #if defined(CONFIG_MEDIATEK_NETSYS_V3) @@ -175,6 +177,7 @@ /* GDM and CDM Threshold */ #define MTK_GDM2_THRES 0x1530 +#define MTK_CDM2_THRES 0x1534 #define MTK_CDMW0_THRES 0x164c #define MTK_CDMW1_THRES 0x1650 #define MTK_CDME0_THRES 0x1654 @@ -453,6 +456,7 @@ #define MTK_RX_BT_32DWORDS (3 << 11) #define MTK_NDP_CO_PRO BIT(10) #define MTK_TX_WB_DDONE BIT(6) +#define MTK_DMA_SIZE_MASK GENMASK(5, 4) #define MTK_DMA_SIZE_16DWORDS (2 << 4) #define MTK_DMA_SIZE_32DWORDS (3 << 4) #define MTK_RX_DMA_BUSY BIT(3) @@ -745,6 +749,7 @@ #define MAC_MCR_FORCE_MODE BIT(15) #define MAC_MCR_TX_EN BIT(14) #define MAC_MCR_RX_EN BIT(13) +#define MAC_MCR_PRMBL_LMT_EN BIT(10) #define MAC_MCR_BACKOFF_EN BIT(9) #define MAC_MCR_BACKPR_EN BIT(8) #define MAC_MCR_FORCE_EEE1000 BIT(7) @@ -1718,6 +1723,9 @@ struct mtk_soc_data { struct { u32 txd_size; u32 rxd_size; + u32 tx_dma_size; + u32 rx_dma_size; + u32 fq_dma_size; u32 rx_dma_l4_valid; u32 dma_max_len; u32 dma_len_offset; @@ -1900,7 +1908,7 @@ struct mtk_eth { void *scratch_ring; struct mtk_reset_event reset_event; dma_addr_t phy_scratch_ring; - void *scratch_head; + void *scratch_head[MTK_FQ_DMA_HEAD]; struct clk *clks[MTK_CLK_MAX]; struct mii_bus *mii_bus; @@ -1991,7 +1999,6 @@ int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id); struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id); int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r); int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r); -int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range); void mtk_usxgmii_link_poll(struct work_struct *work); void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev); diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h index 111590d65..ead9e1fe2 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h @@ -1092,8 +1092,13 @@ enum FoeIpAct { #define entry_hnat_is_bound(e) (e->bfib1.state == BIND) #define entry_hnat_state(e) (e->bfib1.state) -#define skb_hnat_is_hashed(skb) \ +#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3) +#define skb_hnat_is_hashed(skb) \ + (skb_hnat_entry(skb) != 0x7fff && skb_hnat_entry(skb) < hnat_priv->foe_etry_num) +#else +#define skb_hnat_is_hashed(skb) \ (skb_hnat_entry(skb) != 0x3fff && skb_hnat_entry(skb) < hnat_priv->foe_etry_num) +#endif #define FROM_GE_LAN_GRP(skb) (FROM_GE_LAN(skb) | FROM_GE_LAN2(skb)) #define FROM_GE_LAN(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN) #define FROM_GE_LAN2(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN2) diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c index 34fc0918c..6e1f3dda9 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c @@ -608,6 +608,15 @@ int entry_detail(u32 ppe_id, int index) entry->ipv4_hnapt.tport_id, entry->ipv4_hnapt.tops_entry, entry->ipv4_hnapt.cdrt_id); + pr_info("usr_info = %d, tid = %d, hf = %d, amsdu = %d\n", + entry->ipv4_hnapt.winfo_pao.usr_info, + entry->ipv4_hnapt.winfo_pao.tid, + entry->ipv4_hnapt.winfo_pao.hf, + entry->ipv4_hnapt.winfo_pao.amsdu); + pr_info("is_fixedrate = %d, is_prior = %d, is_sp = %d\n", + entry->ipv4_hnapt.winfo_pao.is_fixedrate, + entry->ipv4_hnapt.winfo_pao.is_prior, + entry->ipv4_hnapt.winfo_pao.is_sp); #endif pr_info("=========================================\n\n"); } else { @@ -638,17 +647,43 @@ int entry_detail(u32 ppe_id, int index) entry->ipv6_hnapt.tport_id, entry->ipv6_hnapt.tops_entry, entry->ipv6_hnapt.cdrt_id); - + pr_info("usr_info = %d, tid = %d, hf = %d, amsdu = %d\n", + entry->ipv6_hnapt.winfo_pao.usr_info, + entry->ipv6_hnapt.winfo_pao.tid, + entry->ipv6_hnapt.winfo_pao.hf, + entry->ipv6_hnapt.winfo_pao.amsdu); + pr_info("is_fixedrate = %d, is_prior = %d, is_sp = %d\n", + entry->ipv6_hnapt.winfo_pao.is_fixedrate, + entry->ipv6_hnapt.winfo_pao.is_prior, + entry->ipv6_hnapt.winfo_pao.is_sp); } else if (IS_IPV4_MAPE(entry) || IS_IPV4_MAPT(entry)) { pr_info("tport_id = %d, tops_entry = %d, cdrt_id = %d\n", entry->ipv4_mape.tport_id, entry->ipv4_mape.tops_entry, entry->ipv4_mape.cdrt_id); + pr_info("usr_info = %d, tid = %d, hf = %d, amsdu = %d\n", + entry->ipv4_mape.winfo_pao.usr_info, + entry->ipv4_mape.winfo_pao.tid, + entry->ipv4_mape.winfo_pao.hf, + entry->ipv4_mape.winfo_pao.amsdu); + pr_info("is_fixedrate = %d, is_prior = %d, is_sp = %d\n", + entry->ipv4_mape.winfo_pao.is_fixedrate, + entry->ipv4_mape.winfo_pao.is_prior, + entry->ipv4_mape.winfo_pao.is_sp); } else { pr_info("tport_id = %d, tops_entry = %d, cdrt_id = %d\n", entry->ipv6_5t_route.tport_id, entry->ipv6_5t_route.tops_entry, entry->ipv6_5t_route.cdrt_id); + pr_info("usr_info = %d, tid = %d, hf = %d, amsdu = %d\n", + entry->ipv6_5t_route.winfo_pao.usr_info, + entry->ipv6_5t_route.winfo_pao.tid, + entry->ipv6_5t_route.winfo_pao.hf, + entry->ipv6_5t_route.winfo_pao.amsdu); + pr_info("is_fixedrate = %d, is_prior = %d, is_sp = %d\n", + entry->ipv6_5t_route.winfo_pao.is_fixedrate, + entry->ipv6_5t_route.winfo_pao.is_prior, + entry->ipv6_5t_route.winfo_pao.is_sp); } #endif pr_info("=========================================\n\n"); @@ -2805,7 +2840,7 @@ static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffe qos_toggle = 1; } else if (buf[0] == '2') { pr_info("Per-port-per-queue mode is going to be enabled!\n"); - pr_info("PPPQ use qid 0~5 (scheduler 0).\n"); + pr_info("PPPQ use qid 0~11 (scheduler 0).\n"); qos_toggle = 2; qos_dl_toggle = 1; qos_ul_toggle = 1; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c index 9fe85fbdb..579ef9a21 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c @@ -832,8 +832,7 @@ static unsigned int mtk_hnat_ipv4_nf_pre_routing(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - struct flow_offload_hw_path hw_path = { .dev = skb->dev, - .virt_dev = skb->dev }; + struct flow_offload_hw_path hw_path; if (!skb) goto drop; @@ -848,6 +847,9 @@ mtk_hnat_ipv4_nf_pre_routing(void *priv, struct sk_buff *skb, hnat_set_head_frags(state, skb, -1, hnat_set_iif); + hw_path.dev = skb->dev; + hw_path.virt_dev = skb->dev; + /* * Avoid mistakenly binding of outer IP, ports in SW L2TP decap flow. * In pre-routing, if dev is virtual iface, TOPS module is not loaded, @@ -1221,6 +1223,7 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb, int udp = 0; u32 qid = 0; u32 port_id = 0; + u32 payload_len = 0; int mape = 0; struct mtk_mac *mac = netdev_priv(dev); @@ -1757,6 +1760,29 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb, else qid = 0; + if (IS_PPPQ_MODE && IS_PPPQ_PATH(dev, skb)) { + if (ntohs(eth->h_proto) == ETH_P_IP) { + iph = ip_hdr(skb); + if (iph->protocol == IPPROTO_TCP) { + skb_set_transport_header(skb, sizeof(struct iphdr)); + payload_len = be16_to_cpu(iph->tot_len) - + skb_transport_offset(skb) - tcp_hdrlen(skb); + /* Dispatch ACK packets to high priority queue */ + if (payload_len == 0) + qid += 6; + } + } else if (ntohs(eth->h_proto) == ETH_P_IPV6) { + ip6h = ipv6_hdr(skb); + if (ip6h->nexthdr == NEXTHDR_TCP) { + skb_set_transport_header(skb, sizeof(struct ipv6hdr)); + payload_len = be16_to_cpu(ip6h->payload_len) - tcp_hdrlen(skb); + /* Dispatch ACK packets to high priority queue */ + if (payload_len == 0) + qid += 6; + } + } + } + if (IS_IPV4_GRP(foe)) { entry.ipv4_hnapt.iblk2.dp = gmac; entry.ipv4_hnapt.iblk2.port_mg = diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c index 54ec897b9..710b1b8b1 100755 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c @@ -227,6 +227,8 @@ void mtk_sgmii_setup_phya_gen1(struct mtk_sgmii_pcs *mpcs) regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0), 0x02002800); ndelay(1020); + regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0), + 0x20000000); /* Setup DA default value */ regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0), 0x00000020); @@ -337,6 +339,8 @@ void mtk_sgmii_setup_phya_gen2(struct mtk_sgmii_pcs *mpcs) regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0), 0x02002800); ndelay(1020); + regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0), + 0x20000000); /* Setup DA default value */ regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0), 0x00000020); @@ -583,7 +587,7 @@ static void mtk_sgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, if (mtk_sgmii_link_status(mpcs)) goto exit; - if (mode == MLO_AN_PHY) + if (mode != MLO_AN_INBAND) mtk_sgmii_pcs_config(&mpcs->pcs, mode, interface, mpcs->advertising, false); } while (time_before(jiffies, t_start + msecs_to_jiffies(3000))); diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c index f11422516..40eb3092b 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c @@ -187,6 +187,8 @@ void mtk_usxgmii_setup_phya_usxgmii(struct mtk_usxgmii_pcs *mpcs) regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0), 0x02002800); ndelay(1020); + regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0), + 0x20000000); /* Setup DA default value */ regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0), 0x00000020); @@ -299,6 +301,8 @@ void mtk_usxgmii_setup_phya_5gbaser(struct mtk_usxgmii_pcs *mpcs) regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0), 0x02002800); ndelay(1020); + regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0), + 0x20000000); /* Setup DA default value */ regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0), 0x00000020); @@ -411,6 +415,8 @@ void mtk_usxgmii_setup_phya_10gbaser(struct mtk_usxgmii_pcs *mpcs) regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0), 0x02002800); ndelay(1020); + regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0), + 0x20000000); /* Setup DA default value */ regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0), 0x00000020); @@ -763,6 +769,7 @@ static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, { struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); unsigned long t_start = jiffies; + unsigned int mpcs_mode; /* Reconfiguring USXGMII to ensure the quality of the RX signal * after the line side link up. @@ -776,7 +783,11 @@ static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, if (mtk_usxgmii_link_status(mpcs)) return; - if (mpcs->mode == MLO_AN_PHY) + spin_lock(&mpcs->regmap_lock); + mpcs_mode = mpcs->mode; + spin_unlock(&mpcs->regmap_lock); + + if (mpcs_mode != MLO_AN_INBAND) mtk_usxgmii_pcs_config(&mpcs->pcs, mode, interface, NULL, false); } while (time_before(jiffies, t_start + msecs_to_jiffies(3000))); @@ -836,23 +847,3 @@ struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id) return &ss->pcs[id].pcs; } - -int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range) -{ - unsigned int cur = offset; - unsigned int val1 = 0, val2 = 0, val3 = 0, val4 = 0; - - pr_info("\n============ %s ============ pmap:%lx\n", - name, (unsigned long)pmap); - while (cur < offset + range) { - regmap_read(pmap, cur, &val1); - regmap_read(pmap, cur + 0x4, &val2); - regmap_read(pmap, cur + 0x8, &val3); - regmap_read(pmap, cur + 0xc, &val4); - pr_info("0x%x: %08x %08x %08x %08x\n", cur, - val1, val2, val3, val4); - cur += 0x10; - } - return 0; -} - diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h.h index 38d4c07fe..2fdbb5808 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h.h +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h.h @@ -46,7 +46,7 @@ #define MII_MMD_ADDR_DATA_REG 0x0e #define MMD_OP_MODE_DATA BIT(14) -#define EN8811H_DRIVER_VERSION "v1.2.4" +#define EN8811H_DRIVER_VERSION "v1.2.5" #define LED_ON_CTRL(i) (0x024 + ((i)*2)) #define LED_ON_EN (1 << 15) @@ -99,6 +99,7 @@ struct en8811h_priv { unsigned int dsp_crc32; char buf[512]; int pol; + int surge; }; struct air_base_t_led_cfg { diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c index a73bcee53..723275dcd 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c @@ -334,6 +334,22 @@ int air_buckpbus_reg_write(struct phy_device *phydev, } return ret; } + +int air_surge_5ohm_config(struct phy_device *phydev) +{ + int ret = 0; + struct device *dev = phydev_dev(phydev); + + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x00b0); + if (ret < 0) + return ret; + dev_info(dev, "surge protection mode - 5R\n"); + return ret; +} + #if defined(CONFIG_OF) int en8811h_of_init(struct phy_device *phydev) { @@ -346,12 +362,12 @@ int en8811h_of_init(struct phy_device *phydev) if (of_find_property(of_node, "airoha,polarity", NULL)) { if (of_property_read_u32(of_node, "airoha,polarity", &val) != 0) { - phydev_err(phydev, "airoha,polarity value is invalid."); + dev_err(dev, "airoha,polarity value is invalid."); return -EINVAL; } if (val < AIR_POL_TX_REV_RX_NOR || val > AIR_POL_TX_NOR_RX_REV) { - phydev_err(phydev, + dev_err(dev, "airoha,polarity value %u out of range.", val); return -EINVAL; @@ -360,6 +376,25 @@ int en8811h_of_init(struct phy_device *phydev) } else priv->pol = AIR_POL_TX_NOR_RX_NOR; + if (of_find_property(of_node, "airoha,surge", NULL)) { + if (of_property_read_u32(of_node, "airoha,surge", + &val) != 0) { + dev_err(dev, "airoha,surge value is invalid."); + return -EINVAL; + } + if (val < 0 || val > 1) { + dev_err(dev, + "airoha,surge value %u out of range.", + val); + return -EINVAL; + } + if (val) + priv->surge = 1; + else + priv->surge = 0; + } else + priv->surge = 0; + return 0; } #else @@ -710,7 +745,7 @@ static int airphy_fcm_counter_show(struct phy_device *phydev, seq_puts(seq, "| Tx to Line side_T :"); pkt_cnt = air_buckpbus_reg_read(phydev, 0xe0088); seq_printf(seq, "%010u |\n", pkt_cnt); - ret = air_buckpbus_reg_write(phydev, 0xe0074, 0xf); + ret = air_buckpbus_reg_write(phydev, 0xe0074, 0x3); if (ret < 0) return ret; return 0; @@ -1169,8 +1204,12 @@ static int airphy_temp_show(struct seq_file *seq, void *v) u32 pbus_value = 0; seq_puts(seq, "<>\n"); - air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1100); - air_mii_cl45_write(phydev, 0x1e, 0x800f, 0xe5); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1100); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0xe5); + if (ret < 0) { + pr_notice("\nmii_cl45_write fail\n"); + return -EIO; + } pbus_value = air_buckpbus_reg_read(phydev, 0x3B38); seq_printf(seq, "| Temperature : %dC |\n", pbus_value); @@ -1285,6 +1324,114 @@ static int airphy_lp_speed_open(struct inode *inode, struct file *file) return single_open(file, airphy_lp_speed, inode->i_private); } +static void airphy_debugfs_mii_cl22_help(void) +{ + pr_notice("\nUsage:\n" + "[debugfs] = /sys/kernel/debug/mdio-bus\':[phy_addr]\n" + "Read:\n" + "echo r [phy_register] > /[debugfs]/mii_mgr_op\n" + "Write:\n" + "echo w [phy_register] [value] > /[debugfs]/mii_mgr_op\n"); +} + + +static ssize_t airphy_debugfs_cl22(struct file *file, + const char __user *buffer, size_t count, + loff_t *data) +{ + struct phy_device *phydev = file->private_data; + struct mii_bus *mbus = phydev_mdio_bus(phydev); + int addr = phydev_addr(phydev); + char buf[64]; + int ret = 0; + unsigned int reg, val; + + memset(buf, 0, 64); + if (count > sizeof(buf) - 1) + return -EINVAL; + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf[0] == 'w') { + if (sscanf(buf, "w %x %x", ®, &val) == -1) + return -EFAULT; + + pr_notice("\nphy=%d, reg=0x%x, val=0x%x\n", + phydev_addr(phydev), reg, val); + ret = air_mii_cl22_write(mbus, addr, reg, val); + if (ret < 0) { + pr_notice("\nmii_cl22_write fail\n"); + return -EIO; + } + val = air_mii_cl22_read(mbus, addr, reg); + pr_notice("\nphy=%d, reg=0x%x, val=0x%x confirm..\n", + phydev_addr(phydev), reg, val); + } else if (buf[0] == 'r') { + if (sscanf(buf, "r %x", ®) == -1) + return -EFAULT; + + val = air_mii_cl22_read(mbus, addr, reg); + pr_notice("\nphy=%d, reg=0x%x, val=0x%x\n", + phydev_addr(phydev), reg, val); + } else + airphy_debugfs_mii_cl22_help(); + + return count; +} + +static void airphy_debugfs_mii_cl45_help(void) +{ + pr_notice("\nUsage:\n" + "[debugfs] = /sys/kernel/debug/mdio-bus\':[phy_addr]\n" + "Read:\n" + "echo r [device number] [phy_register] > /[debugfs]/mii_mgr_cl45_op\n" + "Write:\n" + "echo w [device number] [phy_register] [value] > /[debugfs]/mii_mgr_cl45_op\n"); +} + + +static ssize_t airphy_debugfs_cl45(struct file *file, + const char __user *buffer, size_t count, + loff_t *data) +{ + struct phy_device *phydev = file->private_data; + char buf[64]; + int ret = 0; + unsigned int reg, val, devnum; + + memset(buf, 0, 64); + if (count > sizeof(buf) - 1) + return -EINVAL; + if (copy_from_user(buf, buffer, count)) + return -EFAULT; + + if (buf[0] == 'w') { + if (sscanf(buf, "w %x %x %x", &devnum, ®, &val) == -1) + return -EFAULT; + + pr_notice("\nphy=%d, devnum=0x%x, reg=0x%x, val=0x%x\n", + phydev_addr(phydev), devnum, reg, val); + ret = air_mii_cl45_write(phydev, devnum, reg, val); + if (ret < 0) { + pr_notice("\nmii_cl45_write fail\n"); + return -EIO; + } + val = air_mii_cl45_read(phydev, devnum, reg); + pr_notice("\nphy=%d, devnum=0x%x, reg=0x%x, val=0x%x confirm..\n", + phydev_addr(phydev), devnum, reg, val); + } else if (buf[0] == 'r') { + if (sscanf(buf, "r %x %x", &devnum, ®) == -1) + return -EFAULT; + + val = air_mii_cl45_read(phydev, devnum, reg); + pr_notice("\nphy=%d, devnum=0x%x, reg=0x%x, val=0x%x\n", + phydev_addr(phydev), devnum, reg, val); + } else + airphy_debugfs_mii_cl45_help(); + + return count; +} + static const struct file_operations airphy_lp_speed_fops = { .owner = THIS_MODULE, .open = airphy_lp_speed_open, @@ -1361,6 +1508,20 @@ static const struct file_operations airphy_temp_fops = { .release = single_release, }; +static const struct file_operations airphy_debugfs_cl22_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = airphy_debugfs_cl22, + .llseek = noop_llseek, +}; + +static const struct file_operations airphy_debugfs_cl45_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = airphy_debugfs_cl45, + .llseek = noop_llseek, +}; + int airphy_debugfs_init(struct phy_device *phydev) { int ret = 0; @@ -1404,6 +1565,12 @@ int airphy_debugfs_init(struct phy_device *phydev) debugfs_create_file(DEBUGFS_LP_SPEED, S_IFREG | 0444, dir, phydev, &airphy_lp_speed_fops); + debugfs_create_file(DEBUGFS_MII_CL22_OP, S_IFREG | 0200, + dir, phydev, + &airphy_debugfs_cl22_fops); + debugfs_create_file(DEBUGFS_MII_CL45_OP, S_IFREG | 0200, + dir, phydev, + &airphy_debugfs_cl45_fops); priv->debugfs_root = dir; return ret; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h index 9715a5899..dd4f7b1fb 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h @@ -31,6 +31,8 @@ #define DEBUGFS_DBG_REG_SHOW "dbg_regs_show" #define DEBUGFS_TEMPERATURE "temp" #define DEBUGFS_LP_SPEED "lp_speed" +#define DEBUGFS_MII_CL22_OP "cl22_op" +#define DEBUGFS_MII_CL45_OP "cl45_op" enum air_port_mode { AIR_PORT_MODE_FORCE_100, @@ -82,6 +84,7 @@ unsigned int air_buckpbus_reg_read(struct phy_device *phydev, int air_buckpbus_reg_write(struct phy_device *phydev, unsigned int pbus_address, unsigned int pbus_data); int en8811h_of_init(struct phy_device *phydev); +int air_surge_5ohm_config(struct phy_device *phydev); #ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS int airphy_debugfs_init(struct phy_device *phydev); void airphy_debugfs_remove(struct phy_device *phydev); diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c index 50a7f4986..d01169bce 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c @@ -35,6 +35,7 @@ MODULE_LICENSE("GPL"); * GPIO3 <-> BASE_T_LED2, **************************/ /* User-defined.B */ +/*#define AIR_MD32_FW_CHECK*/ #define AIR_LED_SUPPORT #ifdef AIR_LED_SUPPORT static const struct air_base_t_led_cfg led_cfg[3] = { @@ -52,9 +53,45 @@ static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M; /*********************************************************** * F U N C T I O N S ***********************************************************/ +static void air_mdio_read_buf(struct phy_device *phydev, unsigned long address, + const struct firmware *fw, unsigned int *crc32) +{ + unsigned int write_data, offset; + int ret = 0, len = 0; + unsigned int pbus_data_low, pbus_data_high; + struct device *dev = phydev_dev(phydev); + struct mii_bus *mbus = phydev_mdio_bus(phydev); + int addr = phydev_addr(phydev); + char *buf = kmalloc(fw->size, GFP_KERNEL); + memset(buf, '\0', fw->size); + /* page 4 */ + ret |= air_mii_cl22_write(mbus, addr, 0x1F, 4); + /* address increment*/ + ret |= air_mii_cl22_write(mbus, addr, 0x10, 0x8000); + ret |= air_mii_cl22_write(mbus, addr, + 0x15, (unsigned int)((address >> 16) & 0xffff)); + ret |= air_mii_cl22_write(mbus, addr, + 0x16, (unsigned int)(address & 0xffff)); + for (offset = 0; offset < fw->size; offset += 4) { + pbus_data_high = air_mii_cl22_read(mbus, addr, 0x17); + pbus_data_low = air_mii_cl22_read(mbus, addr, 0x18); + buf[offset + 0] = pbus_data_low & 0xff; + buf[offset + 1] = (pbus_data_low & 0xff00) >> 8; + buf[offset + 2] = pbus_data_high & 0xff; + buf[offset + 3] = (pbus_data_high & 0xff00) >> 8; + } + msleep(100); + *crc32 = ~crc32(~0, buf, fw->size); + ret |= air_mii_cl22_write(mbus, addr, 0x1F, 0); + kfree(buf); + if (ret) { + dev_info(dev, "%s 0x%lx FAIL(ret:%d)\n", + __func__, address, ret); + } +} -static int MDIOWriteBuf(struct phy_device *phydev, +static int air_mdio_write_buf(struct phy_device *phydev, unsigned long address, const struct firmware *fw) { unsigned int write_data, offset; @@ -115,6 +152,10 @@ static int en8811h_load_firmware(struct phy_device *phydev) const char *firmware; int ret = 0; u32 pbus_value = 0; +#ifdef AIR_MD32_FW_CHECK + unsigned int d_crc32 = 0, crc32 = 0; + int retry = 0; +#endif struct en8811h_priv *priv = phydev->priv; ret = air_buckpbus_reg_write(phydev, @@ -138,12 +179,12 @@ static int en8811h_load_firmware(struct phy_device *phydev) dev_info(dev, "%s: crc32=0x%x\n", firmware, ~crc32(~0, fw->data, fw->size)); /* Download DM */ - ret = MDIOWriteBuf(phydev, 0x00000000, fw); + ret = air_mdio_write_buf(phydev, 0x00000000, fw); release_firmware(fw); if (ret < 0) { dev_err(dev, - "MDIOWriteBuf 0x00000000 fail, ret: %d\n", ret); - return ret; + "air_mdio_write_buf 0x00000000 fail, ret: %d\n", ret); + goto release; } firmware = EN8811H_MD32_DSP; @@ -157,22 +198,56 @@ static int en8811h_load_firmware(struct phy_device *phydev) dev_info(dev, "%s: crc32=0x%x\n", firmware, ~crc32(~0, fw->data, fw->size)); /* Download PM */ - ret = MDIOWriteBuf(phydev, 0x00100000, fw); - release_firmware(fw); + ret = air_mdio_write_buf(phydev, 0x00100000, fw); if (ret < 0) { dev_err(dev, - "MDIOWriteBuf 0x00100000 fail , ret: %d\n", ret); - return ret; + "air_mdio_write_buf 0x00100000 fail , ret: %d\n", ret); + goto release; } pbus_value = air_buckpbus_reg_read(phydev, 0x800000); pbus_value &= ~BIT(11); ret = air_buckpbus_reg_write(phydev, 0x800000, pbus_value); if (ret < 0) - return ret; + goto release; +#ifdef AIR_MD32_FW_CHECK + crc32 = ~crc32(~0, fw->data, fw->size); + /* Check PM */ + air_mdio_read_buf(phydev, 0x100000, fw, &d_crc32); + if (d_crc32 == crc32) + dev_info(dev, "0x00100000 Check Sum Pass.\n"); + else { + dev_info(dev, "0x00100000 Check Sum Fail.\n"); + dev_info(dev, "CRC32 0x%x != Caculated CRC32 0x%x\n", + crc32, d_crc32); + } + release_firmware(fw); + retry = MAX_RETRY; + do { + ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x01); + if (ret < 0) + return ret; + msleep(100); + pbus_value = air_buckpbus_reg_read(phydev, 0x0f0018); + if (retry == 0) { + dev_err(dev, + "Release Software Reset fail , ret: %d\n", + pbus_value); + break; + } + retry--; + } while (pbus_value != 0x1); + dev_info(dev, + "Release Software Reset successful.\n"); +#else + release_firmware(fw); ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x01); if (ret < 0) return ret; +#endif return 0; +release: + release_firmware(fw); + return ret; } #ifdef AIR_LED_SUPPORT @@ -383,18 +458,10 @@ static int en8811h_probe(struct phy_device *phydev) "EN8811H initialize fail!\n"); goto priv_free; } - /* Mode selection*/ - dev_info(dev, "EN8811H Mode 1 !\n"); - ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0); - if (ret < 0) - goto priv_free; - ret = air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0); - if (ret < 0) - goto priv_free; - ret = air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101); - if (ret < 0) - goto priv_free; - ret = air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101); + ret |= air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002); if (ret < 0) goto priv_free; /* Serdes polarity */ @@ -415,6 +482,13 @@ static int en8811h_probe(struct phy_device *phydev) dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value); pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c); dev_info(dev, "MD32 FW Version : %08x\n", pbus_value); + if (priv->surge) { + ret = air_surge_5ohm_config(phydev); + if (ret < 0) + dev_err(dev, + "air_surge_5ohm_config fail. (ret=%d)\n", ret); + } else + dev_info(dev, "Surge Protection Mode - 0R\n"); #if defined(AIR_LED_SUPPORT) ret = en8811h_led_init(phydev); if (ret < 0) { diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Kconfig b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Kconfig new file mode 100644 index 000000000..654aa37a3 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Kconfig @@ -0,0 +1,8 @@ + +config AN8855_GSW + tristate "Driver for the Airoha AN8855 switch" + help + Airoha AN8855 devices and swconfig driver code, + Provide swconfig command for basic switch operation. + AN8855 support 2.5G speed and managed by SMI interface. + To compile this driver as a module, choose M here. diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Makefile b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Makefile new file mode 100644 index 000000000..5c24bdac8 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for Airoha AN8855 gigabit switch +# + +obj-$(CONFIG_AN8855_GSW) += an8855.o + +an8855-$(CONFIG_SWCONFIG) += an8855_swconfig.o + +an8855-y += an8855_mdio.o an8855.o \ + an8855_common.o an8855_vlan.o an8855_nl.o diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.c new file mode 100644 index 000000000..f3db8b83a --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.c @@ -0,0 +1,913 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "an8855.h" +#include "an8855_regs.h" + +/* AN8855 registers */ +#define SCU_BASE 0x10000000 +#define RG_RGMII_TXCK_C (SCU_BASE + 0x1d0) + +#define HSGMII_AN_CSR_BASE 0x10220000 +#define SGMII_REG_AN0 (HSGMII_AN_CSR_BASE + 0x000) +#define SGMII_REG_AN_13 (HSGMII_AN_CSR_BASE + 0x034) +#define SGMII_REG_AN_FORCE_CL37 (HSGMII_AN_CSR_BASE + 0x060) + +#define HSGMII_CSR_PCS_BASE 0x10220000 +#define RG_HSGMII_PCS_CTROL_1 (HSGMII_CSR_PCS_BASE + 0xa00) +#define RG_AN_SGMII_MODE_FORCE (HSGMII_CSR_PCS_BASE + 0xa24) + +#define MULTI_SGMII_CSR_BASE 0x10224000 +#define SGMII_STS_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x018) +#define MSG_RX_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x100) +#define MSG_RX_LIK_STS_0 (MULTI_SGMII_CSR_BASE + 0x514) +#define MSG_RX_LIK_STS_2 (MULTI_SGMII_CSR_BASE + 0x51c) +#define PHY_RX_FORCE_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x520) + +#define XFI_CSR_PCS_BASE 0x10225000 +#define RG_USXGMII_AN_CONTROL_0 (XFI_CSR_PCS_BASE + 0xbf8) + +#define MULTI_PHY_RA_CSR_BASE 0x10226000 +#define RG_RATE_ADAPT_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x000) +#define RATE_ADP_P0_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x100) +#define MII_RA_AN_ENABLE (MULTI_PHY_RA_CSR_BASE + 0x300) + +#define QP_DIG_CSR_BASE 0x1022a000 +#define QP_CK_RST_CTRL_4 (QP_DIG_CSR_BASE + 0x310) +#define QP_DIG_MODE_CTRL_0 (QP_DIG_CSR_BASE + 0x324) +#define QP_DIG_MODE_CTRL_1 (QP_DIG_CSR_BASE + 0x330) + +#define SERDES_WRAPPER_BASE 0x1022c000 +#define USGMII_CTRL_0 (SERDES_WRAPPER_BASE + 0x000) + +#define QP_PMA_TOP_BASE 0x1022e000 +#define PON_RXFEDIG_CTRL_0 (QP_PMA_TOP_BASE + 0x100) +#define PON_RXFEDIG_CTRL_9 (QP_PMA_TOP_BASE + 0x124) + +#define SS_LCPLL_PWCTL_SETTING_2 (QP_PMA_TOP_BASE + 0x208) +#define SS_LCPLL_TDC_FLT_2 (QP_PMA_TOP_BASE + 0x230) +#define SS_LCPLL_TDC_FLT_5 (QP_PMA_TOP_BASE + 0x23c) +#define SS_LCPLL_TDC_PCW_1 (QP_PMA_TOP_BASE + 0x248) +#define INTF_CTRL_8 (QP_PMA_TOP_BASE + 0x320) +#define INTF_CTRL_9 (QP_PMA_TOP_BASE + 0x324) +#define PLL_CTRL_0 (QP_PMA_TOP_BASE + 0x400) +#define PLL_CTRL_2 (QP_PMA_TOP_BASE + 0x408) +#define PLL_CTRL_3 (QP_PMA_TOP_BASE + 0x40c) +#define PLL_CTRL_4 (QP_PMA_TOP_BASE + 0x410) +#define PLL_CK_CTRL_0 (QP_PMA_TOP_BASE + 0x414) +#define RX_DLY_0 (QP_PMA_TOP_BASE + 0x614) +#define RX_CTRL_2 (QP_PMA_TOP_BASE + 0x630) +#define RX_CTRL_5 (QP_PMA_TOP_BASE + 0x63c) +#define RX_CTRL_6 (QP_PMA_TOP_BASE + 0x640) +#define RX_CTRL_7 (QP_PMA_TOP_BASE + 0x644) +#define RX_CTRL_8 (QP_PMA_TOP_BASE + 0x648) +#define RX_CTRL_26 (QP_PMA_TOP_BASE + 0x690) +#define RX_CTRL_42 (QP_PMA_TOP_BASE + 0x6d0) + +#define QP_ANA_CSR_BASE 0x1022f000 +#define RG_QP_RX_DAC_EN (QP_ANA_CSR_BASE + 0x00) +#define RG_QP_RXAFE_RESERVE (QP_ANA_CSR_BASE + 0x04) +#define RG_QP_CDR_LPF_MJV_LIM (QP_ANA_CSR_BASE + 0x0c) +#define RG_QP_CDR_LPF_SETVALUE (QP_ANA_CSR_BASE + 0x14) +#define RG_QP_CDR_PR_CKREF_DIV1 (QP_ANA_CSR_BASE + 0x18) +#define RG_QP_CDR_PR_KBAND_DIV_PCIE (QP_ANA_CSR_BASE + 0x1c) +#define RG_QP_CDR_FORCE_IBANDLPF_R_OFF (QP_ANA_CSR_BASE + 0x20) +#define RG_QP_TX_MODE_16B_EN (QP_ANA_CSR_BASE + 0x28) +#define RG_QP_PLL_IPLL_DIG_PWR_SEL (QP_ANA_CSR_BASE + 0x3c) +#define RG_QP_PLL_SDM_ORD (QP_ANA_CSR_BASE + 0x40) + +#define ETHER_SYS_BASE 0x1028c800 +#define RG_P5MUX_MODE (ETHER_SYS_BASE + 0x00) +#define RG_FORCE_CKDIR_SEL (ETHER_SYS_BASE + 0x04) +#define RG_SWITCH_MODE (ETHER_SYS_BASE + 0x08) +#define RG_FORCE_MAC5_SB (ETHER_SYS_BASE + 0x2c) +#define RG_GPHY_AFE_PWD (ETHER_SYS_BASE + 0x40) +#define RG_GPHY_SMI_ADDR (ETHER_SYS_BASE + 0x48) +#define CSR_RMII (ETHER_SYS_BASE + 0x70) + +/* PHY EEE Register bitmap of define */ +#define PHY_DEV07 0x07 +#define PHY_DEV07_REG_03C 0x3c + +/* PHY Extend Register 0x14 bitmap of define */ +#define PHY_EXT_REG_14 0x14 + +/* Fields of PHY_EXT_REG_14 */ +#define PHY_EN_DOWN_SHFIT BIT(4) + +/* Unique fields of PMCR for AN8855 */ +#define FORCE_TX_FC BIT(4) +#define FORCE_RX_FC BIT(5) +#define FORCE_DPX BIT(25) +#define FORCE_SPD BITS(28, 30) +#define FORCE_LNK BIT(24) +#define FORCE_MODE BIT(31) + +#define CHIP_ID 0x10005000 +#define CHIP_REV 0x10005004 + +static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw) +{ + u32 val = 0; + + /* PLL */ + val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_1); + val &= ~(0x3 << 2); + val |= (0x1 << 2); + an8855_reg_write(gsw, QP_DIG_MODE_CTRL_1, val); + + /* PLL - LPF */ + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~(0x3 << 0); + val |= (0x1 << 0); + val &= ~(0x7 << 2); + val |= (0x5 << 2); + val &= ~BITS(6, 7); + val &= ~(0x7 << 8); + val |= (0x3 << 8); + val |= BIT(29); + val &= ~BITS(12, 13); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - ICO */ + val = an8855_reg_read(gsw, PLL_CTRL_4); + val |= BIT(2); + an8855_reg_write(gsw, PLL_CTRL_4, val); + + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~BIT(14); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - CHP */ + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~(0xf << 16); + val |= (0x6 << 16); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - PFD */ + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~(0x3 << 20); + val |= (0x1 << 20); + val &= ~(0x3 << 24); + val |= (0x1 << 24); + val &= ~BIT(26); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - POSTDIV */ + val = an8855_reg_read(gsw, PLL_CTRL_2); + val |= BIT(22); + val &= ~BIT(27); + val &= ~BIT(28); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - SDM */ + val = an8855_reg_read(gsw, PLL_CTRL_4); + val &= ~BITS(3, 4); + an8855_reg_write(gsw, PLL_CTRL_4, val); + + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~BIT(30); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + val = an8855_reg_read(gsw, SS_LCPLL_PWCTL_SETTING_2); + val &= ~(0x3 << 16); + val |= (0x1 << 16); + an8855_reg_write(gsw, SS_LCPLL_PWCTL_SETTING_2, val); + + an8855_reg_write(gsw, SS_LCPLL_TDC_FLT_2, 0x7a000000); + an8855_reg_write(gsw, SS_LCPLL_TDC_PCW_1, 0x7a000000); + + val = an8855_reg_read(gsw, SS_LCPLL_TDC_FLT_5); + val &= ~BIT(24); + an8855_reg_write(gsw, SS_LCPLL_TDC_FLT_5, val); + + val = an8855_reg_read(gsw, PLL_CK_CTRL_0); + val &= ~BIT(8); + an8855_reg_write(gsw, PLL_CK_CTRL_0, val); + + /* PLL - SS */ + val = an8855_reg_read(gsw, PLL_CTRL_3); + val &= ~BITS(0, 15); + an8855_reg_write(gsw, PLL_CTRL_3, val); + + val = an8855_reg_read(gsw, PLL_CTRL_4); + val &= ~BITS(0, 1); + an8855_reg_write(gsw, PLL_CTRL_4, val); + + val = an8855_reg_read(gsw, PLL_CTRL_3); + val &= ~BITS(16, 31); + an8855_reg_write(gsw, PLL_CTRL_3, val); + + /* PLL - TDC */ + val = an8855_reg_read(gsw, PLL_CK_CTRL_0); + val &= ~BIT(9); + an8855_reg_write(gsw, PLL_CK_CTRL_0, val); + + val = an8855_reg_read(gsw, RG_QP_PLL_SDM_ORD); + val |= BIT(3); + val |= BIT(4); + an8855_reg_write(gsw, RG_QP_PLL_SDM_ORD, val); + + val = an8855_reg_read(gsw, RG_QP_RX_DAC_EN); + val &= ~(0x3 << 16); + val |= (0x2 << 16); + an8855_reg_write(gsw, RG_QP_RX_DAC_EN, val); + + /* TCL Disable (only for Co-SIM) */ + val = an8855_reg_read(gsw, PON_RXFEDIG_CTRL_0); + val &= ~BIT(12); + an8855_reg_write(gsw, PON_RXFEDIG_CTRL_0, val); + + /* TX Init */ + val = an8855_reg_read(gsw, RG_QP_TX_MODE_16B_EN); + val &= ~BIT(0); + val &= ~(0xffff << 16); + val |= (0x4 << 16); + an8855_reg_write(gsw, RG_QP_TX_MODE_16B_EN, val); + + /* RX Control */ + val = an8855_reg_read(gsw, RG_QP_RXAFE_RESERVE); + val |= BIT(11); + an8855_reg_write(gsw, RG_QP_RXAFE_RESERVE, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_LPF_MJV_LIM); + val &= ~(0x3 << 4); + val |= (0x1 << 4); + an8855_reg_write(gsw, RG_QP_CDR_LPF_MJV_LIM, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_LPF_SETVALUE); + val &= ~(0xf << 25); + val |= (0x1 << 25); + val &= ~(0x7 << 29); + val |= (0x3 << 29); + an8855_reg_write(gsw, RG_QP_CDR_LPF_SETVALUE, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1); + val &= ~(0x1f << 8); + val |= (0xf << 8); + an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE); + val &= ~(0x3f << 0); + val |= (0x19 << 0); + val &= ~BIT(6); + an8855_reg_write(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_FORCE_IBANDLPF_R_OFF); + val &= ~(0x7f << 6); + val |= (0x21 << 6); + val &= ~(0x3 << 16); + val |= (0x2 << 16); + val &= ~BIT(13); + an8855_reg_write(gsw, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE); + val &= ~BIT(30); + an8855_reg_write(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1); + val &= ~(0x7 << 24); + val |= (0x4 << 24); + an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val); + + val = an8855_reg_read(gsw, PLL_CTRL_0); + val |= BIT(0); + an8855_reg_write(gsw, PLL_CTRL_0, val); + + val = an8855_reg_read(gsw, RX_CTRL_26); + val &= ~BIT(23); + val |= BIT(26); + an8855_reg_write(gsw, RX_CTRL_26, val); + + val = an8855_reg_read(gsw, RX_DLY_0); + val &= ~(0xff << 0); + val |= (0x6f << 0); + val |= BITS(8, 13); + an8855_reg_write(gsw, RX_DLY_0, val); + + val = an8855_reg_read(gsw, RX_CTRL_42); + val &= ~(0x1fff << 0); + val |= (0x150 << 0); + an8855_reg_write(gsw, RX_CTRL_42, val); + + val = an8855_reg_read(gsw, RX_CTRL_2); + val &= ~(0x1fff << 16); + val |= (0x150 << 16); + an8855_reg_write(gsw, RX_CTRL_2, val); + + val = an8855_reg_read(gsw, PON_RXFEDIG_CTRL_9); + val &= ~(0x7 << 0); + val |= (0x1 << 0); + an8855_reg_write(gsw, PON_RXFEDIG_CTRL_9, val); + + val = an8855_reg_read(gsw, RX_CTRL_8); + val &= ~(0xfff << 16); + val |= (0x200 << 16); + val &= ~(0x7fff << 14); + val |= (0xfff << 14); + an8855_reg_write(gsw, RX_CTRL_8, val); + + /* Frequency memter */ + val = an8855_reg_read(gsw, RX_CTRL_5); + val &= ~(0xfffff << 10); + val |= (0x10 << 10); + an8855_reg_write(gsw, RX_CTRL_5, val); + + val = an8855_reg_read(gsw, RX_CTRL_6); + val &= ~(0xfffff << 0); + val |= (0x64 << 0); + an8855_reg_write(gsw, RX_CTRL_6, val); + + val = an8855_reg_read(gsw, RX_CTRL_7); + val &= ~(0xfffff << 0); + val |= (0x2710 << 0); + an8855_reg_write(gsw, RX_CTRL_7, val); + + /* PCS Init */ + val = an8855_reg_read(gsw, RG_HSGMII_PCS_CTROL_1); + val &= ~BIT(30); + an8855_reg_write(gsw, RG_HSGMII_PCS_CTROL_1, val); + + /* Rate Adaption */ + val = an8855_reg_read(gsw, RATE_ADP_P0_CTRL_0); + val &= ~BIT(31); + an8855_reg_write(gsw, RATE_ADP_P0_CTRL_0, val); + + val = an8855_reg_read(gsw, RG_RATE_ADAPT_CTRL_0); + val |= BIT(0); + val |= BIT(4); + val |= BITS(26, 27); + an8855_reg_write(gsw, RG_RATE_ADAPT_CTRL_0, val); + + /* Disable AN */ + val = an8855_reg_read(gsw, SGMII_REG_AN0); + val &= ~BIT(12); + an8855_reg_write(gsw, SGMII_REG_AN0, val); + + /* Force Speed */ + val = an8855_reg_read(gsw, SGMII_STS_CTRL_0); + val |= BIT(2); + val |= BITS(4, 5); + an8855_reg_write(gsw, SGMII_STS_CTRL_0, val); + + /* bypass flow control to MAC */ + an8855_reg_write(gsw, MSG_RX_LIK_STS_0, 0x01010107); + an8855_reg_write(gsw, MSG_RX_LIK_STS_2, 0x00000EEF); + + return 0; +} + +static int an8855_sgmii_setup(struct gsw_an8855 *gsw, int mode) +{ + u32 val = 0; + + /* PMA Init */ + /* PLL */ + val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_1); + val &= ~BITS(2, 3); + an8855_reg_write(gsw, QP_DIG_MODE_CTRL_1, val); + + /* PLL - LPF */ + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~(0x3 << 0); + val |= (0x1 << 0); + val &= ~(0x7 << 2); + val |= (0x5 << 2); + val &= ~BITS(6, 7); + val &= ~(0x7 << 8); + val |= (0x3 << 8); + val |= BIT(29); + val &= ~BITS(12, 13); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - ICO */ + val = an8855_reg_read(gsw, PLL_CTRL_4); + val |= BIT(2); + an8855_reg_write(gsw, PLL_CTRL_4, val); + + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~BIT(14); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - CHP */ + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~(0xf << 16); + val |= (0x4 << 16); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - PFD */ + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~(0x3 << 20); + val |= (0x1 << 20); + val &= ~(0x3 << 24); + val |= (0x1 << 24); + val &= ~BIT(26); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - POSTDIV */ + val = an8855_reg_read(gsw, PLL_CTRL_2); + val |= BIT(22); + val &= ~BIT(27); + val &= ~BIT(28); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + /* PLL - SDM */ + val = an8855_reg_read(gsw, PLL_CTRL_4); + val &= ~BITS(3, 4); + an8855_reg_write(gsw, PLL_CTRL_4, val); + + val = an8855_reg_read(gsw, PLL_CTRL_2); + val &= ~BIT(30); + an8855_reg_write(gsw, PLL_CTRL_2, val); + + val = an8855_reg_read(gsw, SS_LCPLL_PWCTL_SETTING_2); + val &= ~(0x3 << 16); + val |= (0x1 << 16); + an8855_reg_write(gsw, SS_LCPLL_PWCTL_SETTING_2, val); + + an8855_reg_write(gsw, SS_LCPLL_TDC_FLT_2, 0x48000000); + an8855_reg_write(gsw, SS_LCPLL_TDC_PCW_1, 0x48000000); + + val = an8855_reg_read(gsw, SS_LCPLL_TDC_FLT_5); + val &= ~BIT(24); + an8855_reg_write(gsw, SS_LCPLL_TDC_FLT_5, val); + + val = an8855_reg_read(gsw, PLL_CK_CTRL_0); + val &= ~BIT(8); + an8855_reg_write(gsw, PLL_CK_CTRL_0, val); + + /* PLL - SS */ + val = an8855_reg_read(gsw, PLL_CTRL_3); + val &= ~BITS(0, 15); + an8855_reg_write(gsw, PLL_CTRL_3, val); + + val = an8855_reg_read(gsw, PLL_CTRL_4); + val &= ~BITS(0, 1); + an8855_reg_write(gsw, PLL_CTRL_4, val); + + val = an8855_reg_read(gsw, PLL_CTRL_3); + val &= ~BITS(16, 31); + an8855_reg_write(gsw, PLL_CTRL_3, val); + + /* PLL - TDC */ + val = an8855_reg_read(gsw, PLL_CK_CTRL_0); + val &= ~BIT(9); + an8855_reg_write(gsw, PLL_CK_CTRL_0, val); + + val = an8855_reg_read(gsw, RG_QP_PLL_SDM_ORD); + val |= BIT(3); + val |= BIT(4); + an8855_reg_write(gsw, RG_QP_PLL_SDM_ORD, val); + + val = an8855_reg_read(gsw, RG_QP_RX_DAC_EN); + val &= ~(0x3 << 16); + val |= (0x2 << 16); + an8855_reg_write(gsw, RG_QP_RX_DAC_EN, val); + + /* PLL - TCL Disable (only for Co-SIM) */ + val = an8855_reg_read(gsw, PON_RXFEDIG_CTRL_0); + val &= ~BIT(12); + an8855_reg_write(gsw, PON_RXFEDIG_CTRL_0, val); + + /* TX Init */ + val = an8855_reg_read(gsw, RG_QP_TX_MODE_16B_EN); + val &= ~BIT(0); + val &= ~BITS(16, 31); + an8855_reg_write(gsw, RG_QP_TX_MODE_16B_EN, val); + + /* RX Init */ + val = an8855_reg_read(gsw, RG_QP_RXAFE_RESERVE); + val |= BIT(11); + an8855_reg_write(gsw, RG_QP_RXAFE_RESERVE, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_LPF_MJV_LIM); + val &= ~(0x3 << 4); + val |= (0x2 << 4); + an8855_reg_write(gsw, RG_QP_CDR_LPF_MJV_LIM, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_LPF_SETVALUE); + val &= ~(0xf << 25); + val |= (0x1 << 25); + val &= ~(0x7 << 29); + val |= (0x6 << 29); + an8855_reg_write(gsw, RG_QP_CDR_LPF_SETVALUE, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1); + val &= ~(0x1f << 8); + val |= (0xc << 8); + an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE); + val &= ~(0x3f << 0); + val |= (0x19 << 0); + val &= ~BIT(6); + an8855_reg_write(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_FORCE_IBANDLPF_R_OFF); + val &= ~(0x7f << 6); + val |= (0x21 << 6); + val &= ~(0x3 << 16); + val |= (0x2 << 16); + val &= ~BIT(13); + an8855_reg_write(gsw, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE); + val &= ~BIT(30); + an8855_reg_write(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE, val); + + val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1); + val &= ~(0x7 << 24); + val |= (0x4 << 24); + an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val); + + val = an8855_reg_read(gsw, PLL_CTRL_0); + val |= BIT(0); + an8855_reg_write(gsw, PLL_CTRL_0, val); + + val = an8855_reg_read(gsw, RX_CTRL_26); + val &= ~BIT(23); + if (mode == SGMII_MODE_AN) + val |= BIT(26); + + an8855_reg_write(gsw, RX_CTRL_26, val); + + val = an8855_reg_read(gsw, RX_DLY_0); + val &= ~(0xff << 0); + val |= (0x6f << 0); + val |= BITS(8, 13); + an8855_reg_write(gsw, RX_DLY_0, val); + + val = an8855_reg_read(gsw, RX_CTRL_42); + val &= ~(0x1fff << 0); + val |= (0x150 << 0); + an8855_reg_write(gsw, RX_CTRL_42, val); + + val = an8855_reg_read(gsw, RX_CTRL_2); + val &= ~(0x1fff << 16); + val |= (0x150 << 16); + an8855_reg_write(gsw, RX_CTRL_2, val); + + val = an8855_reg_read(gsw, PON_RXFEDIG_CTRL_9); + val &= ~(0x7 << 0); + val |= (0x1 << 0); + an8855_reg_write(gsw, PON_RXFEDIG_CTRL_9, val); + + val = an8855_reg_read(gsw, RX_CTRL_8); + val &= ~(0xfff << 16); + val |= (0x200 << 16); + val &= ~(0x7fff << 0); + val |= (0xfff << 0); + an8855_reg_write(gsw, RX_CTRL_8, val); + + /* Frequency memter */ + val = an8855_reg_read(gsw, RX_CTRL_5); + val &= ~(0xfffff << 10); + val |= (0x28 << 10); + an8855_reg_write(gsw, RX_CTRL_5, val); + + val = an8855_reg_read(gsw, RX_CTRL_6); + val &= ~(0xfffff << 0); + val |= (0x64 << 0); + an8855_reg_write(gsw, RX_CTRL_6, val); + + val = an8855_reg_read(gsw, RX_CTRL_7); + val &= ~(0xfffff << 0); + val |= (0x2710 << 0); + an8855_reg_write(gsw, RX_CTRL_7, val); + + if (mode == SGMII_MODE_FORCE) { + /* PCS Init */ + val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_0); + val &= ~BIT(0); + val &= ~BITS(4, 5); + an8855_reg_write(gsw, QP_DIG_MODE_CTRL_0, val); + + val = an8855_reg_read(gsw, RG_HSGMII_PCS_CTROL_1); + val &= ~BIT(30); + an8855_reg_write(gsw, RG_HSGMII_PCS_CTROL_1, val); + + /* Rate Adaption - GMII path config. */ + val = an8855_reg_read(gsw, RG_AN_SGMII_MODE_FORCE); + val |= BIT(0); + val &= ~BITS(4, 5); + an8855_reg_write(gsw, RG_AN_SGMII_MODE_FORCE, val); + + val = an8855_reg_read(gsw, SGMII_STS_CTRL_0); + val |= BIT(2); + val &= ~(0x3 << 4); + val |= (0x2 << 4); + an8855_reg_write(gsw, SGMII_STS_CTRL_0, val); + + val = an8855_reg_read(gsw, SGMII_REG_AN0); + val &= ~BIT(12); + an8855_reg_write(gsw, SGMII_REG_AN0, val); + + val = an8855_reg_read(gsw, PHY_RX_FORCE_CTRL_0); + val |= BIT(4); + an8855_reg_write(gsw, PHY_RX_FORCE_CTRL_0, val); + + val = an8855_reg_read(gsw, RATE_ADP_P0_CTRL_0); + val &= ~BITS(0, 3); + val |= BIT(28); + an8855_reg_write(gsw, RATE_ADP_P0_CTRL_0, val); + + val = an8855_reg_read(gsw, RG_RATE_ADAPT_CTRL_0); + val |= BIT(0); + val |= BIT(4); + val |= BITS(26, 27); + an8855_reg_write(gsw, RG_RATE_ADAPT_CTRL_0, val); + } else { + /* PCS Init */ + val = an8855_reg_read(gsw, RG_HSGMII_PCS_CTROL_1); + val &= ~BIT(30); + an8855_reg_write(gsw, RG_HSGMII_PCS_CTROL_1, val); + + /* Set AN Ability - Interrupt */ + val = an8855_reg_read(gsw, SGMII_REG_AN_FORCE_CL37); + val |= BIT(0); + an8855_reg_write(gsw, SGMII_REG_AN_FORCE_CL37, val); + + val = an8855_reg_read(gsw, SGMII_REG_AN_13); + val &= ~(0x3f << 0); + val |= (0xb << 0); + val |= BIT(8); + an8855_reg_write(gsw, SGMII_REG_AN_13, val); + + /* Rate Adaption - GMII path config. */ + val = an8855_reg_read(gsw, SGMII_REG_AN0); + val |= BIT(12); + an8855_reg_write(gsw, SGMII_REG_AN0, val); + + val = an8855_reg_read(gsw, MII_RA_AN_ENABLE); + val |= BIT(0); + an8855_reg_write(gsw, MII_RA_AN_ENABLE, val); + + val = an8855_reg_read(gsw, RATE_ADP_P0_CTRL_0); + val |= BIT(28); + an8855_reg_write(gsw, RATE_ADP_P0_CTRL_0, val); + + val = an8855_reg_read(gsw, RG_RATE_ADAPT_CTRL_0); + val |= BIT(0); + val |= BIT(4); + val |= BITS(26, 27); + an8855_reg_write(gsw, RG_RATE_ADAPT_CTRL_0, val); + + /* Only for Co-SIM */ + + /* AN Speed up (Only for Co-SIM) */ + + /* Restart AN */ + val = an8855_reg_read(gsw, SGMII_REG_AN0); + val |= BIT(9); + val |= BIT(15); + an8855_reg_write(gsw, SGMII_REG_AN0, val); + } + + /* bypass flow control to MAC */ + an8855_reg_write(gsw, MSG_RX_LIK_STS_0, 0x01010107); + an8855_reg_write(gsw, MSG_RX_LIK_STS_2, 0x00000EEF); + + return 0; +} + +static int an8855_set_port_rmii(struct gsw_an8855 *gsw) +{ + an8855_reg_write(gsw, RG_P5MUX_MODE, 0x301); + an8855_reg_write(gsw, RG_FORCE_CKDIR_SEL, 0x101); + an8855_reg_write(gsw, RG_SWITCH_MODE, 0x101); + an8855_reg_write(gsw, RG_FORCE_MAC5_SB, 0x1010101); + an8855_reg_write(gsw, CSR_RMII, 0x420102); + an8855_reg_write(gsw, RG_RGMII_TXCK_C, 0x1100910); + return 0; +} + +static int an8855_set_port_rgmii(struct gsw_an8855 *gsw) +{ + an8855_reg_write(gsw, RG_FORCE_MAC5_SB, 0x20101); + return 0; +} + +static int an8855_mac_port_setup(struct gsw_an8855 *gsw, u32 port, + struct an8855_port_cfg *port_cfg) +{ + u32 pmcr; + + if (port != 5) { + dev_info(gsw->dev, "port %d is not a MAC port\n", port); + return -EINVAL; + } + + if (port_cfg->enabled) { + pmcr = an8855_reg_read(gsw, PMCR(5)); + + switch (port_cfg->phy_mode) { + case PHY_INTERFACE_MODE_RMII: + pmcr &= ~FORCE_SPD; + pmcr |= FORCE_MODE | (MAC_SPD_100 << 28) | FORCE_DPX + | FORCE_LNK | FORCE_TX_FC | FORCE_RX_FC; + an8855_set_port_rmii(gsw); + break; + case PHY_INTERFACE_MODE_RGMII: + pmcr &= ~FORCE_SPD; + pmcr |= FORCE_MODE | (MAC_SPD_1000 << 28) | FORCE_DPX + | FORCE_LNK | FORCE_TX_FC | FORCE_RX_FC; + an8855_set_port_rgmii(gsw); + break; + case PHY_INTERFACE_MODE_SGMII: + if (port_cfg->force_link) { + pmcr &= ~FORCE_SPD; + pmcr |= FORCE_MODE | (MAC_SPD_1000 << 28) + | FORCE_DPX | FORCE_LNK | FORCE_TX_FC + | FORCE_RX_FC; + an8855_sgmii_setup(gsw, SGMII_MODE_FORCE); + } else + an8855_sgmii_setup(gsw, SGMII_MODE_AN); + break; + case PHY_INTERFACE_MODE_2500BASEX: + pmcr &= ~FORCE_SPD; + pmcr |= FORCE_MODE | (MAC_SPD_2500 << 28) | FORCE_DPX + | FORCE_LNK | FORCE_TX_FC | FORCE_RX_FC; + an8855_set_hsgmii_mode(gsw); + break; + default: + dev_info(gsw->dev, "%s is not supported by port %d\n", + phy_modes(port_cfg->phy_mode), port); + } + + if (port_cfg->force_link) + an8855_reg_write(gsw, PMCR(port), pmcr); + } + + return 0; +} + +static int an8855_sw_detect(struct gsw_an8855 *gsw, struct chip_rev *crev) +{ + u32 id, rev; + + id = an8855_reg_read(gsw, CHIP_ID); + rev = an8855_reg_read(gsw, CHIP_REV); + if (id == AN8855) { + if (crev) { + crev->rev = rev; + crev->name = "AN8855"; + } + + return 0; + } + + return -ENODEV; +} + +static void an8855_phy_setting(struct gsw_an8855 *gsw) +{ + int i; + u32 val; + + /* Release power down */ + an8855_reg_write(gsw, RG_GPHY_AFE_PWD, 0x0); + + for (i = 0; i < AN8855_NUM_PHYS; i++) { + /* Enable HW auto downshift */ + gsw->mii_write(gsw, i, 0x1f, 0x1); + val = gsw->mii_read(gsw, i, PHY_EXT_REG_14); + val |= PHY_EN_DOWN_SHFIT; + gsw->mii_write(gsw, i, PHY_EXT_REG_14, val); + gsw->mii_write(gsw, i, 0x1f, 0x0); + + /* Enable Asymmetric Pause Capability */ + val = gsw->mii_read(gsw, i, MII_ADVERTISE); + val |= ADVERTISE_PAUSE_ASYM; + gsw->mii_write(gsw, i, MII_ADVERTISE, val); + } +} + +static void an8855_low_power_setting(struct gsw_an8855 *gsw) +{ + int port, addr; + + for (port = 0; port < AN8855_NUM_PHYS; port++) { + gsw->mmd_write(gsw, port, 0x1e, 0x11, 0x0f00); + gsw->mmd_write(gsw, port, 0x1e, 0x3c, 0x0000); + gsw->mmd_write(gsw, port, 0x1e, 0x3d, 0x0000); + gsw->mmd_write(gsw, port, 0x1e, 0x3e, 0x0000); + gsw->mmd_write(gsw, port, 0x1e, 0xc6, 0x53aa); + } + + gsw->mmd_write(gsw, 0, 0x1f, 0x268, 0x07f1); + gsw->mmd_write(gsw, 0, 0x1f, 0x269, 0x2111); + gsw->mmd_write(gsw, 0, 0x1f, 0x26a, 0x0000); + gsw->mmd_write(gsw, 0, 0x1f, 0x26b, 0x0074); + gsw->mmd_write(gsw, 0, 0x1f, 0x26e, 0x00f6); + gsw->mmd_write(gsw, 0, 0x1f, 0x26f, 0x6666); + gsw->mmd_write(gsw, 0, 0x1f, 0x271, 0x2c02); + gsw->mmd_write(gsw, 0, 0x1f, 0x272, 0x0c22); + gsw->mmd_write(gsw, 0, 0x1f, 0x700, 0x0001); + gsw->mmd_write(gsw, 0, 0x1f, 0x701, 0x0803); + gsw->mmd_write(gsw, 0, 0x1f, 0x702, 0x01b6); + gsw->mmd_write(gsw, 0, 0x1f, 0x703, 0x2111); + + gsw->mmd_write(gsw, 1, 0x1f, 0x700, 0x0001); + + for (addr = 0x200; addr <= 0x230; addr += 2) + gsw->mmd_write(gsw, 0, 0x1f, addr, 0x2020); + + for (addr = 0x201; addr <= 0x231; addr += 2) + gsw->mmd_write(gsw, 0, 0x1f, addr, 0x0020); +} + +static void an8855_eee_setting(struct gsw_an8855 *gsw, u32 port) +{ + /* Disable EEE */ + gsw->mmd_write(gsw, port, PHY_DEV07, PHY_DEV07_REG_03C, 0); +} + +static int an8855_sw_init(struct gsw_an8855 *gsw) +{ + int i; + u32 val; + + gsw->phy_base = gsw->smi_addr & AN8855_SMI_ADDR_MASK; + + gsw->mii_read = an8855_mii_read; + gsw->mii_write = an8855_mii_write; + gsw->mmd_read = an8855_mmd_read; + gsw->mmd_write = an8855_mmd_write; + + /* Force MAC link down before reset */ + an8855_reg_write(gsw, PMCR(5), FORCE_MODE); + + /* Switch soft reset */ + an8855_reg_write(gsw, SYS_CTRL, SW_SYS_RST); + usleep_range(100000, 110000); + + /* change gphy smi address */ + if (gsw->new_smi_addr != gsw->smi_addr) { + an8855_reg_write(gsw, RG_GPHY_SMI_ADDR, gsw->new_smi_addr); + gsw->smi_addr = gsw->new_smi_addr; + gsw->phy_base = gsw->new_smi_addr; + } + + for (i = 0; i < AN8855_NUM_PHYS; i++) { + val = gsw->mii_read(gsw, i, MII_BMCR); + val |= BMCR_ISOLATE; + gsw->mii_write(gsw, i, MII_BMCR, val); + } + + an8855_mac_port_setup(gsw, 5, &gsw->port5_cfg); + + /* Global mac control settings */ + val = an8855_reg_read(gsw, GMACCR); + val |= (15 << MAX_RX_JUMBO_S) | RX_PKT_LEN_MAX_JUMBO; + an8855_reg_write(gsw, GMACCR, val); + + val = an8855_reg_read(gsw, CKGCR); + val &= ~(CKG_LNKDN_GLB_STOP | CKG_LNKDN_PORT_STOP); + an8855_reg_write(gsw, CKGCR, val); + return 0; +} + +static int an8855_sw_post_init(struct gsw_an8855 *gsw) +{ + int i; + u32 val; + + for (i = 0; i < AN8855_NUM_PHYS; i++) { + val = gsw->mii_read(gsw, i, MII_BMCR); + val &= ~BMCR_ISOLATE; + gsw->mii_write(gsw, i, MII_BMCR, val); + } + + an8855_phy_setting(gsw); + + for (i = 0; i < AN8855_NUM_PHYS; i++) + an8855_eee_setting(gsw, i); + + /* PHY restart AN*/ + for (i = 0; i < AN8855_NUM_PHYS; i++) + gsw->mii_write(gsw, i, MII_BMCR, 0x1240); + + return 0; +} + +struct an8855_sw_id an8855_id = { + .model = AN8855, + .detect = an8855_sw_detect, + .init = an8855_sw_init, + .post_init = an8855_sw_post_init +}; + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Min Yao "); +MODULE_DESCRIPTION("Driver for Airoha AN8855 Gigabit Switch"); diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.h new file mode 100644 index 000000000..883ba6e96 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#ifndef _AN8855_H_ +#define _AN8855_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SWCONFIG +#include +#endif + +#include "an8855_vlan.h" + +#define AN8855_DFL_CPU_PORT 5 +#define AN8855_NUM_PHYS 5 +#define AN8855_DFL_SMI_ADDR 0x1 +#define AN8855_SMI_ADDR_MASK 0x1f + +struct gsw_an8855; + +enum an8855_model { + AN8855 = 0x8855, +}; + +enum sgmii_mode { + SGMII_MODE_AN, + SGMII_MODE_FORCE, +}; + +struct an8855_port_cfg { + struct device_node *np; + phy_interface_t phy_mode; + u32 enabled: 1; + u32 force_link: 1; + u32 speed: 2; + u32 duplex: 1; + bool stag_on; +}; + +struct gsw_an8855 { + u32 id; + + struct device *dev; + struct mii_bus *host_bus; + u32 smi_addr; + u32 new_smi_addr; + u32 phy_base; + + enum an8855_model model; + const char *name; + + struct an8855_port_cfg port5_cfg; + + int phy_link_sts; + + int irq; + int reset_pin; + struct work_struct irq_worker; + +#ifdef CONFIG_SWCONFIG + struct switch_dev swdev; + u32 cpu_port; +#endif + + int global_vlan_enable; + struct an8855_vlan_entry vlan_entries[AN8855_NUM_VLANS]; + struct an8855_port_entry port_entries[AN8855_NUM_PORTS]; + + int (*mii_read)(struct gsw_an8855 *gsw, int phy, int reg); + void (*mii_write)(struct gsw_an8855 *gsw, int phy, int reg, u16 val); + + int (*mmd_read)(struct gsw_an8855 *gsw, int addr, int devad, u16 reg); + void (*mmd_write)(struct gsw_an8855 *gsw, int addr, int devad, u16 reg, + u16 val); + + struct list_head list; +}; + +struct chip_rev { + const char *name; + u32 rev; +}; + +struct an8855_sw_id { + enum an8855_model model; + int (*detect)(struct gsw_an8855 *gsw, struct chip_rev *crev); + int (*init)(struct gsw_an8855 *gsw); + int (*post_init)(struct gsw_an8855 *gsw); +}; + +extern struct list_head an8855_devs; +extern struct an8855_sw_id an8855_id; + +struct gsw_an8855 *an8855_get_gsw(u32 id); +struct gsw_an8855 *an8855_get_first_gsw(void); +void an8855_put_gsw(void); +void an8855_lock_gsw(void); + +u32 an8855_reg_read(struct gsw_an8855 *gsw, u32 reg); +void an8855_reg_write(struct gsw_an8855 *gsw, u32 reg, u32 val); + +int an8855_mii_read(struct gsw_an8855 *gsw, int phy, int reg); +void an8855_mii_write(struct gsw_an8855 *gsw, int phy, int reg, u16 val); + +int an8855_mmd_read(struct gsw_an8855 *gsw, int addr, int devad, u16 reg); +void an8855_mmd_write(struct gsw_an8855 *gsw, int addr, int devad, u16 reg, + u16 val); + +void an8855_irq_worker(struct work_struct *work); +void an8855_irq_enable(struct gsw_an8855 *gsw); + +#endif /* _AN8855_H_ */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_common.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_common.c new file mode 100644 index 000000000..c01b5c48c --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_common.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#include +#include + +#include "an8855.h" +#include "an8855_regs.h" + +void an8855_irq_enable(struct gsw_an8855 *gsw) +{ + u32 val; + int i; + + /* Record initial PHY link status */ + for (i = 0; i < AN8855_NUM_PHYS; i++) { + val = gsw->mii_read(gsw, i, MII_BMSR); + if (val & BMSR_LSTATUS) + gsw->phy_link_sts |= BIT(i); + } + + val = BIT(AN8855_NUM_PHYS) - 1; + an8855_reg_write(gsw, SYS_INT_EN, val); + + val = an8855_reg_read(gsw, INT_MASK); + val |= INT_SYS_BIT; + an8855_reg_write(gsw, INT_MASK, val); +} + +static void display_port_link_status(struct gsw_an8855 *gsw, u32 port) +{ + u32 pmsr, speed_bits; + const char *speed; + + pmsr = an8855_reg_read(gsw, PMSR(port)); + + speed_bits = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S; + + switch (speed_bits) { + case MAC_SPD_10: + speed = "10Mbps"; + break; + case MAC_SPD_100: + speed = "100Mbps"; + break; + case MAC_SPD_1000: + speed = "1Gbps"; + break; + case MAC_SPD_2500: + speed = "2.5Gbps"; + break; + default: + dev_info(gsw->dev, "Invalid speed\n"); + return; + } + + if (pmsr & MAC_LNK_STS) { + dev_info(gsw->dev, "Port %d Link is Up - %s/%s\n", + port, speed, (pmsr & MAC_DPX_STS) ? "Full" : "Half"); + } else { + dev_info(gsw->dev, "Port %d Link is Down\n", port); + } +} + +void an8855_irq_worker(struct work_struct *work) +{ + struct gsw_an8855 *gsw; + u32 sts, physts, laststs; + int i; + + gsw = container_of(work, struct gsw_an8855, irq_worker); + + sts = an8855_reg_read(gsw, SYS_INT_STS); + + /* Check for changed PHY link status */ + for (i = 0; i < AN8855_NUM_PHYS; i++) { + if (!(sts & PHY_LC_INT(i))) + continue; + + laststs = gsw->phy_link_sts & BIT(i); + physts = !!(gsw->mii_read(gsw, i, MII_BMSR) & BMSR_LSTATUS); + physts <<= i; + + if (physts ^ laststs) { + gsw->phy_link_sts ^= BIT(i); + display_port_link_status(gsw, i); + } + } + + an8855_reg_write(gsw, SYS_INT_STS, sts); + + enable_irq(gsw->irq); +} diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_mdio.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_mdio.c new file mode 100644 index 000000000..920240d76 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_mdio.c @@ -0,0 +1,491 @@ +// SPDX-License-Identifian8855_gsw_ider: GPL-2.0 +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "an8855.h" +#include "an8855_swconfig.h" +#include "an8855_regs.h" +#include "an8855_nl.h" + +/* AN8855 driver version */ +#define ARHT_AN8855_SWCFG_DRIVER_VER "1.0.1-L5.4" + +static u32 an8855_gsw_id; +struct list_head an8855_devs; +static DEFINE_MUTEX(an8855_devs_lock); + +static struct an8855_sw_id *an8855_sw_ids[] = { + &an8855_id, +}; + +u32 an8855_reg_read(struct gsw_an8855 *gsw, u32 reg) +{ + u32 high, low; + + mutex_lock(&gsw->host_bus->mdio_lock); + + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x4); + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0); + + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x15, + ((reg >> 16) & 0xFFFF)); + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x16, + (reg & 0xFFFF)); + + low = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x18); + high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x17); + + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x0); + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0); + + mutex_unlock(&gsw->host_bus->mdio_lock); + + return (high << 16) | (low & 0xffff); +} + +void an8855_reg_write(struct gsw_an8855 *gsw, u32 reg, u32 val) +{ + mutex_lock(&gsw->host_bus->mdio_lock); + + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x4); + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0); + + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x11, + ((reg >> 16) & 0xFFFF)); + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x12, + (reg & 0xFFFF)); + + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x13, + ((val >> 16) & 0xFFFF)); + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x14, + (val & 0xFFFF)); + + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x0); + gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0); + + mutex_unlock(&gsw->host_bus->mdio_lock); +} + +int an8855_mii_read(struct gsw_an8855 *gsw, int phy, int reg) +{ + int val; + + if (phy < AN8855_NUM_PHYS) + phy = (gsw->phy_base + phy) & AN8855_SMI_ADDR_MASK; + + mutex_lock(&gsw->host_bus->mdio_lock); + val = gsw->host_bus->read(gsw->host_bus, phy, reg); + mutex_unlock(&gsw->host_bus->mdio_lock); + + return val; +} + +void an8855_mii_write(struct gsw_an8855 *gsw, int phy, int reg, u16 val) +{ + if (phy < AN8855_NUM_PHYS) + phy = (gsw->phy_base + phy) & AN8855_SMI_ADDR_MASK; + + mutex_lock(&gsw->host_bus->mdio_lock); + gsw->host_bus->write(gsw->host_bus, phy, reg, val); + mutex_unlock(&gsw->host_bus->mdio_lock); +} + +int an8855_mmd_read(struct gsw_an8855 *gsw, int addr, int devad, u16 reg) +{ + int val; + u32 regnum = MII_ADDR_C45 | (devad << 16) | reg; + + if (addr < AN8855_NUM_PHYS) + addr = (gsw->phy_base + addr) & AN8855_SMI_ADDR_MASK; + + mutex_lock(&gsw->host_bus->mdio_lock); + val = gsw->host_bus->read(gsw->host_bus, addr, regnum); + mutex_unlock(&gsw->host_bus->mdio_lock); + + return val; +} + +void an8855_mmd_write(struct gsw_an8855 *gsw, int addr, int devad, u16 reg, + u16 val) +{ + u32 regnum = MII_ADDR_C45 | (devad << 16) | reg; + + if (addr < AN8855_NUM_PHYS) + addr = (gsw->phy_base + addr) & AN8855_SMI_ADDR_MASK; + + mutex_lock(&gsw->host_bus->mdio_lock); + gsw->host_bus->write(gsw->host_bus, addr, regnum, val); + mutex_unlock(&gsw->host_bus->mdio_lock); +} + +static inline int an8855_get_duplex(const struct device_node *np) +{ + return of_property_read_bool(np, "full-duplex"); +} + +static void an8855_load_port_cfg(struct gsw_an8855 *gsw) +{ + struct device_node *port_np; + struct device_node *fixed_link_node; + struct an8855_port_cfg *port_cfg; + u32 port; + + for_each_child_of_node(gsw->dev->of_node, port_np) { + if (!of_device_is_compatible(port_np, "airoha,an8855-port")) + continue; + + if (!of_device_is_available(port_np)) + continue; + + if (of_property_read_u32(port_np, "reg", &port)) + continue; + + switch (port) { + case 5: + port_cfg = &gsw->port5_cfg; + break; + default: + continue; + } + + if (port_cfg->enabled) { + dev_info(gsw->dev, "duplicated node for port%d\n", + port_cfg->phy_mode); + continue; + } + + port_cfg->np = port_np; + + port_cfg->phy_mode = of_get_phy_mode(port_np); + if (port_cfg->phy_mode < 0) { + dev_info(gsw->dev, "incorrect phy-mode %d\n", port); + continue; + } + + fixed_link_node = of_get_child_by_name(port_np, "fixed-link"); + if (fixed_link_node) { + u32 speed; + + port_cfg->force_link = 1; + port_cfg->duplex = an8855_get_duplex(fixed_link_node); + + if (of_property_read_u32(fixed_link_node, "speed", + &speed)) { + speed = 0; + continue; + } + + of_node_put(fixed_link_node); + + switch (speed) { + case 10: + port_cfg->speed = MAC_SPD_10; + break; + case 100: + port_cfg->speed = MAC_SPD_100; + break; + case 1000: + port_cfg->speed = MAC_SPD_1000; + break; + case 2500: + port_cfg->speed = MAC_SPD_2500; + break; + + default: + dev_info(gsw->dev, "incorrect speed %d\n", + speed); + continue; + } + } + + port_cfg->stag_on = + of_property_read_bool(port_cfg->np, "airoha,stag-on"); + port_cfg->enabled = 1; + } +} + +static void an8855_add_gsw(struct gsw_an8855 *gsw) +{ + mutex_lock(&an8855_devs_lock); + gsw->id = an8855_gsw_id++; + INIT_LIST_HEAD(&gsw->list); + list_add_tail(&gsw->list, &an8855_devs); + mutex_unlock(&an8855_devs_lock); +} + +static void an8855_remove_gsw(struct gsw_an8855 *gsw) +{ + mutex_lock(&an8855_devs_lock); + list_del(&gsw->list); + mutex_unlock(&an8855_devs_lock); +} + +struct gsw_an8855 *an8855_get_gsw(u32 id) +{ + struct gsw_an8855 *dev; + + mutex_lock(&an8855_devs_lock); + + list_for_each_entry(dev, &an8855_devs, list) { + if (dev->id == id) + return dev; + } + + mutex_unlock(&an8855_devs_lock); + + return NULL; +} + +struct gsw_an8855 *an8855_get_first_gsw(void) +{ + struct gsw_an8855 *dev; + + mutex_lock(&an8855_devs_lock); + + list_for_each_entry(dev, &an8855_devs, list) + return dev; + + mutex_unlock(&an8855_devs_lock); + + return NULL; +} + +void an8855_put_gsw(void) +{ + mutex_unlock(&an8855_devs_lock); +} + +void an8855_lock_gsw(void) +{ + mutex_lock(&an8855_devs_lock); +} + +static int an8855_hw_reset(struct gsw_an8855 *gsw) +{ + struct device_node *np = gsw->dev->of_node; + int ret; + + gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0); + if (gsw->reset_pin < 0) { + dev_info(gsw->dev, "No reset pin of switch\n"); + return 0; + } + + ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "an8855-reset"); + if (ret) { + dev_info(gsw->dev, "Failed to request gpio %d\n", + gsw->reset_pin); + return ret; + } + + gpio_direction_output(gsw->reset_pin, 0); + usleep_range(100000, 150000); + gpio_set_value(gsw->reset_pin, 1); + usleep_range(100000, 150000); + + return 0; +} + +static irqreturn_t an8855_irq_handler(int irq, void *dev) +{ + struct gsw_an8855 *gsw = dev; + + disable_irq_nosync(gsw->irq); + + schedule_work(&gsw->irq_worker); + + return IRQ_HANDLED; +} + +static int an8855_probe(struct platform_device *pdev) +{ + struct gsw_an8855 *gsw; + struct an8855_sw_id *sw; + struct device_node *np = pdev->dev.of_node; + struct device_node *mdio; + struct mii_bus *mdio_bus; + int ret = -EINVAL; + struct chip_rev rev; + struct an8855_mapping *map; + int i; + + mdio = of_parse_phandle(np, "airoha,mdio", 0); + if (!mdio) + return -EINVAL; + + mdio_bus = of_mdio_find_bus(mdio); + if (!mdio_bus) + return -EPROBE_DEFER; + + gsw = devm_kzalloc(&pdev->dev, sizeof(struct gsw_an8855), GFP_KERNEL); + if (!gsw) + return -ENOMEM; + + gsw->host_bus = mdio_bus; + gsw->dev = &pdev->dev; + + dev_info(gsw->dev, "AN8855 Driver Version=%s\n", + ARHT_AN8855_SWCFG_DRIVER_VER); + + /* Switch hard reset */ + if (an8855_hw_reset(gsw)) { + dev_info(&pdev->dev, "reset switch fail.\n"); + goto fail; + } + + /* Fetch the SMI address first */ + gsw->smi_addr = AN8855_DFL_SMI_ADDR; + if (of_property_read_u32(np, "airoha,smi-addr", &gsw->new_smi_addr)) + gsw->new_smi_addr = AN8855_DFL_SMI_ADDR; + + /* Get LAN/WAN port mapping */ + map = an8855_find_mapping(np); + if (map) { + an8855_apply_mapping(gsw, map); + gsw->global_vlan_enable = 1; + dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name); + } + + /* Load MAC port configurations */ + an8855_load_port_cfg(gsw); + + /* Check for valid switch and then initialize */ + an8855_gsw_id = 0; + for (i = 0; i < ARRAY_SIZE(an8855_sw_ids); i++) { + if (!an8855_sw_ids[i]->detect(gsw, &rev)) { + sw = an8855_sw_ids[i]; + + gsw->name = rev.name; + gsw->model = sw->model; + + dev_info(gsw->dev, "Switch is Airoha %s rev %d", + gsw->name, rev.rev); + + /* Initialize the switch */ + ret = sw->init(gsw); + if (ret) + goto fail; + + break; + } + } + + if (i >= ARRAY_SIZE(an8855_sw_ids)) { + dev_err(gsw->dev, "No an8855 switch found\n"); + goto fail; + } + + gsw->irq = platform_get_irq(pdev, 0); + if (gsw->irq >= 0) { + ret = devm_request_irq(gsw->dev, gsw->irq, an8855_irq_handler, + 0, dev_name(gsw->dev), gsw); + if (ret) { + dev_err(gsw->dev, "Failed to request irq %d\n", + gsw->irq); + goto fail; + } + + INIT_WORK(&gsw->irq_worker, an8855_irq_worker); + } + + platform_set_drvdata(pdev, gsw); + + an8855_add_gsw(gsw); + + an8855_gsw_nl_init(); + + an8855_swconfig_init(gsw); + + if (sw->post_init) + sw->post_init(gsw); + + if (gsw->irq >= 0) + an8855_irq_enable(gsw); + + return 0; + +fail: + devm_kfree(&pdev->dev, gsw); + + return ret; +} + +static int an8855_remove(struct platform_device *pdev) +{ + struct gsw_an8855 *gsw = platform_get_drvdata(pdev); + + if (gsw->irq >= 0) + cancel_work_sync(&gsw->irq_worker); + + if (gsw->reset_pin >= 0) + devm_gpio_free(&pdev->dev, gsw->reset_pin); + +#ifdef CONFIG_SWCONFIG + an8855_swconfig_destroy(gsw); +#endif + + an8855_gsw_nl_exit(); + + an8855_remove_gsw(gsw); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static const struct of_device_id an8855_ids[] = { + {.compatible = "airoha,an8855"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, an8855_ids); + +static struct platform_driver an8855_driver = { + .probe = an8855_probe, + .remove = an8855_remove, + .driver = { + .name = "an8855", + .of_match_table = an8855_ids, + }, +}; + +static int __init an8855_init(void) +{ + int ret; + + INIT_LIST_HEAD(&an8855_devs); + ret = platform_driver_register(&an8855_driver); + + return ret; +} + +module_init(an8855_init); + +static void __exit an8855_exit(void) +{ + platform_driver_unregister(&an8855_driver); +} + +module_exit(an8855_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Min Yao "); +MODULE_VERSION(ARHT_AN8855_SWCFG_DRIVER_VER); +MODULE_DESCRIPTION("Driver for Airoha AN8855 Gigabit Switch"); diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.c new file mode 100644 index 000000000..37e3dad39 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#include +#include +#include +#include +#include + +#include "an8855.h" +#include "an8855_nl.h" + +struct an8855_nl_cmd_item { + enum an8855_cmd cmd; + bool require_dev; + int (*process)(struct genl_info *info, struct gsw_an8855 *gsw); + u32 nr_required_attrs; + const enum an8855_attr *required_attrs; +}; + +static int an8855_nl_response(struct sk_buff *skb, struct genl_info *info); + +static const struct nla_policy an8855_nl_cmd_policy[] = { + [AN8855_ATTR_TYPE_MESG] = { .type = NLA_STRING }, + [AN8855_ATTR_TYPE_PHY] = { .type = NLA_S32 }, + [AN8855_ATTR_TYPE_REG] = { .type = NLA_S32 }, + [AN8855_ATTR_TYPE_VAL] = { .type = NLA_S32 }, + [AN8855_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 }, + [AN8855_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 }, + [AN8855_ATTR_TYPE_DEVAD] = { .type = NLA_S32 }, +}; + +static const struct genl_ops an8855_nl_ops[] = { + { + .cmd = AN8855_CMD_REQUEST, + .doit = an8855_nl_response, +// .policy = an8855_nl_cmd_policy, + .flags = GENL_ADMIN_PERM, + }, { + .cmd = AN8855_CMD_READ, + .doit = an8855_nl_response, +// .policy = an8855_nl_cmd_policy, + .flags = GENL_ADMIN_PERM, + }, { + .cmd = AN8855_CMD_WRITE, + .doit = an8855_nl_response, +// .policy = an8855_nl_cmd_policy, + .flags = GENL_ADMIN_PERM, + }, +}; + +static struct genl_family an8855_nl_family = { + .name = AN8855_GENL_NAME, + .version = AN8855_GENL_VERSION, + .maxattr = AN8855_NR_ATTR_TYPE, + .ops = an8855_nl_ops, + .n_ops = ARRAY_SIZE(an8855_nl_ops), + .policy = an8855_nl_cmd_policy, +}; + +static int an8855_nl_list_devs(char *buff, int size) +{ + struct gsw_an8855 *gsw; + int len, total = 0; + char buf[80]; + + memset(buff, 0, size); + + an8855_lock_gsw(); + + list_for_each_entry(gsw, &an8855_devs, list) { + len = snprintf(buf, sizeof(buf), + "id: %d, model: %s, node: %s\n", + gsw->id, gsw->name, gsw->dev->of_node->name); + if (len == strlen(buf)) { + if (size - total > 0) + strncat(buff, buf, size - total); + total += len; + } + } + + an8855_put_gsw(); + + return total; +} + +static int an8855_nl_prepare_reply(struct genl_info *info, u8 cmd, + struct sk_buff **skbp) +{ + struct sk_buff *msg; + void *reply; + + if (!info) + return -EINVAL; + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + /* Construct send-back message header */ + reply = genlmsg_put(msg, info->snd_portid, info->snd_seq, + &an8855_nl_family, 0, cmd); + if (!reply) { + nlmsg_free(msg); + return -EINVAL; + } + + *skbp = msg; + return 0; +} + +static int an8855_nl_send_reply(struct sk_buff *skb, struct genl_info *info) +{ + struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb)); + void *reply = genlmsg_data(genlhdr); + + /* Finalize a generic netlink message (update message header) */ + genlmsg_end(skb, reply); + + /* reply to a request */ + return genlmsg_reply(skb, info); +} + +static s32 an8855_nl_get_s32(struct genl_info *info, enum an8855_attr attr, + s32 defval) +{ + struct nlattr *na; + + na = info->attrs[attr]; + if (na) + return nla_get_s32(na); + + return defval; +} + +static int an8855_nl_get_u32(struct genl_info *info, enum an8855_attr attr, + u32 *val) +{ + struct nlattr *na; + + na = info->attrs[attr]; + if (na) { + *val = nla_get_u32(na); + return 0; + } + + return -1; +} + +static struct gsw_an8855 *an8855_nl_parse_find_gsw(struct genl_info *info) +{ + struct gsw_an8855 *gsw; + struct nlattr *na; + int gsw_id; + + na = info->attrs[AN8855_ATTR_TYPE_DEV_ID]; + if (na) { + gsw_id = nla_get_s32(na); + if (gsw_id >= 0) + gsw = an8855_get_gsw(gsw_id); + else + gsw = an8855_get_first_gsw(); + } else { + gsw = an8855_get_first_gsw(); + } + + return gsw; +} + +static int an8855_nl_get_swdevs(struct genl_info *info, struct gsw_an8855 *gsw) +{ + struct sk_buff *rep_skb = NULL; + char dev_info[512]; + int ret; + + ret = an8855_nl_list_devs(dev_info, sizeof(dev_info) - 1); + if (!ret) { + pr_info("No switch registered\n"); + return -EINVAL; + } + + ret = an8855_nl_prepare_reply(info, AN8855_CMD_REPLY, &rep_skb); + if (ret < 0) + goto err; + + ret = nla_put_string(rep_skb, AN8855_ATTR_TYPE_MESG, dev_info); + if (ret < 0) + goto err; + + return an8855_nl_send_reply(rep_skb, info); + +err: + if (rep_skb) + nlmsg_free(rep_skb); + + return ret; +} + +static int an8855_nl_reply_read(struct genl_info *info, struct gsw_an8855 *gsw) +{ + struct sk_buff *rep_skb = NULL; + s32 phy, devad, reg; + int value; + int ret = 0; + + phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1); + devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1); + reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1); + + if (reg < 0) + goto err; + + ret = an8855_nl_prepare_reply(info, AN8855_CMD_READ, &rep_skb); + if (ret < 0) + goto err; + + if (phy >= 0) { + if (devad < 0) + value = gsw->mii_read(gsw, phy, reg); + else + value = gsw->mmd_read(gsw, phy, devad, reg); + } else { + value = an8855_reg_read(gsw, reg); + } + + ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg); + if (ret < 0) + goto err; + + ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value); + if (ret < 0) + goto err; + + return an8855_nl_send_reply(rep_skb, info); + +err: + if (rep_skb) + nlmsg_free(rep_skb); + + return ret; +} + +static int an8855_nl_reply_write(struct genl_info *info, struct gsw_an8855 *gsw) +{ + struct sk_buff *rep_skb = NULL; + s32 phy, devad, reg; + u32 value; + int ret = 0; + + phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1); + devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1); + reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1); + + if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value)) + goto err; + + if (reg < 0) + goto err; + + ret = an8855_nl_prepare_reply(info, AN8855_CMD_WRITE, &rep_skb); + if (ret < 0) + goto err; + + if (phy >= 0) { + if (devad < 0) + gsw->mii_write(gsw, phy, reg, value); + else + gsw->mmd_write(gsw, phy, devad, reg, value); + } else { + an8855_reg_write(gsw, reg, value); + } + + ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg); + if (ret < 0) + goto err; + + ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value); + if (ret < 0) + goto err; + + return an8855_nl_send_reply(rep_skb, info); + +err: + if (rep_skb) + nlmsg_free(rep_skb); + + return ret; +} + +static const enum an8855_attr an8855_nl_cmd_read_attrs[] = { + AN8855_ATTR_TYPE_REG +}; + +static const enum an8855_attr an8855_nl_cmd_write_attrs[] = { + AN8855_ATTR_TYPE_REG, + AN8855_ATTR_TYPE_VAL +}; + +static const struct an8855_nl_cmd_item an8855_nl_cmds[] = { + { + .cmd = AN8855_CMD_REQUEST, + .require_dev = false, + .process = an8855_nl_get_swdevs + }, { + .cmd = AN8855_CMD_READ, + .require_dev = true, + .process = an8855_nl_reply_read, + .required_attrs = an8855_nl_cmd_read_attrs, + .nr_required_attrs = ARRAY_SIZE(an8855_nl_cmd_read_attrs), + }, { + .cmd = AN8855_CMD_WRITE, + .require_dev = true, + .process = an8855_nl_reply_write, + .required_attrs = an8855_nl_cmd_write_attrs, + .nr_required_attrs = ARRAY_SIZE(an8855_nl_cmd_write_attrs), + } +}; + +static int an8855_nl_response(struct sk_buff *skb, struct genl_info *info) +{ + struct genlmsghdr *hdr = nlmsg_data(info->nlhdr); + const struct an8855_nl_cmd_item *cmditem = NULL; + struct gsw_an8855 *gsw = NULL; + u32 sat_req_attrs = 0; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(an8855_nl_cmds); i++) { + if (hdr->cmd == an8855_nl_cmds[i].cmd) { + cmditem = &an8855_nl_cmds[i]; + break; + } + } + + if (!cmditem) { + pr_info("an8855-nl: unknown cmd %u\n", hdr->cmd); + return -EINVAL; + } + + for (i = 0; i < cmditem->nr_required_attrs; i++) { + if (info->attrs[cmditem->required_attrs[i]]) + sat_req_attrs++; + } + + if (sat_req_attrs != cmditem->nr_required_attrs) { + pr_info("an8855-nl: missing required attr(s) for cmd %u\n", + hdr->cmd); + return -EINVAL; + } + + if (cmditem->require_dev) { + gsw = an8855_nl_parse_find_gsw(info); + if (!gsw) { + pr_info("an8855-nl: failed to find switch dev\n"); + return -EINVAL; + } + } + + ret = cmditem->process(info, gsw); + + an8855_put_gsw(); + + return ret; +} + +int an8855_gsw_nl_init(void) +{ + int ret; + + ret = genl_register_family(&an8855_nl_family); + if (ret) { + pr_info("an8855-nl: genl_register_family_with_ops failed\n"); + return ret; + } + + return 0; +} + +void an8855_gsw_nl_exit(void) +{ + genl_unregister_family(&an8855_nl_family); +} diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.h new file mode 100644 index 000000000..b00df7540 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#ifndef _AN8855_NL_H_ +#define _AN8855_NL_H_ + +#define AN8855_GENL_NAME "an8855" +#define AN8855_GENL_VERSION 0x1 + +enum an8855_cmd { + AN8855_CMD_UNSPEC = 0, + AN8855_CMD_REQUEST, + AN8855_CMD_REPLY, + AN8855_CMD_READ, + AN8855_CMD_WRITE, + + __AN8855_CMD_MAX, +}; + +enum an8855_attr { + AN8855_ATTR_TYPE_UNSPEC = 0, + AN8855_ATTR_TYPE_MESG, + AN8855_ATTR_TYPE_PHY, + AN8855_ATTR_TYPE_DEVAD, + AN8855_ATTR_TYPE_REG, + AN8855_ATTR_TYPE_VAL, + AN8855_ATTR_TYPE_DEV_NAME, + AN8855_ATTR_TYPE_DEV_ID, + + __AN8855_ATTR_TYPE_MAX, +}; + +#define AN8855_NR_ATTR_TYPE (__AN8855_ATTR_TYPE_MAX - 1) + +#ifdef __KERNEL__ +int an8855_gsw_nl_init(void); +void an8855_gsw_nl_exit(void); +#endif /* __KERNEL__ */ + +#endif /* _AN8855_NL_H_ */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_regs.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_regs.h new file mode 100644 index 000000000..9dbfaeb0f --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_regs.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#ifndef _AN8855_REGS_H_ +#define _AN8855_REGS_H_ + +#include + +#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n))) + +/* Values of Egress TAG Control */ +#define ETAG_CTRL_UNTAG 0 +#define ETAG_CTRL_TAG 2 +#define ETAG_CTRL_SWAP 1 +#define ETAG_CTRL_STACK 3 + +#define VTCR 0x10200600 +#define VAWD0 0x10200604 +#define VAWD1 0x10200608 +#define VARD0 0x10200618 +#define VARD1 0x1020061C + +/* Fields of VTCR */ +#define VTCR_BUSY BIT(31) +#define VTCR_FUNC_S 12 +#define VTCR_FUNC_M 0xf000 +#define VTCR_VID_S 0 +#define VTCR_VID_M 0xfff + +/* Values of VTCR_FUNC */ +#define VTCR_READ_VLAN_ENTRY 0 +#define VTCR_WRITE_VLAN_ENTRY 1 + +/* VLAN entry fields */ +#define IVL_MAC BIT(5) +#define EG_CON BIT(11) +#define VTAG_EN BIT(10) +#define PORT_MEM_S 26 +#define PORT_MEM_M 0xfc000000 +#define VENTRY_VALID BIT(0) +#define ETAG_M 0x3fff000 +#define PORT_ETAG_S(p) (((p) * 2) + 12) +#define PORT_ETAG_M 0x03 + +#define PORT_CTRL_BASE 0x10208000 +#define PORT_CTRL_PORT_OFFSET 0x200 +#define PORT_CTRL_REG(p, r) (PORT_CTRL_BASE + \ + (p) * PORT_CTRL_PORT_OFFSET + (r)) +#define PCR(p) PORT_CTRL_REG(p, 0x04) +#define PVC(p) PORT_CTRL_REG(p, 0x10) +#define PORTMATRIX(p) PORT_CTRL_REG(p, 0x44) +#define PVID(p) PORT_CTRL_REG(p, 0x48) + +#define GRP_PORT_VID_M 0xfff + +/* Values of PORT_VLAN */ +#define PORT_MATRIX_MODE 0 +#define FALLBACK_MODE 1 +#define CHECK_MODE 2 +#define SECURITY_MODE 3 + +/* Fields of PVC */ +#define STAG_VPID_S 16 +#define STAG_VPID_M 0xffff0000 +#define VLAN_ATTR_S 6 +#define VLAN_ATTR_M 0xc0 +#define PVC_STAG_REPLACE BIT(11) +#define PVC_PORT_STAG BIT(5) + +/* Values of VLAN_ATTR */ +#define VA_USER_PORT 0 +#define VA_STACK_PORT 1 +#define VA_TRANSLATION_PORT 2 +#define VA_TRANSPARENT_PORT 3 + +#define PORT_MATRIX_M ((1 << AN8855_NUM_PORTS) - 1) + +#define PORT_MAC_CTRL_BASE 0x10210000 +#define PORT_MAC_CTRL_PORT_OFFSET 0x200 +#define PORT_MAC_CTRL_REG(p, r) (PORT_MAC_CTRL_BASE + \ + (p) * PORT_MAC_CTRL_PORT_OFFSET + (r)) +#define PMCR(p) PORT_MAC_CTRL_REG(p, 0x00) +#define PMSR(p) PORT_MAC_CTRL_REG(p, 0x10) + +#define GMACCR (PORT_MAC_CTRL_BASE + 0x30e0) + +#define MAX_RX_JUMBO_S 2 +#define MAX_RX_JUMBO_M 0x3c +#define MAX_RX_PKT_LEN_S 0 +#define MAX_RX_PKT_LEN_M 0x3 + +/* Values of MAX_RX_PKT_LEN */ +#define RX_PKT_LEN_1518 0 +#define RX_PKT_LEN_1536 1 +#define RX_PKT_LEN_1522 2 +#define RX_PKT_LEN_MAX_JUMBO 3 + +/* Fields of PMSR */ +#define EEE1G_STS BIT(7) +#define EEE100_STS BIT(6) +#define RX_FC_STS BIT(5) +#define TX_FC_STS BIT(4) +#define MAC_SPD_STS_S 28 +#define MAC_SPD_STS_M 0x70000000 +#define MAC_DPX_STS BIT(25) +#define MAC_LNK_STS BIT(24) + +/* Values of MAC_SPD_STS */ +#define MAC_SPD_10 0 +#define MAC_SPD_100 1 +#define MAC_SPD_1000 2 +#define MAC_SPD_2500 3 + +#define MIB_COUNTER_BASE 0x10214000 +#define MIB_COUNTER_PORT_OFFSET 0x200 +#define MIB_COUNTER_REG(p, r) (MIB_COUNTER_BASE + \ + (p) * MIB_COUNTER_PORT_OFFSET + (r)) +#define STATS_TDPC 0x00 +#define STATS_TCRC 0x04 +#define STATS_TUPC 0x08 +#define STATS_TMPC 0x0C +#define STATS_TBPC 0x10 +#define STATS_TCEC 0x14 +#define STATS_TSCEC 0x18 +#define STATS_TMCEC 0x1C +#define STATS_TDEC 0x20 +#define STATS_TLCEC 0x24 +#define STATS_TXCEC 0x28 +#define STATS_TPPC 0x2C +#define STATS_TL64PC 0x30 +#define STATS_TL65PC 0x34 +#define STATS_TL128PC 0x38 +#define STATS_TL256PC 0x3C +#define STATS_TL512PC 0x40 +#define STATS_TL1024PC 0x44 +#define STATS_TL1519PC 0x48 +#define STATS_TOC 0x4C +#define STATS_TODPC 0x54 +#define STATS_TOC2 0x58 + +#define STATS_RDPC 0x80 +#define STATS_RFPC 0x84 +#define STATS_RUPC 0x88 +#define STATS_RMPC 0x8C +#define STATS_RBPC 0x90 +#define STATS_RAEPC 0x94 +#define STATS_RCEPC 0x98 +#define STATS_RUSPC 0x9C +#define STATS_RFEPC 0xA0 +#define STATS_ROSPC 0xA4 +#define STATS_RJEPC 0xA8 +#define STATS_RPPC 0xAC +#define STATS_RL64PC 0xB0 +#define STATS_RL65PC 0xB4 +#define STATS_RL128PC 0xB8 +#define STATS_RL256PC 0xBC +#define STATS_RL512PC 0xC0 +#define STATS_RL1024PC 0xC4 +#define STATS_RL1519PC 0xC8 +#define STATS_ROC 0xCC +#define STATS_RDPC_CTRL 0xD4 +#define STATS_RDPC_ING 0xD8 +#define STATS_RDPC_ARL 0xDC +#define STATS_RDPC_FC 0xE0 +#define STATS_RDPC_WRED 0xE4 +#define STATS_RDPC_MIR 0xE8 +#define STATS_ROC2 0xEC +#define STATS_RSFSPC 0xF4 +#define STATS_RSFTPC 0xF8 +#define STATS_RXCDPC 0xFC + +#define SYS_CTRL 0x100050C0 +#define SW_SYS_RST BIT(31) + +#define INT_MASK 0x100050F0 +#define INT_SYS_BIT BIT(15) + +#define SYS_INT_EN 0x1021C010 +#define SYS_INT_STS 0x1021C014 +#define PHY_LC_INT(p) BIT(p) + +#define CKGCR (0x10213E1C) +#define CKG_LNKDN_GLB_STOP (0x01) +#define CKG_LNKDN_PORT_STOP (0x02) +#endif /* _AN8855_REGS_H_ */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.c new file mode 100644 index 000000000..e7965829a --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.c @@ -0,0 +1,527 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "an8855.h" +#include "an8855_swconfig.h" +#include "an8855_regs.h" + +#define AN8855_PORT_MIB_TXB_ID 19 /* TxByte */ +#define AN8855_PORT_MIB_RXB_ID 40 /* RxByte */ + +#define MIB_DESC(_s, _o, _n) \ + { \ + .size = (_s), \ + .offset = (_o), \ + .name = (_n), \ + } + +struct an8855_mib_desc { + unsigned int size; + unsigned int offset; + const char *name; +}; + +static const struct an8855_mib_desc an8855_mibs[] = { + MIB_DESC(1, STATS_TDPC, "TxDrop"), + MIB_DESC(1, STATS_TCRC, "TxCRC"), + MIB_DESC(1, STATS_TUPC, "TxUni"), + MIB_DESC(1, STATS_TMPC, "TxMulti"), + MIB_DESC(1, STATS_TBPC, "TxBroad"), + MIB_DESC(1, STATS_TCEC, "TxCollision"), + MIB_DESC(1, STATS_TSCEC, "TxSingleCol"), + MIB_DESC(1, STATS_TMCEC, "TxMultiCol"), + MIB_DESC(1, STATS_TDEC, "TxDefer"), + MIB_DESC(1, STATS_TLCEC, "TxLateCol"), + MIB_DESC(1, STATS_TXCEC, "TxExcCol"), + MIB_DESC(1, STATS_TPPC, "TxPause"), + MIB_DESC(1, STATS_TL64PC, "Tx64Byte"), + MIB_DESC(1, STATS_TL65PC, "Tx65Byte"), + MIB_DESC(1, STATS_TL128PC, "Tx128Byte"), + MIB_DESC(1, STATS_TL256PC, "Tx256Byte"), + MIB_DESC(1, STATS_TL512PC, "Tx512Byte"), + MIB_DESC(1, STATS_TL1024PC, "Tx1024Byte"), + MIB_DESC(1, STATS_TL1519PC, "Tx1519Byte"), + MIB_DESC(2, STATS_TOC, "TxByte"), + MIB_DESC(1, STATS_TODPC, "TxOverSize"), + MIB_DESC(2, STATS_TOC2, "SecondaryTxByte"), + MIB_DESC(1, STATS_RDPC, "RxDrop"), + MIB_DESC(1, STATS_RFPC, "RxFiltered"), + MIB_DESC(1, STATS_RUPC, "RxUni"), + MIB_DESC(1, STATS_RMPC, "RxMulti"), + MIB_DESC(1, STATS_RBPC, "RxBroad"), + MIB_DESC(1, STATS_RAEPC, "RxAlignErr"), + MIB_DESC(1, STATS_RCEPC, "RxCRC"), + MIB_DESC(1, STATS_RUSPC, "RxUnderSize"), + MIB_DESC(1, STATS_RFEPC, "RxFragment"), + MIB_DESC(1, STATS_ROSPC, "RxOverSize"), + MIB_DESC(1, STATS_RJEPC, "RxJabber"), + MIB_DESC(1, STATS_RPPC, "RxPause"), + MIB_DESC(1, STATS_RL64PC, "Rx64Byte"), + MIB_DESC(1, STATS_RL65PC, "Rx65Byte"), + MIB_DESC(1, STATS_RL128PC, "Rx128Byte"), + MIB_DESC(1, STATS_RL256PC, "Rx256Byte"), + MIB_DESC(1, STATS_RL512PC, "Rx512Byte"), + MIB_DESC(1, STATS_RL1024PC, "Rx1024Byte"), + MIB_DESC(2, STATS_ROC, "RxByte"), + MIB_DESC(1, STATS_RDPC_CTRL, "RxCtrlDrop"), + MIB_DESC(1, STATS_RDPC_ING, "RxIngDrop"), + MIB_DESC(1, STATS_RDPC_ARL, "RxARLDrop"), + MIB_DESC(1, STATS_RDPC_FC, "RxFCDrop"), + MIB_DESC(1, STATS_RDPC_WRED, "RxWREDDrop"), + MIB_DESC(1, STATS_RDPC_MIR, "RxMIRDrop"), + MIB_DESC(2, STATS_ROC2, "SecondaryRxByte"), + MIB_DESC(1, STATS_RSFSPC, "RxsFlowSampling"), + MIB_DESC(1, STATS_RSFTPC, "RxsFlowTotal"), + MIB_DESC(1, STATS_RXCDPC, "RxPortDrop"), +}; + +enum { + /* Global attributes. */ + AN8855_ATTR_ENABLE_VLAN, +}; + +static int an8855_get_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + + val->value.i = gsw->global_vlan_enable; + + return 0; +} + +static int an8855_set_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + + gsw->global_vlan_enable = val->value.i != 0; + + return 0; +} + +static int an8855_get_port_pvid(struct switch_dev *dev, int port, int *val) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + + if (port >= AN8855_NUM_PORTS) + return -EINVAL; + + *val = an8855_reg_read(gsw, PVID(port)); + *val &= GRP_PORT_VID_M; + + return 0; +} + +static int an8855_set_port_pvid(struct switch_dev *dev, int port, int pvid) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + + if (port >= AN8855_NUM_PORTS) + return -EINVAL; + + if (pvid < AN8855_MIN_VID || pvid > AN8855_MAX_VID) + return -EINVAL; + + gsw->port_entries[port].pvid = pvid; + + return 0; +} + +static int an8855_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + u32 member; + u32 etags; + int i; + + val->len = 0; + + if (val->port_vlan >= AN8855_NUM_VLANS) + return -EINVAL; + + an8855_vlan_ctrl(gsw, VTCR_READ_VLAN_ENTRY, val->port_vlan); + + member = an8855_reg_read(gsw, VARD0); + member &= PORT_MEM_M; + member >>= PORT_MEM_S; + member |= ((an8855_reg_read(gsw, VARD1) & 0x1) << 6); + + etags = an8855_reg_read(gsw, VARD0) & ETAG_M; + + for (i = 0; i < AN8855_NUM_PORTS; i++) { + struct switch_port *p; + int etag; + + if (!(member & BIT(i))) + continue; + + p = &val->value.ports[val->len++]; + p->id = i; + + etag = (etags >> PORT_ETAG_S(i)) & PORT_ETAG_M; + + if (etag == ETAG_CTRL_TAG) + p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED); + else if (etag != ETAG_CTRL_UNTAG) + dev_info(gsw->dev, + "vlan egress tag control neither untag nor tag.\n"); + } + + return 0; +} + +static int an8855_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + u8 member = 0; + u8 etags = 0; + int i; + + if (val->port_vlan >= AN8855_NUM_VLANS || + val->len > AN8855_NUM_PORTS) + return -EINVAL; + + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; + + if (p->id >= AN8855_NUM_PORTS) + return -EINVAL; + + member |= BIT(p->id); + + if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) + etags |= BIT(p->id); + } + + gsw->vlan_entries[val->port_vlan].member = member; + gsw->vlan_entries[val->port_vlan].etags = etags; + + return 0; +} + +static int an8855_set_vid(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + int vlan; + u16 vid; + + vlan = val->port_vlan; + vid = (u16)val->value.i; + + if (vlan < 0 || vlan >= AN8855_NUM_VLANS) + return -EINVAL; + + if (vid > AN8855_MAX_VID) + return -EINVAL; + + gsw->vlan_entries[vlan].vid = vid; + return 0; +} + +static int an8855_get_vid(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + val->value.i = val->port_vlan; + return 0; +} + +static int an8855_get_port_link(struct switch_dev *dev, int port, + struct switch_port_link *link) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + u32 speed, pmsr; + + if (port < 0 || port >= AN8855_NUM_PORTS) + return -EINVAL; + + pmsr = an8855_reg_read(gsw, PMSR(port)); + + link->link = pmsr & MAC_LNK_STS; + link->duplex = pmsr & MAC_DPX_STS; + speed = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S; + + switch (speed) { + case MAC_SPD_10: + link->speed = SWITCH_PORT_SPEED_10; + break; + case MAC_SPD_100: + link->speed = SWITCH_PORT_SPEED_100; + break; + case MAC_SPD_1000: + link->speed = SWITCH_PORT_SPEED_1000; + break; + case MAC_SPD_2500: + /* TODO: swconfig has no support for 2500 now */ + link->speed = SWITCH_PORT_SPEED_UNKNOWN; + break; + } + + return 0; +} + +static int an8855_set_port_link(struct switch_dev *dev, int port, + struct switch_port_link *link) +{ +#ifndef MODULE + if (port >= AN8855_NUM_PHYS) + return -EINVAL; + + return switch_generic_set_link(dev, port, link); +#else + return -ENOTSUPP; +#endif +} + +static u64 get_mib_counter(struct gsw_an8855 *gsw, int i, int port) +{ + unsigned int offset; + u64 lo, hi, hi2; + + offset = an8855_mibs[i].offset; + + if (an8855_mibs[i].size == 1) + return an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset)); + + do { + hi = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4)); + lo = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset)); + hi2 = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4)); + } while (hi2 != hi); + + return (hi << 32) | lo; +} + +static int an8855_get_port_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + static char buf[4096]; + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + int i, len = 0; + + if (val->port_vlan >= AN8855_NUM_PORTS) + return -EINVAL; + + len += snprintf(buf + len, sizeof(buf) - len, + "Port %d MIB counters\n", val->port_vlan); + + for (i = 0; i < ARRAY_SIZE(an8855_mibs); ++i) { + u64 counter; + + len += snprintf(buf + len, sizeof(buf) - len, + "%-11s: ", an8855_mibs[i].name); + counter = get_mib_counter(gsw, i, val->port_vlan); + len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", + counter); + } + + val->value.s = buf; + val->len = len; + return 0; +} + +static int an8855_get_port_stats(struct switch_dev *dev, int port, + struct switch_port_stats *stats) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + + if (port < 0 || port >= AN8855_NUM_PORTS) + return -EINVAL; + + stats->tx_bytes = get_mib_counter(gsw, AN8855_PORT_MIB_TXB_ID, port); + stats->rx_bytes = get_mib_counter(gsw, AN8855_PORT_MIB_RXB_ID, port); + + return 0; +} + +static void an8855_port_isolation(struct gsw_an8855 *gsw) +{ + int i; + + for (i = 0; i < AN8855_NUM_PORTS; i++) + an8855_reg_write(gsw, PORTMATRIX(i), + BIT(gsw->cpu_port)); + + an8855_reg_write(gsw, PORTMATRIX(gsw->cpu_port), PORT_MATRIX_M); + + for (i = 0; i < AN8855_NUM_PORTS; i++) { + u32 pvc_mode = 0x8100 << STAG_VPID_S; + + if (gsw->port5_cfg.stag_on && i == 5) + pvc_mode |= PVC_PORT_STAG | PVC_STAG_REPLACE; + else + pvc_mode |= (VA_TRANSPARENT_PORT << VLAN_ATTR_S); + + an8855_reg_write(gsw, PVC(i), pvc_mode); + } +} + +static int an8855_apply_config(struct switch_dev *dev) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + + if (!gsw->global_vlan_enable) { + an8855_port_isolation(gsw); + return 0; + } + + an8855_apply_vlan_config(gsw); + + return 0; +} + +static int an8855_reset_switch(struct switch_dev *dev) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + int i; + + memset(gsw->port_entries, 0, sizeof(gsw->port_entries)); + memset(gsw->vlan_entries, 0, sizeof(gsw->vlan_entries)); + + /* set default vid of each vlan to the same number of vlan, so the vid + * won't need be set explicitly. + */ + for (i = 0; i < AN8855_NUM_VLANS; i++) + gsw->vlan_entries[i].vid = i; + + return 0; +} + +static int an8855_phy_read16(struct switch_dev *dev, int addr, u8 reg, + u16 *value) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + + *value = gsw->mii_read(gsw, addr, reg); + + return 0; +} + +static int an8855_phy_write16(struct switch_dev *dev, int addr, u8 reg, + u16 value) +{ + struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev); + + gsw->mii_write(gsw, addr, reg, value); + + return 0; +} + +static const struct switch_attr an8855_global[] = { + { + .type = SWITCH_TYPE_INT, + .name = "enable_vlan", + .description = "VLAN mode (1:enabled)", + .max = 1, + .id = AN8855_ATTR_ENABLE_VLAN, + .get = an8855_get_vlan_enable, + .set = an8855_set_vlan_enable, + } +}; + +static const struct switch_attr an8855_port[] = { + { + .type = SWITCH_TYPE_STRING, + .name = "mib", + .description = "Get MIB counters for port", + .get = an8855_get_port_mib, + .set = NULL, + }, +}; + +static const struct switch_attr an8855_vlan[] = { + { + .type = SWITCH_TYPE_INT, + .name = "vid", + .description = "VLAN ID (0-4094)", + .set = an8855_set_vid, + .get = an8855_get_vid, + .max = 4094, + }, +}; + +static const struct switch_dev_ops an8855_swdev_ops = { + .attr_global = { + .attr = an8855_global, + .n_attr = ARRAY_SIZE(an8855_global), + }, + .attr_port = { + .attr = an8855_port, + .n_attr = ARRAY_SIZE(an8855_port), + }, + .attr_vlan = { + .attr = an8855_vlan, + .n_attr = ARRAY_SIZE(an8855_vlan), + }, + .get_vlan_ports = an8855_get_vlan_ports, + .set_vlan_ports = an8855_set_vlan_ports, + .get_port_pvid = an8855_get_port_pvid, + .set_port_pvid = an8855_set_port_pvid, + .get_port_link = an8855_get_port_link, + .set_port_link = an8855_set_port_link, + .get_port_stats = an8855_get_port_stats, + .apply_config = an8855_apply_config, + .reset_switch = an8855_reset_switch, + .phy_read16 = an8855_phy_read16, + .phy_write16 = an8855_phy_write16, +}; + +int an8855_swconfig_init(struct gsw_an8855 *gsw) +{ + struct device_node *np = gsw->dev->of_node; + struct switch_dev *swdev; + int ret; + + if (of_property_read_u32(np, "airoha,cpuport", &gsw->cpu_port)) + gsw->cpu_port = AN8855_DFL_CPU_PORT; + + swdev = &gsw->swdev; + + swdev->name = gsw->name; + swdev->alias = gsw->name; + swdev->cpu_port = gsw->cpu_port; + swdev->ports = AN8855_NUM_PORTS; + swdev->vlans = AN8855_NUM_VLANS; + swdev->ops = &an8855_swdev_ops; + + ret = register_switch(swdev, NULL); + if (ret) { + dev_notice(gsw->dev, "Failed to register switch %s\n", + swdev->name); + return ret; + } + + an8855_apply_config(swdev); + + return 0; +} + +void an8855_swconfig_destroy(struct gsw_an8855 *gsw) +{ + unregister_switch(&gsw->swdev); +} diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.h new file mode 100644 index 000000000..4c8f2bf6f --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023 Airoha Inc. + * Author: Min Yao + */ + +#ifndef _AN8855_SWCONFIG_H_ +#define _AN8855_SWCONFIG_H_ + +#ifdef CONFIG_SWCONFIG +#include +#include "an8855.h" + +int an8855_swconfig_init(struct gsw_an8855 *gsw); +void an8855_swconfig_destroy(struct gsw_an8855 *gsw); +#else +static inline int an8855_swconfig_init(struct gsw_an8855 *gsw) +{ + an8855_apply_vlan_config(gsw); + + return 0; +} + +static inline void an8855_swconfig_destroy(struct gsw_an8855 *gsw) +{ +} +#endif + +#endif /* _AN8855_SWCONFIG_H_ */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.c b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.c new file mode 100644 index 000000000..6ef8c9943 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 Airoha Inc. + */ + +#include "an8855.h" +#include "an8855_regs.h" + +struct an8855_mapping an8855_def_mapping[] = { + { + .name = "llllw", + .pvids = { 1, 1, 1, 1, 2, 1 }, + .members = { 0, 0x2f, 0x30 }, + .etags = { 0, 0, 0x20 }, + .vids = { 0, 1, 2 }, + }, { + .name = "wllll", + .pvids = { 2, 1, 1, 1, 1, 1 }, + .members = { 0, 0x3e, 0x21 }, + .etags = { 0, 0, 0x20 }, + .vids = { 0, 1, 2 }, + }, { + .name = "lwlll", + .pvids = { 1, 2, 1, 1, 1, 1 }, + .members = { 0, 0x3d, 0x22 }, + .etags = { 0, 0, 0x20 }, + .vids = { 0, 1, 2 }, + }, { + .name = "lllll", + .pvids = { 1, 1, 1, 1, 1, 1 }, + .members = { 0, 0x3f }, + .etags = { 0, 0 }, + .vids = { 0, 1 }, + }, +}; + +void an8855_vlan_ctrl(struct gsw_an8855 *gsw, u32 cmd, u32 val) +{ + int i; + + an8855_reg_write(gsw, VTCR, + VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) | + (val & VTCR_VID_M)); + + for (i = 0; i < 300; i++) { + u32 val = an8855_reg_read(gsw, VTCR); + + if ((val & VTCR_BUSY) == 0) + break; + + usleep_range(1000, 1100); + } + + if (i == 300) + dev_info(gsw->dev, "vtcr timeout\n"); +} + +static void an8855_write_vlan_entry(struct gsw_an8855 *gsw, int vlan, u16 vid, + u8 ports, u8 etags) +{ + int port; + u32 val; + + /* vlan port membership */ + if (ports) { + val = IVL_MAC | VTAG_EN | VENTRY_VALID + | ((ports << PORT_MEM_S) & PORT_MEM_M); + /* egress mode */ + for (port = 0; port < AN8855_NUM_PORTS; port++) { + if (etags & BIT(port)) + val |= (ETAG_CTRL_TAG << PORT_ETAG_S(port)); + else + val |= (ETAG_CTRL_UNTAG << PORT_ETAG_S(port)); + } + an8855_reg_write(gsw, VAWD0, val); + } else { + an8855_reg_write(gsw, VAWD0, 0); + } + + if (ports & 0x40) + an8855_reg_write(gsw, VAWD1, 0x1); + else + an8855_reg_write(gsw, VAWD1, 0x0); + + /* write to vlan table */ + an8855_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid); +} + +void an8855_apply_vlan_config(struct gsw_an8855 *gsw) +{ + int i, j; + u8 tag_ports; + u8 untag_ports; + u32 val; + + /* set all ports as security mode */ + for (i = 0; i < AN8855_NUM_PORTS; i++) { + val = an8855_reg_read(gsw, PCR(i)); + an8855_reg_write(gsw, PCR(i), val | SECURITY_MODE); + an8855_reg_write(gsw, PORTMATRIX(i), PORT_MATRIX_M); + } + + /* check if a port is used in tag/untag vlan egress mode */ + tag_ports = 0; + untag_ports = 0; + + for (i = 0; i < AN8855_NUM_VLANS; i++) { + u8 member = gsw->vlan_entries[i].member; + u8 etags = gsw->vlan_entries[i].etags; + + if (!member) + continue; + + for (j = 0; j < AN8855_NUM_PORTS; j++) { + if (!(member & BIT(j))) + continue; + + if (etags & BIT(j)) + tag_ports |= 1u << j; + else + untag_ports |= 1u << j; + } + } + + /* set all untag-only ports as transparent and the rest as user port */ + for (i = 0; i < AN8855_NUM_PORTS; i++) { + u32 pvc_mode = 0x8100 << STAG_VPID_S; + + if (untag_ports & BIT(i) && !(tag_ports & BIT(i))) + pvc_mode = (0x8100 << STAG_VPID_S) | + (VA_TRANSPARENT_PORT << VLAN_ATTR_S); + + if (gsw->port5_cfg.stag_on && i == 5) + pvc_mode = (u32)((0x8100 << STAG_VPID_S) | PVC_PORT_STAG + | PVC_STAG_REPLACE); + + an8855_reg_write(gsw, PVC(i), pvc_mode); + } + + /* first clear the switch vlan table */ + for (i = 0; i < AN8855_NUM_VLANS; i++) + an8855_write_vlan_entry(gsw, i, i, 0, 0); + + /* now program only vlans with members to avoid + * clobbering remapped entries in later iterations + */ + for (i = 0; i < AN8855_NUM_VLANS; i++) { + u16 vid = gsw->vlan_entries[i].vid; + u8 member = gsw->vlan_entries[i].member; + u8 etags = gsw->vlan_entries[i].etags; + + if (member) + an8855_write_vlan_entry(gsw, i, vid, member, etags); + } + + /* Port Default PVID */ + for (i = 0; i < AN8855_NUM_PORTS; i++) { + int vlan = gsw->port_entries[i].pvid; + u16 pvid = 0; + u32 val; + + if (vlan < AN8855_NUM_VLANS && gsw->vlan_entries[vlan].member) + pvid = gsw->vlan_entries[vlan].vid; + + val = an8855_reg_read(gsw, PVID(i)); + val &= ~GRP_PORT_VID_M; + val |= pvid; + an8855_reg_write(gsw, PVID(i), val); + } +} + +struct an8855_mapping *an8855_find_mapping(struct device_node *np) +{ + const char *map; + int i; + + if (of_property_read_string(np, "airoha,portmap", &map)) + return NULL; + + for (i = 0; i < ARRAY_SIZE(an8855_def_mapping); i++) + if (!strcmp(map, an8855_def_mapping[i].name)) + return &an8855_def_mapping[i]; + + return NULL; +} + +void an8855_apply_mapping(struct gsw_an8855 *gsw, struct an8855_mapping *map) +{ + int i = 0; + + for (i = 0; i < AN8855_NUM_PORTS; i++) + gsw->port_entries[i].pvid = map->pvids[i]; + + for (i = 0; i < AN8855_NUM_VLANS; i++) { + gsw->vlan_entries[i].member = map->members[i]; + gsw->vlan_entries[i].etags = map->etags[i]; + gsw->vlan_entries[i].vid = map->vids[i]; + } +} diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.h b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.h new file mode 100644 index 000000000..d2cd68ac7 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023 Airoha Inc. + */ + +#ifndef _AN8855_VLAN_H_ +#define _AN8855_VLAN_H_ + +#define AN8855_NUM_PORTS 6 +#define AN8855_NUM_VLANS 4095 +#define AN8855_MAX_VID 4095 +#define AN8855_MIN_VID 0 + +struct gsw_an8855; + +struct an8855_port_entry { + u16 pvid; +}; + +struct an8855_vlan_entry { + u16 vid; + u8 member; + u8 etags; +}; + +struct an8855_mapping { + char *name; + u16 pvids[AN8855_NUM_PORTS]; + u8 members[AN8855_NUM_VLANS]; + u8 etags[AN8855_NUM_VLANS]; + u16 vids[AN8855_NUM_VLANS]; +}; + +extern struct an8855_mapping an8855_defaults[]; + +void an8855_vlan_ctrl(struct gsw_an8855 *gsw, u32 cmd, u32 val); +void an8855_apply_vlan_config(struct gsw_an8855 *gsw); +struct an8855_mapping *an8855_find_mapping(struct device_node *np); +void an8855_apply_mapping(struct gsw_an8855 *gsw, struct an8855_mapping *map); +#endif /* _AN8855_VLAN_H_ */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/net/dsa/tag_arht.c b/feeds/mediatek-sdk/mediatek/files-5.4/net/dsa/tag_arht.c new file mode 100644 index 000000000..60ca9861d --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files-5.4/net/dsa/tag_arht.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Airoha DSA Tag support + * Copyright (C) 2023 Min Yao + */ + +#include +#include + +#include "dsa_priv.h" + +#define AIR_HDR_LEN 4 +#define AIR_HDR_XMIT_UNTAGGED 0 +#define AIR_HDR_XMIT_TAGGED_TPID_8100 1 +#define AIR_HDR_XMIT_TAGGED_TPID_88A8 2 +#define AIR_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0) +#define AIR_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0) + +static struct sk_buff *air_tag_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + u8 xmit_tpid; + u8 *air_tag; + unsigned char *dest = eth_hdr(skb)->h_dest; + + /* Build the special tag after the MAC Source Address. If VLAN header + * is present, it's required that VLAN header and special tag is + * being combined. Only in this way we can allow the switch can parse + * the both special and VLAN tag at the same time and then look up VLAN + * table with VID. + */ + switch (skb->protocol) { + case htons(ETH_P_8021Q): + xmit_tpid = AIR_HDR_XMIT_TAGGED_TPID_8100; + break; + case htons(ETH_P_8021AD): + xmit_tpid = AIR_HDR_XMIT_TAGGED_TPID_88A8; + break; + default: + if (skb_cow_head(skb, AIR_HDR_LEN) < 0) + return NULL; + + xmit_tpid = AIR_HDR_XMIT_UNTAGGED; + skb_push(skb, AIR_HDR_LEN); + memmove(skb->data, skb->data + AIR_HDR_LEN, 2 * ETH_ALEN); + } + + air_tag = skb->data + 2 * ETH_ALEN; + + /* Mark tag attribute on special tag insertion to notify hardware + * whether that's a combined special tag with 802.1Q header. + */ + air_tag[0] = xmit_tpid; + air_tag[1] = (1 << dp->index) & AIR_HDR_XMIT_DP_BIT_MASK; + + /* Tag control information is kept for 802.1Q */ + if (xmit_tpid == AIR_HDR_XMIT_UNTAGGED) { + air_tag[2] = 0; + air_tag[3] = 0; + } + + return skb; +} + +static struct sk_buff *air_tag_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) +{ + int port; + __be16 *phdr, hdr; + unsigned char *dest = eth_hdr(skb)->h_dest; + bool is_multicast_skb = is_multicast_ether_addr(dest) && + !is_broadcast_ether_addr(dest); + + if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) { + hdr = ntohs(skb->vlan_proto); + skb->vlan_proto = 0; + skb->vlan_tci = 0; + } else { + if (unlikely(!pskb_may_pull(skb, AIR_HDR_LEN))) + return NULL; + + /* The AIR header is added by the switch between src addr + * and ethertype at this point, skb->data points to 2 bytes + * after src addr so header should be 2 bytes right before. + */ + phdr = (__be16 *)(skb->data - 2); + hdr = ntohs(*phdr); + + /* Remove AIR tag and recalculate checksum. */ + skb_pull_rcsum(skb, AIR_HDR_LEN); + + memmove(skb->data - ETH_HLEN, + skb->data - ETH_HLEN - AIR_HDR_LEN, + 2 * ETH_ALEN); + } + + /* Get source port information */ + port = (hdr & AIR_HDR_RECV_SOURCE_PORT_MASK); + + skb->dev = dsa_master_find_slave(dev, 0, port); + if (!skb->dev) + return NULL; + + /* Only unicast or broadcast frames are offloaded */ + if (likely(!is_multicast_skb)) + skb->offload_fwd_mark = 1; + + return skb; +} + +static int air_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto, + int *offset) +{ + *offset = 4; + *proto = ((__be16 *)skb->data)[1]; + + return 0; +} + +static const struct dsa_device_ops air_netdev_ops = { + .name = "air", + .proto = DSA_TAG_PROTO_ARHT, + .xmit = air_tag_xmit, + .rcv = air_tag_rcv, + .flow_dissect = air_tag_flow_dissect, + .overhead = AIR_HDR_LEN, +}; + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_AIR); + +module_dsa_tag_driver(air_netdev_ops); diff --git a/feeds/mediatek-sdk/mediatek/files/block/partitions/fit.c b/feeds/mediatek-sdk/mediatek/files/block/partitions/fit.c deleted file mode 100644 index 91b25e058..000000000 --- a/feeds/mediatek-sdk/mediatek/files/block/partitions/fit.c +++ /dev/null @@ -1,303 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * fs/partitions/fit.c - * Copyright (C) 2021 Daniel Golle - * - * headers extracted from U-Boot mkimage sources - * (C) Copyright 2008 Semihalf - * (C) Copyright 2000-2005 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * based on existing partition parsers - * Copyright (C) 1991-1998 Linus Torvalds - * Re-organised Feb 1998 Russell King - */ - -#define pr_fmt(fmt) fmt - -#include -#include -#include -#include -#include -#include - -#include "check.h" - -#define FIT_IMAGES_PATH "/images" -#define FIT_CONFS_PATH "/configurations" - -/* hash/signature/key node */ -#define FIT_HASH_NODENAME "hash" -#define FIT_ALGO_PROP "algo" -#define FIT_VALUE_PROP "value" -#define FIT_IGNORE_PROP "uboot-ignore" -#define FIT_SIG_NODENAME "signature" -#define FIT_KEY_REQUIRED "required" -#define FIT_KEY_HINT "key-name-hint" - -/* cipher node */ -#define FIT_CIPHER_NODENAME "cipher" -#define FIT_ALGO_PROP "algo" - -/* image node */ -#define FIT_DATA_PROP "data" -#define FIT_DATA_POSITION_PROP "data-position" -#define FIT_DATA_OFFSET_PROP "data-offset" -#define FIT_DATA_SIZE_PROP "data-size" -#define FIT_TIMESTAMP_PROP "timestamp" -#define FIT_DESC_PROP "description" -#define FIT_ARCH_PROP "arch" -#define FIT_TYPE_PROP "type" -#define FIT_OS_PROP "os" -#define FIT_COMP_PROP "compression" -#define FIT_ENTRY_PROP "entry" -#define FIT_LOAD_PROP "load" - -/* configuration node */ -#define FIT_KERNEL_PROP "kernel" -#define FIT_FILESYSTEM_PROP "filesystem" -#define FIT_RAMDISK_PROP "ramdisk" -#define FIT_FDT_PROP "fdt" -#define FIT_LOADABLE_PROP "loadables" -#define FIT_DEFAULT_PROP "default" -#define FIT_SETUP_PROP "setup" -#define FIT_FPGA_PROP "fpga" -#define FIT_FIRMWARE_PROP "firmware" -#define FIT_STANDALONE_PROP "standalone" - -#define FIT_MAX_HASH_LEN HASH_MAX_DIGEST_SIZE - -#define MIN_FREE_SECT 16 -#define REMAIN_VOLNAME "rootfs_data" - -int parse_fit_partitions(struct parsed_partitions *state, u64 fit_start_sector, u64 sectors, int *slot, int add_remain) -{ - struct block_device *bdev = state->disk->part0; - struct address_space *mapping = bdev->bd_inode->i_mapping; - struct page *page; - void *fit, *init_fit; - struct partition_meta_info *info; - char tmp[sizeof(info->volname)]; - u64 dsize, dsectors, imgmaxsect = 0; - u32 size, image_pos, image_len; - const u32 *image_offset_be, *image_len_be, *image_pos_be; - int ret = 1, node, images, config; - const char *image_name, *image_type, *image_description, *config_default, - *config_description, *config_loadables, *bootconf_c; - int image_name_len, image_type_len, image_description_len, config_default_len, - config_description_len, config_loadables_len, bootconf_len; - sector_t start_sect, nr_sects; - size_t label_min; - struct device_node *np = NULL; - char *bootconf = NULL, *bootconf_term; - const char *loadable; - const char *select_rootfs = NULL; - bool found; - int loadables_rem_len, loadable_len; - - if (fit_start_sector % (1<<(PAGE_SHIFT - SECTOR_SHIFT))) - return -ERANGE; - - page = read_mapping_page(mapping, fit_start_sector >> (PAGE_SHIFT - SECTOR_SHIFT), NULL); - if (IS_ERR(page)) - return -EFAULT; - - if (PageError(page)) - return -EFAULT; - - init_fit = page_address(page); - - if (!init_fit) { - put_page(page); - return -EFAULT; - } - - if (fdt_check_header(init_fit)) { - put_page(page); - return 0; - } - - dsectors = get_capacity(bdev->bd_disk); - if (sectors) - dsectors = (dsectors>sectors)?sectors:dsectors; - - dsize = dsectors << SECTOR_SHIFT; - size = fdt_totalsize(init_fit); - - /* silently skip non-external-data legacy FIT images */ - if (size > PAGE_SIZE) { - put_page(page); - return 0; - } - - if (size >= dsize) { - state->access_beyond_eod = 1; - put_page(page); - return -EFBIG; - } - - fit = kmemdup(init_fit, size, GFP_KERNEL); - put_page(page); - if (!fit) - return -ENOMEM; - - np = of_find_node_by_path("/chosen"); - if (np) { - bootconf_c = of_get_property(np, "u-boot,bootconf", &bootconf_len); - if (bootconf_c && bootconf_len) - bootconf = kmemdup_nul(bootconf_c, bootconf_len, GFP_KERNEL); - } - - if (bootconf) { - bootconf_term = strchr(bootconf, '#'); - if (bootconf_term) - *bootconf_term = '\0'; - } - - config = fdt_path_offset(fit, FIT_CONFS_PATH); - if (config < 0) { - printk(KERN_ERR "FIT: Cannot find %s node: %d\n", FIT_CONFS_PATH, images); - ret = -ENOENT; - goto ret_out; - } - - config_default = fdt_getprop(fit, config, FIT_DEFAULT_PROP, &config_default_len); - - if (!config_default && !bootconf) { - printk(KERN_ERR "FIT: Cannot find default configuration\n"); - ret = -ENOENT; - goto ret_out; - } - - node = fdt_subnode_offset(fit, config, bootconf?:config_default); - if (node < 0) { - printk(KERN_ERR "FIT: Cannot find %s node: %d\n", bootconf?:config_default, node); - ret = -ENOENT; - goto ret_out; - } - - config_description = fdt_getprop(fit, node, FIT_DESC_PROP, &config_description_len); - config_loadables = fdt_getprop(fit, node, FIT_LOADABLE_PROP, &config_loadables_len); - - printk(KERN_DEBUG "FIT: %s configuration: \"%s\"%s%s%s\n", - bootconf?"Selected":"Default", bootconf?:config_default, - config_description?" (":"", config_description?:"", config_description?")":""); - - if (!config_loadables || !config_loadables_len) { - printk(KERN_ERR "FIT: No loadables configured in \"%s\"\n", bootconf?:config_default); - ret = -ENOENT; - goto ret_out; - } - - images = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (images < 0) { - printk(KERN_ERR "FIT: Cannot find %s node: %d\n", FIT_IMAGES_PATH, images); - ret = -EINVAL; - goto ret_out; - } - - fdt_for_each_subnode(node, fit, images) { - image_name = fdt_get_name(fit, node, &image_name_len); - image_type = fdt_getprop(fit, node, FIT_TYPE_PROP, &image_type_len); - image_offset_be = fdt_getprop(fit, node, FIT_DATA_OFFSET_PROP, NULL); - image_pos_be = fdt_getprop(fit, node, FIT_DATA_POSITION_PROP, NULL); - image_len_be = fdt_getprop(fit, node, FIT_DATA_SIZE_PROP, NULL); - if (!image_name || !image_type || !image_len_be) - continue; - - image_len = be32_to_cpu(*image_len_be); - if (!image_len) - continue; - - if (image_offset_be) - image_pos = be32_to_cpu(*image_offset_be) + size; - else if (image_pos_be) - image_pos = be32_to_cpu(*image_pos_be); - else - continue; - - image_description = fdt_getprop(fit, node, FIT_DESC_PROP, &image_description_len); - - printk(KERN_DEBUG "FIT: %16s sub-image 0x%08x..0x%08x \"%s\" %s%s%s\n", - image_type, image_pos, image_pos + image_len - 1, image_name, - image_description?"(":"", image_description?:"", image_description?") ":""); - - if (strcmp(image_type, FIT_FILESYSTEM_PROP)) - continue; - - /* check if sub-image is part of configured loadables */ - found = false; - loadable = config_loadables; - loadables_rem_len = config_loadables_len; - while (loadables_rem_len > 1) { - loadable_len = strnlen(loadable, loadables_rem_len - 1) + 1; - loadables_rem_len -= loadable_len; - if (!strncmp(image_name, loadable, loadable_len)) { - found = true; - break; - } - loadable += loadable_len; - } - if (!found) - continue; - - if (image_pos & ((1 << PAGE_SHIFT)-1)) { - printk(KERN_ERR "FIT: image %s start not aligned to page boundaries, skipping\n", image_name); - continue; - } - - if (image_len & ((1 << PAGE_SHIFT)-1)) { - printk(KERN_ERR "FIT: sub-image %s end not aligned to page boundaries, skipping\n", image_name); - continue; - } - - start_sect = image_pos >> SECTOR_SHIFT; - nr_sects = image_len >> SECTOR_SHIFT; - imgmaxsect = (imgmaxsect < (start_sect + nr_sects))?(start_sect + nr_sects):imgmaxsect; - - if (start_sect + nr_sects > dsectors) { - state->access_beyond_eod = 1; - continue; - } - - put_partition(state, ++(*slot), fit_start_sector + start_sect, nr_sects); - state->parts[*slot].flags = ADDPART_FLAG_READONLY; - state->parts[*slot].has_info = true; - info = &state->parts[*slot].info; - - label_min = min_t(int, sizeof(info->volname) - 1, image_name_len); - strncpy(info->volname, image_name, label_min); - info->volname[label_min] = '\0'; - - snprintf(tmp, sizeof(tmp), "(%s)", info->volname); - strlcat(state->pp_buf, tmp, PAGE_SIZE); - - /* Mark first loadable listed to be mounted as rootfs */ - if (!strcmp(image_name, config_loadables)) { - select_rootfs = image_name; - state->parts[*slot].flags |= ADDPART_FLAG_ROOTDEV; - } - } - - if (select_rootfs) - printk(KERN_DEBUG "FIT: selecting configured loadable \"%s\" to be root filesystem\n", select_rootfs); - - if (add_remain && (imgmaxsect + MIN_FREE_SECT) < dsectors) { - put_partition(state, ++(*slot), fit_start_sector + imgmaxsect, dsectors - imgmaxsect); - state->parts[*slot].flags = 0; - info = &state->parts[*slot].info; - strcpy(info->volname, REMAIN_VOLNAME); - snprintf(tmp, sizeof(tmp), "(%s)", REMAIN_VOLNAME); - strlcat(state->pp_buf, tmp, PAGE_SIZE); - } -ret_out: - kfree(bootconf); - kfree(fit); - return ret; -} - -int fit_partition(struct parsed_partitions *state) { - int slot = 0; - return parse_fit_partitions(state, 0, 0, &slot, 0); -} diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/bcma/fallback-sprom.c b/feeds/mediatek-sdk/mediatek/files/drivers/bcma/fallback-sprom.c deleted file mode 100644 index ce93560a4..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/bcma/fallback-sprom.c +++ /dev/null @@ -1,533 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * BCMA Fallback SPROM Driver - * - * Copyright (C) 2020 Álvaro Fernández Rojas - * Copyright (C) 2014 Jonas Gorski - * Copyright (C) 2008 Maxime Bizon - * Copyright (C) 2008 Florian Fainelli - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define BCMA_FBS_MAX_SIZE 468 - -/* SPROM Extraction */ -#define SPOFF(offset) ((offset) / sizeof(u16)) - -#define SPEX(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) - -#define SPEX32(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \ - in[SPOFF(_offset)]) & (_mask)) >> (_shift)) - -#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \ - do { \ - SPEX(_field[0], _offset + 0, _mask, _shift); \ - SPEX(_field[1], _offset + 2, _mask, _shift); \ - SPEX(_field[2], _offset + 4, _mask, _shift); \ - SPEX(_field[3], _offset + 6, _mask, _shift); \ - SPEX(_field[4], _offset + 8, _mask, _shift); \ - SPEX(_field[5], _offset + 10, _mask, _shift); \ - SPEX(_field[6], _offset + 12, _mask, _shift); \ - SPEX(_field[7], _offset + 14, _mask, _shift); \ - } while (0) - -struct bcma_fbs { - struct device *dev; - struct list_head list; - struct ssb_sprom sprom; - u32 pci_bus; - u32 pci_dev; - bool devid_override; -}; - -static DEFINE_SPINLOCK(bcma_fbs_lock); -static struct list_head bcma_fbs_list = LIST_HEAD_INIT(bcma_fbs_list); - -int bcma_get_fallback_sprom(struct bcma_bus *bus, struct ssb_sprom *out) -{ - struct bcma_fbs *pos; - u32 pci_bus, pci_dev; - - if (bus->hosttype != BCMA_HOSTTYPE_PCI) - return -ENOENT; - - pci_bus = bus->host_pci->bus->number; - pci_dev = PCI_SLOT(bus->host_pci->devfn); - - list_for_each_entry(pos, &bcma_fbs_list, list) { - if (pos->pci_bus != pci_bus || - pos->pci_dev != pci_dev) - continue; - - if (pos->devid_override) - bus->host_pci->device = pos->sprom.dev_id; - - memcpy(out, &pos->sprom, sizeof(struct ssb_sprom)); - dev_info(pos->dev, "requested by [%x:%x]", - pos->pci_bus, pos->pci_dev); - - return 0; - } - - pr_err("unable to fill SPROM for [%x:%x]\n", pci_bus, pci_dev); - - return -EINVAL; -} - -static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift) -{ - u16 v; - u8 gain; - - v = in[SPOFF(offset)]; - gain = (v & mask) >> shift; - if (gain == 0xFF) { - gain = 8; /* If unset use 2dBm */ - } else { - /* Q5.2 Fractional part is stored in 0xC0 */ - gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); - } - - return (s8)gain; -} - -static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) -{ - static const u16 pwr_info_offset[] = { - SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, - SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 - }; - u16 o; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != - ARRAY_SIZE(out->core_pwr_info)); - - SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); - SPEX(board_type, SSB_SPROM1_SPID, ~0, 0); - - SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, - SSB_SPROM4_TXPID2G0_SHIFT); - SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1, - SSB_SPROM4_TXPID2G1_SHIFT); - SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G2, - SSB_SPROM4_TXPID2G2_SHIFT); - SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G3, - SSB_SPROM4_TXPID2G3_SHIFT); - - SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL0, - SSB_SPROM4_TXPID5GL0_SHIFT); - SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL1, - SSB_SPROM4_TXPID5GL1_SHIFT); - SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL2, - SSB_SPROM4_TXPID5GL2_SHIFT); - SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL3, - SSB_SPROM4_TXPID5GL3_SHIFT); - - SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G0, - SSB_SPROM4_TXPID5G0_SHIFT); - SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G1, - SSB_SPROM4_TXPID5G1_SHIFT); - SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G2, - SSB_SPROM4_TXPID5G2_SHIFT); - SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G3, - SSB_SPROM4_TXPID5G3_SHIFT); - - SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH0, - SSB_SPROM4_TXPID5GH0_SHIFT); - SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH1, - SSB_SPROM4_TXPID5GH1_SHIFT); - SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH2, - SSB_SPROM4_TXPID5GH2_SHIFT); - SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH3, - SSB_SPROM4_TXPID5GH3_SHIFT); - - SPEX(boardflags_lo, SSB_SPROM8_BFLLO, ~0, 0); - SPEX(boardflags_hi, SSB_SPROM8_BFLHI, ~0, 0); - SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0); - SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0); - - SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); - - /* Extract core's power info */ - for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { - o = pwr_info_offset[i]; - SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI, - SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI, - SSB_SPROM8_2G_MAXP, 0); - - SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0); - - SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI, - SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI, - SSB_SPROM8_5G_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP, - SSB_SPROM8_5GH_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP, - SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT); - - SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0); - } - - SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS, - SSB_SROM8_FEM_TSSIPOS_SHIFT); - SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN, - SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); - SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE, - SSB_SROM8_FEM_PDET_RANGE_SHIFT); - SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO, - SSB_SROM8_FEM_TR_ISO_SHIFT); - SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT, - SSB_SROM8_FEM_ANTSWLUT_SHIFT); - - SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS, - SSB_SROM8_FEM_TSSIPOS_SHIFT); - SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN, - SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); - SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE, - SSB_SROM8_FEM_PDET_RANGE_SHIFT); - SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO, - SSB_SROM8_FEM_TR_ISO_SHIFT); - SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT, - SSB_SROM8_FEM_ANTSWLUT_SHIFT); - - SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, - SSB_SPROM8_ANTAVAIL_A_SHIFT); - SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, - SSB_SPROM8_ANTAVAIL_BG_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); - SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, - SSB_SPROM8_ITSSI_BG_SHIFT); - SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); - SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, - SSB_SPROM8_ITSSI_A_SHIFT); - SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); - SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, - SSB_SPROM8_MAXP_AL_SHIFT); - SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, - SSB_SPROM8_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, - SSB_SPROM8_GPIOB_P3_SHIFT); - SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); - SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, - SSB_SPROM8_TRI5G_SHIFT); - SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); - SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, - SSB_SPROM8_TRI5GH_SHIFT); - SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, - SSB_SPROM8_RXPO2G_SHIFT); - SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, - SSB_SPROM8_RXPO5G_SHIFT); - SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); - SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, - SSB_SPROM8_RSSISMC2G_SHIFT); - SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, - SSB_SPROM8_RSSISAV2G_SHIFT); - SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, - SSB_SPROM8_BXA2G_SHIFT); - SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); - SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, - SSB_SPROM8_RSSISMC5G_SHIFT); - SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, - SSB_SPROM8_RSSISAV5G_SHIFT); - SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, - SSB_SPROM8_BXA5G_SHIFT); - - SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0); - SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0); - SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0); - SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0); - SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0); - SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0); - SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0); - SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0); - SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0); - SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0); - SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0); - SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0); - SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0); - SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0); - SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0); - SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0); - SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); - - /* Extract the antenna gain values. */ - out->antenna_gain.a0 = sprom_extract_antgain(in, - SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN0, - SSB_SPROM8_AGAIN0_SHIFT); - out->antenna_gain.a1 = sprom_extract_antgain(in, - SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN1, - SSB_SPROM8_AGAIN1_SHIFT); - out->antenna_gain.a2 = sprom_extract_antgain(in, - SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN2, - SSB_SPROM8_AGAIN2_SHIFT); - out->antenna_gain.a3 = sprom_extract_antgain(in, - SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN3, - SSB_SPROM8_AGAIN3_SHIFT); - - SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, - SSB_SPROM8_LEDDC_ON_SHIFT); - SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF, - SSB_SPROM8_LEDDC_OFF_SHIFT); - - SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN, - SSB_SPROM8_TXRXC_TXCHAIN_SHIFT); - SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN, - SSB_SPROM8_TXRXC_RXCHAIN_SHIFT); - SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH, - SSB_SPROM8_TXRXC_SWITCH_SHIFT); - - SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0); - - SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0); - - SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP, - SSB_SPROM8_RAWTS_RAWTEMP_SHIFT); - SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER, - SSB_SPROM8_RAWTS_MEASPOWER_SHIFT); - SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX, - SSB_SPROM8_OPT_CORRX_TEMP_SLOPE, - SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT); - SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX, - SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT); - SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX, - SSB_SPROM8_OPT_CORRX_TEMP_OPTION, - SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT); - SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP, - SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR, - SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT); - SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP, - SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP, - SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT); - SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL, - SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT); - - SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0); - SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0); - SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0); - SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0); - - SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH, - SSB_SPROM8_THERMAL_TRESH_SHIFT); - SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET, - SSB_SPROM8_THERMAL_OFFSET_SHIFT); - SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA, - SSB_SPROM8_TEMPDELTA_PHYCAL, - SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT); - SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD, - SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT); - SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA, - SSB_SPROM8_TEMPDELTA_HYSTERESIS, - SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT); -} - -static int sprom_extract(struct bcma_fbs *priv, const u16 *in, u16 size) -{ - struct ssb_sprom *out = &priv->sprom; - - memset(out, 0, sizeof(*out)); - - out->revision = in[size - 1] & 0x00FF; - if (out->revision < 8 || out->revision > 11) { - dev_warn(priv->dev, - "Unsupported SPROM revision %d detected." - " Will extract v8\n", - out->revision); - out->revision = 8; - } - - sprom_extract_r8(out, in); - - return 0; -} - -static void bcma_fbs_fixup(struct bcma_fbs *priv, u16 *sprom) -{ - struct device_node *node = priv->dev->of_node; - u32 fixups, off, val; - int i = 0; - - if (!of_get_property(node, "brcm,sprom-fixups", &fixups)) - return; - - fixups /= sizeof(u32); - - dev_info(priv->dev, "patching SPROM with %u fixups...\n", fixups >> 1); - - while (i < fixups) { - if (of_property_read_u32_index(node, "brcm,sprom-fixups", - i++, &off)) { - dev_err(priv->dev, "error reading fixup[%u] offset\n", - i - 1); - return; - } - - if (of_property_read_u32_index(node, "brcm,sprom-fixups", - i++, &val)) { - dev_err(priv->dev, "error reading fixup[%u] value\n", - i - 1); - return; - } - - dev_dbg(priv->dev, "fixup[%d]=0x%04x\n", off, val); - - sprom[off] = val; - } -} - -static bool sprom_override_devid(struct bcma_fbs *priv, struct ssb_sprom *out, - const u16 *in) -{ - SPEX(dev_id, 0x0060, 0xFFFF, 0); - return !!out->dev_id; -} - -static void bcma_fbs_set(struct bcma_fbs *priv, struct device_node *node) -{ - struct ssb_sprom *sprom = &priv->sprom; - const struct firmware *fw; - const char *sprom_name; - int err; - - if (of_property_read_string(node, "brcm,sprom", &sprom_name)) - sprom_name = NULL; - - if (sprom_name) { - err = request_firmware_direct(&fw, sprom_name, priv->dev); - if (err) - dev_err(priv->dev, "%s load error\n", sprom_name); - } else { - err = -ENOENT; - } - - if (err) { - sprom->revision = 0x02; - sprom->board_rev = 0x0017; - sprom->country_code = 0x00; - sprom->ant_available_bg = 0x03; - sprom->pa0b0 = 0x15ae; - sprom->pa0b1 = 0xfa85; - sprom->pa0b2 = 0xfe8d; - sprom->pa1b0 = 0xffff; - sprom->pa1b1 = 0xffff; - sprom->pa1b2 = 0xffff; - sprom->gpio0 = 0xff; - sprom->gpio1 = 0xff; - sprom->gpio2 = 0xff; - sprom->gpio3 = 0xff; - sprom->maxpwr_bg = 0x4c; - sprom->itssi_bg = 0x00; - sprom->boardflags_lo = 0x2848; - sprom->boardflags_hi = 0x0000; - priv->devid_override = false; - - dev_warn(priv->dev, "using basic SPROM\n"); - } else { - size_t size = min(fw->size, (size_t) BCMA_FBS_MAX_SIZE); - u16 tmp_sprom[BCMA_FBS_MAX_SIZE >> 1]; - u32 i, j; - - for (i = 0, j = 0; i < size; i += 2, j++) - tmp_sprom[j] = (fw->data[i] << 8) | fw->data[i + 1]; - - release_firmware(fw); - bcma_fbs_fixup(priv, tmp_sprom); - sprom_extract(priv, tmp_sprom, size >> 1); - - priv->devid_override = sprom_override_devid(priv, sprom, - tmp_sprom); - } -} - -static int bcma_fbs_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; - struct bcma_fbs *priv; - unsigned long flags; - u8 mac[ETH_ALEN]; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->dev = dev; - - bcma_fbs_set(priv, node); - - of_property_read_u32(node, "pci-bus", &priv->pci_bus); - of_property_read_u32(node, "pci-dev", &priv->pci_dev); - - of_get_mac_address(node, mac); - if (is_valid_ether_addr(mac)) { - dev_info(dev, "mtd mac %pM\n", mac); - } else { - random_ether_addr(mac); - dev_info(dev, "random mac %pM\n", mac); - } - - memcpy(priv->sprom.il0mac, mac, ETH_ALEN); - memcpy(priv->sprom.et0mac, mac, ETH_ALEN); - memcpy(priv->sprom.et1mac, mac, ETH_ALEN); - memcpy(priv->sprom.et2mac, mac, ETH_ALEN); - - spin_lock_irqsave(&bcma_fbs_lock, flags); - list_add(&priv->list, &bcma_fbs_list); - spin_unlock_irqrestore(&bcma_fbs_lock, flags); - - dev_info(dev, "registered SPROM for [%x:%x]\n", - priv->pci_bus, priv->pci_dev); - - return 0; -} - -static const struct of_device_id bcma_fbs_of_match[] = { - { .compatible = "brcm,bcma-sprom", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, bcma_fbs_of_match); - -static struct platform_driver bcma_fbs_driver = { - .probe = bcma_fbs_probe, - .driver = { - .name = "bcma-sprom", - .of_match_table = bcma_fbs_of_match, - }, -}; - -int __init bcma_fbs_register(void) -{ - return platform_driver_register(&bcma_fbs_driver); -} diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/Kconfig b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/Kconfig index f1864d8fd..4832b8d9e 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/Kconfig +++ b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/Kconfig @@ -12,6 +12,7 @@ config MTD_SPLIT_SQUASHFS_ROOT bool "Squashfs based root partition parser" depends on MTD_SPLIT_SUPPORT select MTD_SPLIT + default n help This provides a parsing function which allows to detect the offset and size of the unused portion of a rootfs partition @@ -19,11 +20,6 @@ config MTD_SPLIT_SQUASHFS_ROOT comment "Firmware partition parsers" -config MTD_SPLIT_BCM63XX_FW - bool "BCM63xx firmware parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - config MTD_SPLIT_BCM_WFI_FW bool "Broadcom Whole Flash Image parser" depends on MTD_SPLIT_SUPPORT @@ -100,8 +96,3 @@ config MTD_SPLIT_ELF_FW bool "ELF loader firmware partition parser" depends on MTD_SPLIT_SUPPORT select MTD_SPLIT - -config MTD_SPLIT_H3C_VFS - bool "Parser finding rootfs appended to H3C VFS" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/Makefile b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/Makefile index a969c336a..9217d8f64 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/Makefile +++ b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/Makefile @@ -1,5 +1,4 @@ obj-$(CONFIG_MTD_SPLIT) += mtdsplit.o -obj-$(CONFIG_MTD_SPLIT_BCM63XX_FW) += mtdsplit_bcm63xx.o obj-$(CONFIG_MTD_SPLIT_BCM_WFI_FW) += mtdsplit_bcm_wfi.o obj-$(CONFIG_MTD_SPLIT_CFE_BOOTFS) += mtdsplit_cfe_bootfs.o obj-$(CONFIG_MTD_SPLIT_SEAMA_FW) += mtdsplit_seama.o @@ -15,4 +14,3 @@ obj-$(CONFIG_MTD_SPLIT_WRGG_FW) += mtdsplit_wrgg.o obj-$(CONFIG_MTD_SPLIT_MINOR_FW) += mtdsplit_minor.o obj-$(CONFIG_MTD_SPLIT_JIMAGE_FW) += mtdsplit_jimage.o obj-$(CONFIG_MTD_SPLIT_ELF_FW) += mtdsplit_elf.o -obj-$(CONFIG_MTD_SPLIT_H3C_VFS) += mtdsplit_h3c_vfs.o diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c deleted file mode 100644 index 3a4b8a754..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Firmware MTD split for BCM63XX, based on bcm63xxpart.c - * - * Copyright (C) 2006-2008 Florian Fainelli - * Copyright (C) 2006-2008 Mike Albon - * Copyright (C) 2009-2010 Daniel Dickinson - * Copyright (C) 2011-2013 Jonas Gorski - * Copyright (C) 2015 Simon Arlott - * Copyright (C) 2017 Álvaro Fernández Rojas - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -/* Ensure strings read from flash structs are null terminated */ -#define STR_NULL_TERMINATE(x) \ - do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0) - -#define BCM63XX_NR_PARTS 2 - -static int bcm63xx_read_image_tag(struct mtd_info *master, loff_t offset, - struct bcm_tag *hdr) -{ - int ret; - size_t retlen; - u32 computed_crc; - - ret = mtd_read(master, offset, sizeof(*hdr), &retlen, (void *) hdr); - if (ret) - return ret; - - if (retlen != sizeof(*hdr)) - return -EIO; - - computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)hdr, - offsetof(struct bcm_tag, header_crc)); - if (computed_crc == hdr->header_crc) { - STR_NULL_TERMINATE(hdr->board_id); - STR_NULL_TERMINATE(hdr->tag_version); - - pr_info("CFE image tag found at 0x%llx with version %s, " - "board type %s\n", offset, hdr->tag_version, - hdr->board_id); - - return 0; - } else { - pr_err("CFE image tag at 0x%llx CRC invalid " - "(expected %08x, actual %08x)\n", - offset, hdr->header_crc, computed_crc); - - return 1; - } -} - -static int bcm63xx_parse_partitions(struct mtd_info *master, - const struct mtd_partition **pparts, - struct bcm_tag *hdr) -{ - struct mtd_partition *parts; - unsigned int flash_image_start; - unsigned int kernel_address; - unsigned int kernel_length; - size_t kernel_offset = 0, kernel_size = 0; - size_t rootfs_offset = 0, rootfs_size = 0; - int kernel_part, rootfs_part; - - STR_NULL_TERMINATE(hdr->flash_image_start); - if (kstrtouint(hdr->flash_image_start, 10, &flash_image_start) || - flash_image_start < BCM963XX_EXTENDED_SIZE) { - pr_err("invalid rootfs address: %*ph\n", - (int) sizeof(hdr->flash_image_start), - hdr->flash_image_start); - return -EINVAL; - } - - STR_NULL_TERMINATE(hdr->kernel_address); - if (kstrtouint(hdr->kernel_address, 10, &kernel_address) || - kernel_address < BCM963XX_EXTENDED_SIZE) { - pr_err("invalid kernel address: %*ph\n", - (int) sizeof(hdr->kernel_address), hdr->kernel_address); - return -EINVAL; - } - - STR_NULL_TERMINATE(hdr->kernel_length); - if (kstrtouint(hdr->kernel_length, 10, &kernel_length) || - !kernel_length) { - pr_err("invalid kernel length: %*ph\n", - (int) sizeof(hdr->kernel_length), hdr->kernel_length); - return -EINVAL; - } - - kernel_offset = kernel_address - BCM963XX_EXTENDED_SIZE - - mtdpart_get_offset(master); - kernel_size = kernel_length; - - if (flash_image_start < kernel_address) { - /* rootfs first */ - rootfs_part = 0; - kernel_part = 1; - rootfs_offset = flash_image_start - BCM963XX_EXTENDED_SIZE - - mtdpart_get_offset(master); - rootfs_size = kernel_offset - rootfs_offset; - } else { - /* kernel first */ - kernel_part = 0; - rootfs_part = 1; - rootfs_offset = kernel_offset + kernel_size; - rootfs_size = master->size - rootfs_offset; - } - - if (mtd_check_rootfs_magic(master, rootfs_offset, NULL)) - pr_warn("rootfs magic not found\n"); - - parts = kzalloc(BCM63XX_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[kernel_part].name = KERNEL_PART_NAME; - parts[kernel_part].offset = kernel_offset; - parts[kernel_part].size = kernel_size; - - parts[rootfs_part].name = ROOTFS_PART_NAME; - parts[rootfs_part].offset = rootfs_offset; - parts[rootfs_part].size = rootfs_size; - - *pparts = parts; - return BCM63XX_NR_PARTS; -} - -static int mtdsplit_parse_bcm63xx(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct bcm_tag hdr; - loff_t offset; - - if (mtd_type_is_nand(master)) - return -EINVAL; - - /* find bcm63xx_cfe image on erase block boundaries */ - for (offset = 0; offset < master->size; offset += master->erasesize) { - if (!bcm63xx_read_image_tag(master, offset, (void *) &hdr)) - return bcm63xx_parse_partitions(master, pparts, - (void *) &hdr); - } - - return -EINVAL; -} - -static const struct of_device_id mtdsplit_fit_of_match_table[] = { - { .compatible = "brcm,bcm963xx-imagetag" }, - { }, -}; - -static struct mtd_part_parser mtdsplit_bcm63xx_parser = { - .owner = THIS_MODULE, - .name = "bcm63xx-fw", - .of_match_table = mtdsplit_fit_of_match_table, - .parse_fn = mtdsplit_parse_bcm63xx, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_bcm63xx_init(void) -{ - register_mtd_parser(&mtdsplit_bcm63xx_parser); - - return 0; -} - -module_init(mtdsplit_bcm63xx_init); diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_fit.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_fit.c index 3b71597d2..67ee33d08 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_fit.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_fit.c @@ -21,204 +21,47 @@ #include #include #include -#include #include #include "mtdsplit.h" -// string macros from git://git.denx.de/u-boot.git/include/image.h +struct fdt_header { + uint32_t magic; /* magic word FDT_MAGIC */ + uint32_t totalsize; /* total size of DT block */ + uint32_t off_dt_struct; /* offset to structure */ + uint32_t off_dt_strings; /* offset to strings */ + uint32_t off_mem_rsvmap; /* offset to memory reserve map */ + uint32_t version; /* format version */ + uint32_t last_comp_version; /* last compatible version */ -#define FIT_IMAGES_PATH "/images" -#define FIT_DATA_PROP "data" -#define FIT_DATA_POSITION_PROP "data-position" -#define FIT_DATA_OFFSET_PROP "data-offset" -#define FIT_DATA_SIZE_PROP "data-size" + /* version 2 fields below */ + uint32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + uint32_t size_dt_strings; /* size of the strings block */ -// functions from git://git.denx.de/u-boot.git/common/image-fit.c - -/** - * fit_image_get_data - get data property and its size for a given component image node - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @data: double pointer to void, will hold data property's data address - * @size: pointer to size_t, will hold data property's data size - * - * fit_image_get_data() finds data property in a given component image node. - * If the property is found its data start address and size are returned to - * the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -static int fit_image_get_data(const void *fit, int noffset, - const void **data, size_t *size) -{ - int len; - - *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len); - if (*data == NULL) { - *size = 0; - return -1; - } - - *size = len; - return 0; -} - - -/** - * Get 'data-offset' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_offset: holds the data-offset property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -static int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL); - if (!val) - return -ENOENT; - - *data_offset = fdt32_to_cpu(*val); - - return 0; -} - -/** - * Get 'data-position' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_position: holds the data-position property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -static int fit_image_get_data_position(const void *fit, int noffset, - int *data_position) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL); - if (!val) - return -ENOENT; - - *data_position = fdt32_to_cpu(*val); - - return 0; -} - -/** - * Get 'data-size' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_size: holds the data-size property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -static int fit_image_get_data_size(const void *fit, int noffset, int *data_size) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL); - if (!val) - return -ENOENT; - - *data_size = fdt32_to_cpu(*val); - - return 0; -} - -/** - * fit_image_get_data_and_size - get data and its size including - * both embedded and external data - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @data: double pointer to void, will hold data property's data address - * @size: pointer to size_t, will hold data property's data size - * - * fit_image_get_data_and_size() finds data and its size including - * both embedded and external data. If the property is found - * its data start address and size are returned to the caller. - * - * returns: - * 0, on success - * otherwise, on failure - */ -static int fit_image_get_data_and_size(const void *fit, int noffset, - const void **data, size_t *size) -{ - bool external_data = false; - int offset; - int len; - int ret; - - if (!fit_image_get_data_position(fit, noffset, &offset)) { - external_data = true; - } else if (!fit_image_get_data_offset(fit, noffset, &offset)) { - external_data = true; - /* - * For FIT with external data, figure out where - * the external images start. This is the base - * for the data-offset properties in each image. - */ - offset += ((fdt_totalsize(fit) + 3) & ~3); - } - - if (external_data) { - ret = fit_image_get_data_size(fit, noffset, &len); - if (!ret) { - *data = fit + offset; - *size = len; - } - } else { - ret = fit_image_get_data(fit, noffset, data, size); - } - - return ret; -} + /* version 17 fields below */ + uint32_t size_dt_struct; /* size of the structure block */ +}; static int mtdsplit_fit_parse(struct mtd_info *mtd, const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { - struct device_node *np = mtd_get_of_node(mtd); - const char *cmdline_match = NULL; struct fdt_header hdr; size_t hdr_len, retlen; size_t offset; - u32 offset_start = 0; size_t fit_offset, fit_size; size_t rootfs_offset, rootfs_size; - size_t data_size, img_total, max_size = 0; struct mtd_partition *parts; - int ret, ndepth, noffset, images_noffset; - const void *img_data; - void *fit; - - of_property_read_string(np, "openwrt,cmdline-match", &cmdline_match); - if (cmdline_match && !strstr(saved_command_line, cmdline_match)) - return -ENODEV; - - of_property_read_u32(np, "openwrt,fit-offset", &offset_start); + int ret; hdr_len = sizeof(struct fdt_header); /* Parse the MTD device & search for the FIT image location */ for(offset = 0; offset + hdr_len <= mtd->size; offset += mtd->erasesize) { - ret = mtd_read(mtd, offset + offset_start, hdr_len, &retlen, (void*) &hdr); + ret = mtd_read(mtd, offset, hdr_len, &retlen, (void*) &hdr); if (ret) { pr_err("read error in \"%s\" at offset 0x%llx\n", mtd->name, (unsigned long long) offset); @@ -250,92 +93,31 @@ mtdsplit_fit_parse(struct mtd_info *mtd, return -ENODEV; } - /* - * Classic uImage.FIT has all data embedded into the FDT - * data structure. Hence the total size of the image equals - * the total size of the FDT structure. - * Modern uImage.FIT may have only references to data in FDT, - * hence we need to parse FDT structure to find the end of the - * last external data refernced. - */ - if (fit_size > 0x1000) { - enum mtdsplit_part_type type; - - /* Search for the rootfs partition after the FIT image */ - ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size + offset_start, mtd->size, - &rootfs_offset, &type); - if (ret) { - pr_info("no rootfs found after FIT image in \"%s\"\n", - mtd->name); - return ret; - } - - rootfs_size = mtd->size - rootfs_offset; - - parts = kzalloc(2 * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = fit_offset; - parts[0].size = mtd_rounddown_to_eb(fit_size + offset_start, mtd) + mtd->erasesize; - - if (type == MTDSPLIT_PART_TYPE_UBI) - parts[1].name = UBI_PART_NAME; - else - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = rootfs_size; - - *pparts = parts; - - return 2; - } else { - /* Search for rootfs_data after FIT external data */ - fit = kzalloc(fit_size, GFP_KERNEL); - ret = mtd_read(mtd, offset, fit_size + offset_start, &retlen, fit); - if (ret) { - pr_err("read error in \"%s\" at offset 0x%llx\n", - mtd->name, (unsigned long long) offset); - return ret; - } - - images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (images_noffset < 0) { - pr_err("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); - return -ENODEV; - } - - for (ndepth = 0, - noffset = fdt_next_node(fit, images_noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - if (ndepth == 1) { - ret = fit_image_get_data_and_size(fit, noffset, &img_data, &data_size); - if (ret) - return 0; - - img_total = data_size + (img_data - fit); - - max_size = (max_size > img_total) ? max_size : img_total; - } - } - - parts = kzalloc(sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = ROOTFS_SPLIT_NAME; - parts[0].offset = fit_offset + mtd_rounddown_to_eb(max_size, mtd) + mtd->erasesize; - parts[0].size = mtd->size - parts[0].offset; - - *pparts = parts; - - kfree(fit); - - return 1; + /* Search for the rootfs partition after the FIT image */ + ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size, mtd->size, + &rootfs_offset, NULL); + if (ret) { + pr_info("no rootfs found after FIT image in \"%s\"\n", + mtd->name); + return ret; } + + rootfs_size = mtd->size - rootfs_offset; + + parts = kzalloc(2 * sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + + parts[0].name = KERNEL_PART_NAME; + parts[0].offset = fit_offset; + parts[0].size = mtd_rounddown_to_eb(fit_size, mtd) + mtd->erasesize; + + parts[1].name = ROOTFS_PART_NAME; + parts[1].offset = rootfs_offset; + parts[1].size = rootfs_size; + + *pparts = parts; + return 2; } static const struct of_device_id mtdsplit_fit_of_match_table[] = { diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c deleted file mode 100644 index f264233db..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c +++ /dev/null @@ -1,170 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Some devices made by H3C use a "VFS" filesystem to store firmware images. - * This parses the start of the filesystem to read the length of the first - * file (the kernel image). It then searches for the rootfs after the end of - * the file data. This driver assumes that the filesystem was generated by - * mkh3cvfs, and only works if the filesystem matches the expected layout, - * which includes the file name of the kernel image. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define VFS_ERASEBLOCK_SIZE 0x10000 -#define VFS_BLOCK_SIZE 0x400 -#define VFS_BLOCKS_PER_ERASEBLOCK (VFS_ERASEBLOCK_SIZE / VFS_BLOCK_SIZE) - -#define FORMAT_FLAG_OFFSET 0x0 - -#define FORMAT_FLAG (VFS_ERASEBLOCK_SIZE << 12 | VFS_BLOCK_SIZE) - -#define FILE_ENTRY_OFFSET 0x800 - -#define FILE_ENTRY_FLAGS 0x3f -#define FILE_ENTRY_PARENT_BLOCK 0 -#define FILE_ENTRY_PARENT_INDEX 0 -#define FILE_ENTRY_DATA_BLOCK 2 -#define FILE_ENTRY_NAME "openwrt-kernel.bin" - -#define NR_PARTS 2 - -struct file_entry { - uint8_t flags; - - uint8_t res0[5]; - - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - - uint8_t res1[3]; - - uint32_t length; - - uint32_t parent_block; - uint16_t parent_index; - - uint8_t res2[2]; - - uint32_t data_block; - - char name[96]; -} __attribute__ ((packed)); - -static inline size_t block_offset(int block) -{ - return VFS_ERASEBLOCK_SIZE * (block / (VFS_BLOCKS_PER_ERASEBLOCK-1)) - + VFS_BLOCK_SIZE * (1 + (block % (VFS_BLOCKS_PER_ERASEBLOCK-1))); -} - -static inline int block_count(size_t size) -{ - return (size + VFS_BLOCK_SIZE - 1) / VFS_BLOCK_SIZE; -} - -static int mtdsplit_h3c_vfs_parse(struct mtd_info *mtd, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - uint32_t format_flag; - struct file_entry file_entry; - size_t retlen; - int err; - size_t kernel_size; - size_t expected_offset; - size_t rootfs_offset; - - if (mtd->erasesize != VFS_ERASEBLOCK_SIZE) - return -EINVAL; - - /* Check format flag */ - err = mtd_read(mtd, FORMAT_FLAG_OFFSET, sizeof(format_flag), &retlen, - (void *) &format_flag); - if (err) - return err; - - if (retlen != sizeof(format_flag)) - return -EIO; - - if (format_flag != FORMAT_FLAG) - return -EINVAL; - - /* Check file entry */ - err = mtd_read(mtd, FILE_ENTRY_OFFSET, sizeof(file_entry), &retlen, - (void *) &file_entry); - if (err) - return err; - - if (retlen != sizeof(file_entry)) - return -EIO; - - if (file_entry.flags != FILE_ENTRY_FLAGS) - return -EINVAL; - - if (file_entry.parent_block != FILE_ENTRY_PARENT_BLOCK) - return -EINVAL; - - if (file_entry.parent_index != FILE_ENTRY_PARENT_INDEX) - return -EINVAL; - - if (file_entry.data_block != FILE_ENTRY_DATA_BLOCK) - return -EINVAL; - - if (strncmp(file_entry.name, FILE_ENTRY_NAME, sizeof(file_entry.name)) != 0) - return -EINVAL; - - /* Find rootfs offset */ - kernel_size = block_offset(file_entry.data_block + - block_count(file_entry.length) - 1) + - VFS_BLOCK_SIZE; - - expected_offset = mtd_roundup_to_eb(kernel_size, mtd); - - err = mtd_find_rootfs_from(mtd, expected_offset, mtd->size, - &rootfs_offset, NULL); - if (err) - return err; - - parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = rootfs_offset; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = mtd->size - rootfs_offset; - - *pparts = parts; - return NR_PARTS; -} - -static const struct of_device_id mtdsplit_h3c_vfs_of_match_table[] = { - { .compatible = "h3c,vfs-firmware" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_h3c_vfs_of_match_table); - -static struct mtd_part_parser mtdsplit_h3c_vfs_parser = { - .owner = THIS_MODULE, - .name = "h3c-vfs", - .of_match_table = mtdsplit_h3c_vfs_of_match_table, - .parse_fn = mtdsplit_h3c_vfs_parse, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -module_mtd_part_parser(mtdsplit_h3c_vfs_parser); diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt.c deleted file mode 100644 index bcff7d6ac..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (c) 2017 MediaTek Inc. - * Author: Xiangsheng Hou - * Copyright (c) 2020-2022 Felix Fietkau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include "mtk_bmt.h" - -struct bmt_desc bmtd = {}; - -/* -------- Nand operations wrapper -------- */ -int bbt_nand_copy(u16 dest_blk, u16 src_blk, loff_t max_offset) -{ - int pages = bmtd.blk_size >> bmtd.pg_shift; - loff_t src = (loff_t)src_blk << bmtd.blk_shift; - loff_t dest = (loff_t)dest_blk << bmtd.blk_shift; - loff_t offset = 0; - uint8_t oob[64]; - int i, ret; - - for (i = 0; i < pages; i++) { - struct mtd_oob_ops rd_ops = { - .mode = MTD_OPS_PLACE_OOB, - .oobbuf = oob, - .ooblen = min_t(int, bmtd.mtd->oobsize / pages, sizeof(oob)), - .datbuf = bmtd.data_buf, - .len = bmtd.pg_size, - }; - struct mtd_oob_ops wr_ops = { - .mode = MTD_OPS_PLACE_OOB, - .oobbuf = oob, - .datbuf = bmtd.data_buf, - .len = bmtd.pg_size, - }; - - if (offset >= max_offset) - break; - - ret = bmtd._read_oob(bmtd.mtd, src + offset, &rd_ops); - if (ret < 0 && !mtd_is_bitflip(ret)) - return ret; - - if (!rd_ops.retlen) - break; - - ret = bmtd._write_oob(bmtd.mtd, dest + offset, &wr_ops); - if (ret < 0) - return ret; - - wr_ops.ooblen = rd_ops.oobretlen; - offset += rd_ops.retlen; - } - - return 0; -} - -/* -------- Bad Blocks Management -------- */ -bool mapping_block_in_range(int block, int *start, int *end) -{ - const __be32 *cur = bmtd.remap_range; - u32 addr = block << bmtd.blk_shift; - int i; - - if (!cur || !bmtd.remap_range_len) { - *start = 0; - *end = bmtd.total_blks; - return true; - } - - for (i = 0; i < bmtd.remap_range_len; i++, cur += 2) { - if (addr < be32_to_cpu(cur[0]) || addr >= be32_to_cpu(cur[1])) - continue; - - *start = be32_to_cpu(cur[0]); - *end = be32_to_cpu(cur[1]); - return true; - } - - return false; -} - -static bool -mtk_bmt_remap_block(u32 block, u32 mapped_block, int copy_len) -{ - int start, end; - - if (!mapping_block_in_range(block, &start, &end)) - return false; - - return bmtd.ops->remap_block(block, mapped_block, copy_len); -} - -static int -mtk_bmt_read(struct mtd_info *mtd, loff_t from, - struct mtd_oob_ops *ops) -{ - struct mtd_oob_ops cur_ops = *ops; - int retry_count = 0; - loff_t cur_from; - int ret = 0; - int max_bitflips = 0; - - ops->retlen = 0; - ops->oobretlen = 0; - - while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) { - int cur_ret; - - u32 offset = from & (bmtd.blk_size - 1); - u32 block = from >> bmtd.blk_shift; - int cur_block; - - cur_block = bmtd.ops->get_mapping_block(block); - if (cur_block < 0) - return -EIO; - - cur_from = ((loff_t)cur_block << bmtd.blk_shift) + offset; - - cur_ops.oobretlen = 0; - cur_ops.retlen = 0; - cur_ops.len = min_t(u32, mtd->erasesize - offset, - ops->len - ops->retlen); - cur_ret = bmtd._read_oob(mtd, cur_from, &cur_ops); - if (cur_ret < 0) - ret = cur_ret; - else - max_bitflips = max_t(int, max_bitflips, cur_ret); - if (cur_ret < 0 && !mtd_is_bitflip(cur_ret)) { - if (mtk_bmt_remap_block(block, cur_block, mtd->erasesize) && - retry_count++ < 10) - continue; - - goto out; - } - - if (mtd->bitflip_threshold && cur_ret >= mtd->bitflip_threshold) - mtk_bmt_remap_block(block, cur_block, mtd->erasesize); - - ops->retlen += cur_ops.retlen; - ops->oobretlen += cur_ops.oobretlen; - - cur_ops.ooboffs = 0; - cur_ops.datbuf += cur_ops.retlen; - cur_ops.oobbuf += cur_ops.oobretlen; - cur_ops.ooblen -= cur_ops.oobretlen; - - if (!cur_ops.len) - cur_ops.len = mtd->erasesize - offset; - - from += cur_ops.len; - retry_count = 0; - } - -out: - if (ret < 0) - return ret; - - return max_bitflips; -} - -static int -mtk_bmt_write(struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops) -{ - struct mtd_oob_ops cur_ops = *ops; - int retry_count = 0; - loff_t cur_to; - int ret; - - ops->retlen = 0; - ops->oobretlen = 0; - - while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) { - u32 offset = to & (bmtd.blk_size - 1); - u32 block = to >> bmtd.blk_shift; - int cur_block; - - cur_block = bmtd.ops->get_mapping_block(block); - if (cur_block < 0) - return -EIO; - - cur_to = ((loff_t)cur_block << bmtd.blk_shift) + offset; - - cur_ops.oobretlen = 0; - cur_ops.retlen = 0; - cur_ops.len = min_t(u32, bmtd.blk_size - offset, - ops->len - ops->retlen); - ret = bmtd._write_oob(mtd, cur_to, &cur_ops); - if (ret < 0) { - if (mtk_bmt_remap_block(block, cur_block, offset) && - retry_count++ < 10) - continue; - - return ret; - } - - ops->retlen += cur_ops.retlen; - ops->oobretlen += cur_ops.oobretlen; - - cur_ops.ooboffs = 0; - cur_ops.datbuf += cur_ops.retlen; - cur_ops.oobbuf += cur_ops.oobretlen; - cur_ops.ooblen -= cur_ops.oobretlen; - - if (!cur_ops.len) - cur_ops.len = mtd->erasesize - offset; - - to += cur_ops.len; - retry_count = 0; - } - - return 0; -} - -static int -mtk_bmt_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct erase_info mapped_instr = { - .len = bmtd.blk_size, - }; - int retry_count = 0; - u64 start_addr, end_addr; - int ret; - u16 orig_block; - int block; - - start_addr = instr->addr & (~mtd->erasesize_mask); - end_addr = instr->addr + instr->len; - - while (start_addr < end_addr) { - orig_block = start_addr >> bmtd.blk_shift; - block = bmtd.ops->get_mapping_block(orig_block); - if (block < 0) - return -EIO; - mapped_instr.addr = (loff_t)block << bmtd.blk_shift; - ret = bmtd._erase(mtd, &mapped_instr); - if (ret) { - if (mtk_bmt_remap_block(orig_block, block, 0) && - retry_count++ < 10) - continue; - instr->fail_addr = start_addr; - break; - } - start_addr += mtd->erasesize; - retry_count = 0; - } - - return ret; -} -static int -mtk_bmt_block_isbad(struct mtd_info *mtd, loff_t ofs) -{ - int retry_count = 0; - u16 orig_block = ofs >> bmtd.blk_shift; - u16 block; - int ret; - -retry: - block = bmtd.ops->get_mapping_block(orig_block); - ret = bmtd._block_isbad(mtd, (loff_t)block << bmtd.blk_shift); - if (ret) { - if (mtk_bmt_remap_block(orig_block, block, bmtd.blk_size) && - retry_count++ < 10) - goto retry; - } - return ret; -} - -static int -mtk_bmt_block_markbad(struct mtd_info *mtd, loff_t ofs) -{ - u16 orig_block = ofs >> bmtd.blk_shift; - int block; - - block = bmtd.ops->get_mapping_block(orig_block); - if (block < 0) - return -EIO; - - mtk_bmt_remap_block(orig_block, block, bmtd.blk_size); - - return bmtd._block_markbad(mtd, (loff_t)block << bmtd.blk_shift); -} - -static void -mtk_bmt_replace_ops(struct mtd_info *mtd) -{ - bmtd._read_oob = mtd->_read_oob; - bmtd._write_oob = mtd->_write_oob; - bmtd._erase = mtd->_erase; - bmtd._block_isbad = mtd->_block_isbad; - bmtd._block_markbad = mtd->_block_markbad; - - mtd->_read_oob = mtk_bmt_read; - mtd->_write_oob = mtk_bmt_write; - mtd->_erase = mtk_bmt_mtd_erase; - mtd->_block_isbad = mtk_bmt_block_isbad; - mtd->_block_markbad = mtk_bmt_block_markbad; -} - -static int mtk_bmt_debug_repair(void *data, u64 val) -{ - int block = val >> bmtd.blk_shift; - int prev_block, new_block; - - prev_block = bmtd.ops->get_mapping_block(block); - if (prev_block < 0) - return -EIO; - - bmtd.ops->unmap_block(block); - new_block = bmtd.ops->get_mapping_block(block); - if (new_block < 0) - return -EIO; - - if (prev_block == new_block) - return 0; - - bbt_nand_erase(new_block); - bbt_nand_copy(new_block, prev_block, bmtd.blk_size); - - return 0; -} - -static int mtk_bmt_debug_mark_good(void *data, u64 val) -{ - bmtd.ops->unmap_block(val >> bmtd.blk_shift); - - return 0; -} - -static int mtk_bmt_debug_mark_bad(void *data, u64 val) -{ - u32 block = val >> bmtd.blk_shift; - int cur_block; - - cur_block = bmtd.ops->get_mapping_block(block); - if (cur_block < 0) - return -EIO; - - mtk_bmt_remap_block(block, cur_block, bmtd.blk_size); - - return 0; -} - -static int mtk_bmt_debug(void *data, u64 val) -{ - return bmtd.ops->debug(data, val); -} - - -DEFINE_DEBUGFS_ATTRIBUTE(fops_repair, NULL, mtk_bmt_debug_repair, "%llu\n"); -DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_good, NULL, mtk_bmt_debug_mark_good, "%llu\n"); -DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_bad, NULL, mtk_bmt_debug_mark_bad, "%llu\n"); -DEFINE_DEBUGFS_ATTRIBUTE(fops_debug, NULL, mtk_bmt_debug, "%llu\n"); - -static void -mtk_bmt_add_debugfs(void) -{ - struct dentry *dir; - - dir = bmtd.debugfs_dir = debugfs_create_dir("mtk-bmt", NULL); - if (!dir) - return; - - debugfs_create_file_unsafe("repair", S_IWUSR, dir, NULL, &fops_repair); - debugfs_create_file_unsafe("mark_good", S_IWUSR, dir, NULL, &fops_mark_good); - debugfs_create_file_unsafe("mark_bad", S_IWUSR, dir, NULL, &fops_mark_bad); - debugfs_create_file_unsafe("debug", S_IWUSR, dir, NULL, &fops_debug); -} - -void mtk_bmt_detach(struct mtd_info *mtd) -{ - if (bmtd.mtd != mtd) - return; - - if (bmtd.debugfs_dir) - debugfs_remove_recursive(bmtd.debugfs_dir); - bmtd.debugfs_dir = NULL; - - kfree(bmtd.bbt_buf); - kfree(bmtd.data_buf); - - mtd->_read_oob = bmtd._read_oob; - mtd->_write_oob = bmtd._write_oob; - mtd->_erase = bmtd._erase; - mtd->_block_isbad = bmtd._block_isbad; - mtd->_block_markbad = bmtd._block_markbad; - mtd->size = bmtd.total_blks << bmtd.blk_shift; - - memset(&bmtd, 0, sizeof(bmtd)); -} - - -int mtk_bmt_attach(struct mtd_info *mtd) -{ - struct device_node *np; - int ret = 0; - - if (bmtd.mtd) - return -ENOSPC; - - np = mtd_get_of_node(mtd); - if (!np) - return 0; - - if (of_property_read_bool(np, "mediatek,bmt-v2")) - bmtd.ops = &mtk_bmt_v2_ops; - else if (of_property_read_bool(np, "mediatek,nmbm")) - bmtd.ops = &mtk_bmt_nmbm_ops; - else if (of_property_read_bool(np, "mediatek,bbt")) - bmtd.ops = &mtk_bmt_bbt_ops; - else - return 0; - - bmtd.remap_range = of_get_property(np, "mediatek,bmt-remap-range", - &bmtd.remap_range_len); - bmtd.remap_range_len /= 8; - - bmtd.mtd = mtd; - mtk_bmt_replace_ops(mtd); - - bmtd.blk_size = mtd->erasesize; - bmtd.blk_shift = ffs(bmtd.blk_size) - 1; - bmtd.pg_size = mtd->writesize; - bmtd.pg_shift = ffs(bmtd.pg_size) - 1; - bmtd.total_blks = mtd->size >> bmtd.blk_shift; - - bmtd.data_buf = kzalloc(bmtd.pg_size + bmtd.mtd->oobsize, GFP_KERNEL); - if (!bmtd.data_buf) { - pr_info("nand: FATAL ERR: allocate buffer failed!\n"); - ret = -1; - goto error; - } - - memset(bmtd.data_buf, 0xff, bmtd.pg_size + bmtd.mtd->oobsize); - - ret = bmtd.ops->init(np); - if (ret) - goto error; - - mtk_bmt_add_debugfs(); - return 0; - -error: - mtk_bmt_detach(mtd); - return ret; -} - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Xiangsheng Hou , Felix Fietkau "); -MODULE_DESCRIPTION("Bad Block mapping management v2 for MediaTek NAND Flash Driver"); - diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt.h b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt.h deleted file mode 100644 index 517ff7414..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef __MTK_BMT_PRIV_H -#define __MTK_BMT_PRIV_H - -#include -#include -#include -#include -#include -#include - -#define MAIN_SIGNATURE_OFFSET 0 -#define OOB_SIGNATURE_OFFSET 1 - -#define BBT_LOG(fmt, ...) pr_debug("[BBT][%s|%d] "fmt"\n", __func__, __LINE__, ##__VA_ARGS__) - -struct mtk_bmt_ops { - char *sig; - unsigned int sig_len; - int (*init)(struct device_node *np); - bool (*remap_block)(u16 block, u16 mapped_block, int copy_len); - void (*unmap_block)(u16 block); - int (*get_mapping_block)(int block); - int (*debug)(void *data, u64 val); -}; - -struct bbbt; -struct nmbm_instance; - -struct bmt_desc { - struct mtd_info *mtd; - unsigned char *bbt_buf; - unsigned char *data_buf; - - int (*_read_oob) (struct mtd_info *mtd, loff_t from, - struct mtd_oob_ops *ops); - int (*_write_oob) (struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops); - int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); - int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); - int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); - - const struct mtk_bmt_ops *ops; - - union { - struct bbbt *bbt; - struct nmbm_instance *ni; - }; - - struct dentry *debugfs_dir; - - u32 table_size; - u32 pg_size; - u32 blk_size; - u16 pg_shift; - u16 blk_shift; - /* bbt logical address */ - u16 pool_lba; - /* bbt physical address */ - u16 pool_pba; - /* Maximum count of bad blocks that the vendor guaranteed */ - u16 bb_max; - /* Total blocks of the Nand Chip */ - u16 total_blks; - /* The block(n) BMT is located at (bmt_tbl[n]) */ - u16 bmt_blk_idx; - /* How many pages needs to store 'struct bbbt' */ - u32 bmt_pgs; - - const __be32 *remap_range; - int remap_range_len; - - /* to compensate for driver level remapping */ - u8 oob_offset; -}; - -extern struct bmt_desc bmtd; -extern const struct mtk_bmt_ops mtk_bmt_v2_ops; -extern const struct mtk_bmt_ops mtk_bmt_bbt_ops; -extern const struct mtk_bmt_ops mtk_bmt_nmbm_ops; - -static inline u32 blk_pg(u16 block) -{ - return (u32)(block << (bmtd.blk_shift - bmtd.pg_shift)); -} - -static inline int -bbt_nand_read(u32 page, unsigned char *dat, int dat_len, - unsigned char *fdm, int fdm_len) -{ - struct mtd_oob_ops ops = { - .mode = MTD_OPS_PLACE_OOB, - .ooboffs = bmtd.oob_offset, - .oobbuf = fdm, - .ooblen = fdm_len, - .datbuf = dat, - .len = dat_len, - }; - int ret; - - ret = bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops); - if (ret < 0) - return ret; - if (ret) - pr_info("%s: %d bitflips\n", __func__, ret); - return 0; -} - -static inline int bbt_nand_erase(u16 block) -{ - struct mtd_info *mtd = bmtd.mtd; - struct erase_info instr = { - .addr = (loff_t)block << bmtd.blk_shift, - .len = bmtd.blk_size, - }; - - return bmtd._erase(mtd, &instr); -} - -static inline int write_bmt(u16 block, unsigned char *dat) -{ - struct mtd_oob_ops ops = { - .mode = MTD_OPS_PLACE_OOB, - .ooboffs = OOB_SIGNATURE_OFFSET + bmtd.oob_offset, - .oobbuf = bmtd.ops->sig, - .ooblen = bmtd.ops->sig_len, - .datbuf = dat, - .len = bmtd.bmt_pgs << bmtd.pg_shift, - }; - loff_t addr = (loff_t)block << bmtd.blk_shift; - - return bmtd._write_oob(bmtd.mtd, addr, &ops); -} - -int bbt_nand_copy(u16 dest_blk, u16 src_blk, loff_t max_offset); -bool mapping_block_in_range(int block, int *start, int *end); - -#endif diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_bbt.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_bbt.c deleted file mode 100644 index 519e1ed70..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_bbt.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2017 MediaTek Inc. - * Author: Xiangsheng Hou - * Copyright (c) 2020-2022 Felix Fietkau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include "mtk_bmt.h" - -static bool -bbt_block_is_bad(u16 block) -{ - u8 cur = bmtd.bbt_buf[block / 4]; - - return cur & (3 << ((block % 4) * 2)); -} - -static void -bbt_set_block_state(u16 block, bool bad) -{ - u8 mask = (3 << ((block % 4) * 2)); - - if (bad) - bmtd.bbt_buf[block / 4] |= mask; - else - bmtd.bbt_buf[block / 4] &= ~mask; - - bbt_nand_erase(bmtd.bmt_blk_idx); - write_bmt(bmtd.bmt_blk_idx, bmtd.bbt_buf); -} - -static int -get_mapping_block_index_bbt(int block) -{ - int start, end, ofs; - int bad_blocks = 0; - int i; - - if (!mapping_block_in_range(block, &start, &end)) - return block; - - start >>= bmtd.blk_shift; - end >>= bmtd.blk_shift; - /* skip bad blocks within the mapping range */ - ofs = block - start; - for (i = start; i < end; i++) { - if (bbt_block_is_bad(i)) - bad_blocks++; - else if (ofs) - ofs--; - else - break; - } - - if (i < end) - return i; - - /* when overflowing, remap remaining blocks to bad ones */ - for (i = end - 1; bad_blocks > 0; i--) { - if (!bbt_block_is_bad(i)) - continue; - - bad_blocks--; - if (bad_blocks <= ofs) - return i; - } - - return block; -} - -static bool remap_block_bbt(u16 block, u16 mapped_blk, int copy_len) -{ - int start, end; - u16 new_blk; - - if (!mapping_block_in_range(block, &start, &end)) - return false; - - bbt_set_block_state(mapped_blk, true); - - new_blk = get_mapping_block_index_bbt(block); - bbt_nand_erase(new_blk); - if (copy_len > 0) - bbt_nand_copy(new_blk, mapped_blk, copy_len); - - return true; -} - -static void -unmap_block_bbt(u16 block) -{ - bbt_set_block_state(block, false); -} - -static int -mtk_bmt_read_bbt(void) -{ - u8 oob_buf[8]; - int i; - - for (i = bmtd.total_blks - 1; i >= bmtd.total_blks - 5; i--) { - u32 page = i << (bmtd.blk_shift - bmtd.pg_shift); - - if (bbt_nand_read(page, bmtd.bbt_buf, bmtd.pg_size, - oob_buf, sizeof(oob_buf))) { - pr_info("read_bbt: could not read block %d\n", i); - continue; - } - - if (oob_buf[0] != 0xff) { - pr_info("read_bbt: bad block at %d\n", i); - continue; - } - - if (memcmp(&oob_buf[1], "mtknand", 7) != 0) { - pr_info("read_bbt: signature mismatch in block %d\n", i); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, oob_buf, 8, 1); - continue; - } - - pr_info("read_bbt: found bbt at block %d\n", i); - bmtd.bmt_blk_idx = i; - return 0; - } - - return -EIO; -} - - -static int -mtk_bmt_init_bbt(struct device_node *np) -{ - int buf_size = round_up(bmtd.total_blks >> 2, bmtd.blk_size); - int ret; - - bmtd.bbt_buf = kmalloc(buf_size, GFP_KERNEL); - if (!bmtd.bbt_buf) - return -ENOMEM; - - memset(bmtd.bbt_buf, 0xff, buf_size); - bmtd.mtd->size -= 4 * bmtd.mtd->erasesize; - - ret = mtk_bmt_read_bbt(); - if (ret) - return ret; - - bmtd.bmt_pgs = buf_size / bmtd.pg_size; - - return 0; -} - -static int mtk_bmt_debug_bbt(void *data, u64 val) -{ - char buf[5]; - int i, k; - - switch (val) { - case 0: - for (i = 0; i < bmtd.total_blks; i += 4) { - u8 cur = bmtd.bbt_buf[i / 4]; - - for (k = 0; k < 4; k++, cur >>= 2) - buf[k] = (cur & 3) ? 'B' : '.'; - - buf[4] = 0; - printk("[%06x] %s\n", i * bmtd.blk_size, buf); - } - break; - case 100: -#if 0 - for (i = bmtd.bmt_blk_idx; i < bmtd.total_blks - 1; i++) - bbt_nand_erase(bmtd.bmt_blk_idx); -#endif - - bmtd.bmt_blk_idx = bmtd.total_blks - 1; - bbt_nand_erase(bmtd.bmt_blk_idx); - write_bmt(bmtd.bmt_blk_idx, bmtd.bbt_buf); - break; - default: - break; - } - return 0; -} - -const struct mtk_bmt_ops mtk_bmt_bbt_ops = { - .sig = "mtknand", - .sig_len = 7, - .init = mtk_bmt_init_bbt, - .remap_block = remap_block_bbt, - .unmap_block = unmap_block_bbt, - .get_mapping_block = get_mapping_block_index_bbt, - .debug = mtk_bmt_debug_bbt, -}; diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_nmbm.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_nmbm.c deleted file mode 100644 index a896e49ec..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_nmbm.c +++ /dev/null @@ -1,2348 +0,0 @@ -#include -#include -#include "mtk_bmt.h" - -#define nlog_err(ni, ...) printk(KERN_ERR __VA_ARGS__) -#define nlog_info(ni, ...) printk(KERN_INFO __VA_ARGS__) -#define nlog_debug(ni, ...) printk(KERN_INFO __VA_ARGS__) -#define nlog_warn(ni, ...) printk(KERN_WARNING __VA_ARGS__) - -#define NMBM_MAGIC_SIGNATURE 0x304d4d4e /* NMM0 */ -#define NMBM_MAGIC_INFO_TABLE 0x314d4d4e /* NMM1 */ - -#define NMBM_VERSION_MAJOR_S 0 -#define NMBM_VERSION_MAJOR_M 0xffff -#define NMBM_VERSION_MINOR_S 16 -#define NMBM_VERSION_MINOR_M 0xffff -#define NMBM_VERSION_MAKE(major, minor) (((major) & NMBM_VERSION_MAJOR_M) | \ - (((minor) & NMBM_VERSION_MINOR_M) << \ - NMBM_VERSION_MINOR_S)) -#define NMBM_VERSION_MAJOR_GET(ver) (((ver) >> NMBM_VERSION_MAJOR_S) & \ - NMBM_VERSION_MAJOR_M) -#define NMBM_VERSION_MINOR_GET(ver) (((ver) >> NMBM_VERSION_MINOR_S) & \ - NMBM_VERSION_MINOR_M) - -#define NMBM_BITMAP_UNIT_SIZE (sizeof(u32)) -#define NMBM_BITMAP_BITS_PER_BLOCK 2 -#define NMBM_BITMAP_BITS_PER_UNIT (8 * sizeof(u32)) -#define NMBM_BITMAP_BLOCKS_PER_UNIT (NMBM_BITMAP_BITS_PER_UNIT / \ - NMBM_BITMAP_BITS_PER_BLOCK) - -#define NMBM_SPARE_BLOCK_MULTI 1 -#define NMBM_SPARE_BLOCK_DIV 2 -#define NMBM_SPARE_BLOCK_MIN 2 - -#define NMBM_MGMT_DIV 16 -#define NMBM_MGMT_BLOCKS_MIN 32 - -#define NMBM_TRY_COUNT 3 - -#define BLOCK_ST_BAD 0 -#define BLOCK_ST_NEED_REMAP 2 -#define BLOCK_ST_GOOD 3 -#define BLOCK_ST_MASK 3 - -#define NMBM_VER_MAJOR 1 -#define NMBM_VER_MINOR 0 -#define NMBM_VER NMBM_VERSION_MAKE(NMBM_VER_MAJOR, \ - NMBM_VER_MINOR) - -struct nmbm_header { - u32 magic; - u32 version; - u32 size; - u32 checksum; -}; - -struct nmbm_signature { - struct nmbm_header header; - uint64_t nand_size; - u32 block_size; - u32 page_size; - u32 spare_size; - u32 mgmt_start_pb; - u8 max_try_count; - u8 padding[3]; -}; - -struct nmbm_info_table_header { - struct nmbm_header header; - u32 write_count; - u32 state_table_off; - u32 mapping_table_off; - u32 padding; -}; - -struct nmbm_instance { - u32 rawpage_size; - u32 rawblock_size; - u32 rawchip_size; - - struct nmbm_signature signature; - - u8 *info_table_cache; - u32 info_table_size; - u32 info_table_spare_blocks; - struct nmbm_info_table_header info_table; - - u32 *block_state; - u32 block_state_changed; - u32 state_table_size; - - int32_t *block_mapping; - u32 block_mapping_changed; - u32 mapping_table_size; - - u8 *page_cache; - - int protected; - - u32 block_count; - u32 data_block_count; - - u32 mgmt_start_ba; - u32 main_table_ba; - u32 backup_table_ba; - u32 mapping_blocks_ba; - u32 mapping_blocks_top_ba; - u32 signature_ba; - - u32 max_ratio; - u32 max_reserved_blocks; - bool empty_page_ecc_ok; - bool force_create; -}; - -static inline u32 nmbm_crc32(u32 crcval, const void *buf, size_t size) -{ - unsigned int chksz; - const unsigned char *p = buf; - - while (size) { - if (size > UINT_MAX) - chksz = UINT_MAX; - else - chksz = (uint)size; - - crcval = crc32_le(crcval, p, chksz); - size -= chksz; - p += chksz; - } - - return crcval; -} -/* - * nlog_table_creation - Print log of table creation event - * @ni: NMBM instance structure - * @main_table: whether the table is main info table - * @start_ba: start block address of the table - * @end_ba: block address after the end of the table - */ -static void nlog_table_creation(struct nmbm_instance *ni, bool main_table, - uint32_t start_ba, uint32_t end_ba) -{ - if (start_ba == end_ba - 1) - nlog_info(ni, "%s info table has been written to block %u\n", - main_table ? "Main" : "Backup", start_ba); - else - nlog_info(ni, "%s info table has been written to block %u-%u\n", - main_table ? "Main" : "Backup", start_ba, end_ba - 1); -} - -/* - * nlog_table_update - Print log of table update event - * @ni: NMBM instance structure - * @main_table: whether the table is main info table - * @start_ba: start block address of the table - * @end_ba: block address after the end of the table - */ -static void nlog_table_update(struct nmbm_instance *ni, bool main_table, - uint32_t start_ba, uint32_t end_ba) -{ - if (start_ba == end_ba - 1) - nlog_debug(ni, "%s info table has been updated in block %u\n", - main_table ? "Main" : "Backup", start_ba); - else - nlog_debug(ni, "%s info table has been updated in block %u-%u\n", - main_table ? "Main" : "Backup", start_ba, end_ba - 1); -} - -/* - * nlog_table_found - Print log of table found event - * @ni: NMBM instance structure - * @first_table: whether the table is first found info table - * @write_count: write count of the info table - * @start_ba: start block address of the table - * @end_ba: block address after the end of the table - */ -static void nlog_table_found(struct nmbm_instance *ni, bool first_table, - uint32_t write_count, uint32_t start_ba, - uint32_t end_ba) -{ - if (start_ba == end_ba - 1) - nlog_info(ni, "%s info table with writecount %u found in block %u\n", - first_table ? "First" : "Second", write_count, - start_ba); - else - nlog_info(ni, "%s info table with writecount %u found in block %u-%u\n", - first_table ? "First" : "Second", write_count, - start_ba, end_ba - 1); -} - -/*****************************************************************************/ -/* Address conversion functions */ -/*****************************************************************************/ - -/* - * ba2addr - Convert a block address to linear address - * @ni: NMBM instance structure - * @ba: Block address - */ -static uint64_t ba2addr(struct nmbm_instance *ni, uint32_t ba) -{ - return (uint64_t)ba << bmtd.blk_shift; -} -/* - * size2blk - Get minimum required blocks for storing specific size of data - * @ni: NMBM instance structure - * @size: size for storing - */ -static uint32_t size2blk(struct nmbm_instance *ni, uint64_t size) -{ - return (size + bmtd.blk_size - 1) >> bmtd.blk_shift; -} - -/*****************************************************************************/ -/* High level NAND chip APIs */ -/*****************************************************************************/ - -/* - * nmbm_read_phys_page - Read page with retry - * @ni: NMBM instance structure - * @addr: linear address where the data will be read from - * @data: the main data to be read - * @oob: the oob data to be read - * - * Read a page for at most NMBM_TRY_COUNT times. - * - * Return 0 for success, positive value for corrected bitflip count, - * -EBADMSG for ecc error, other negative values for other errors - */ -static int nmbm_read_phys_page(struct nmbm_instance *ni, uint64_t addr, - void *data, void *oob) -{ - int tries, ret; - - for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { - struct mtd_oob_ops ops = { - .mode = MTD_OPS_PLACE_OOB, - .oobbuf = oob, - .datbuf = data, - }; - - if (data) - ops.len = bmtd.pg_size; - if (oob) - ops.ooblen = mtd_oobavail(bmtd.mtd, &ops); - - ret = bmtd._read_oob(bmtd.mtd, addr, &ops); - if (ret == -EUCLEAN) - return min_t(u32, bmtd.mtd->bitflip_threshold + 1, - bmtd.mtd->ecc_strength); - if (ret >= 0) - return 0; - } - - if (ret != -EBADMSG) - nlog_err(ni, "Page read failed at address 0x%08llx\n", addr); - - return ret; -} - -/* - * nmbm_write_phys_page - Write page with retry - * @ni: NMBM instance structure - * @addr: linear address where the data will be written to - * @data: the main data to be written - * @oob: the oob data to be written - * - * Write a page for at most NMBM_TRY_COUNT times. - */ -static bool nmbm_write_phys_page(struct nmbm_instance *ni, uint64_t addr, - const void *data, const void *oob) -{ - int tries, ret; - - for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { - struct mtd_oob_ops ops = { - .mode = MTD_OPS_PLACE_OOB, - .oobbuf = (void *)oob, - .datbuf = (void *)data, - }; - - if (data) - ops.len = bmtd.pg_size; - if (oob) - ops.ooblen = mtd_oobavail(bmtd.mtd, &ops); - - ret = bmtd._write_oob(bmtd.mtd, addr, &ops); - if (!ret) - return true; - } - - nlog_err(ni, "Page write failed at address 0x%08llx\n", addr); - - return false; -} - -/* - * nmbm_erase_phys_block - Erase a block with retry - * @ni: NMBM instance structure - * @addr: Linear address - * - * Erase a block for at most NMBM_TRY_COUNT times. - */ -static bool nmbm_erase_phys_block(struct nmbm_instance *ni, uint64_t addr) -{ - int tries, ret; - - for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { - struct erase_info ei = { - .addr = addr, - .len = bmtd.mtd->erasesize, - }; - - ret = bmtd._erase(bmtd.mtd, &ei); - if (!ret) - return true; - } - - nlog_err(ni, "Block erasure failed at address 0x%08llx\n", addr); - - return false; -} - -/* - * nmbm_check_bad_phys_block - Check whether a block is marked bad in OOB - * @ni: NMBM instance structure - * @ba: block address - */ -static bool nmbm_check_bad_phys_block(struct nmbm_instance *ni, uint32_t ba) -{ - uint64_t addr = ba2addr(ni, ba); - - return bmtd._block_isbad(bmtd.mtd, addr); -} - -/* - * nmbm_mark_phys_bad_block - Mark a block bad - * @ni: NMBM instance structure - * @addr: Linear address - */ -static int nmbm_mark_phys_bad_block(struct nmbm_instance *ni, uint32_t ba) -{ - uint64_t addr = ba2addr(ni, ba); - - nlog_info(ni, "Block %u [0x%08llx] will be marked bad\n", ba, addr); - - return bmtd._block_markbad(bmtd.mtd, addr); -} - -/*****************************************************************************/ -/* NMBM related functions */ -/*****************************************************************************/ - -/* - * nmbm_check_header - Check whether a NMBM structure is valid - * @data: pointer to a NMBM structure with a NMBM header at beginning - * @size: Size of the buffer pointed by @header - * - * The size of the NMBM structure may be larger than NMBM header, - * e.g. block mapping table and block state table. - */ -static bool nmbm_check_header(const void *data, uint32_t size) -{ - const struct nmbm_header *header = data; - struct nmbm_header nhdr; - uint32_t new_checksum; - - /* - * Make sure expected structure size is equal or smaller than - * buffer size. - */ - if (header->size > size) - return false; - - memcpy(&nhdr, data, sizeof(nhdr)); - - nhdr.checksum = 0; - new_checksum = nmbm_crc32(0, &nhdr, sizeof(nhdr)); - if (header->size > sizeof(nhdr)) - new_checksum = nmbm_crc32(new_checksum, - (const uint8_t *)data + sizeof(nhdr), - header->size - sizeof(nhdr)); - - if (header->checksum != new_checksum) - return false; - - return true; -} - -/* - * nmbm_update_checksum - Update checksum of a NMBM structure - * @header: pointer to a NMBM structure with a NMBM header at beginning - * - * The size of the NMBM structure must be specified by @header->size - */ -static void nmbm_update_checksum(struct nmbm_header *header) -{ - header->checksum = 0; - header->checksum = nmbm_crc32(0, header, header->size); -} - -/* - * nmbm_get_spare_block_count - Calculate number of blocks should be reserved - * @block_count: number of blocks of data - * - * Calculate number of blocks should be reserved for data - */ -static uint32_t nmbm_get_spare_block_count(uint32_t block_count) -{ - uint32_t val; - - val = (block_count + NMBM_SPARE_BLOCK_DIV / 2) / NMBM_SPARE_BLOCK_DIV; - val *= NMBM_SPARE_BLOCK_MULTI; - - if (val < NMBM_SPARE_BLOCK_MIN) - val = NMBM_SPARE_BLOCK_MIN; - - return val; -} - -/* - * nmbm_get_block_state_raw - Get state of a block from raw block state table - * @block_state: pointer to raw block state table (bitmap) - * @ba: block address - */ -static uint32_t nmbm_get_block_state_raw(u32 *block_state, - uint32_t ba) -{ - uint32_t unit, shift; - - unit = ba / NMBM_BITMAP_BLOCKS_PER_UNIT; - shift = (ba % NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_BITS_PER_BLOCK; - - return (block_state[unit] >> shift) & BLOCK_ST_MASK; -} - -/* - * nmbm_get_block_state - Get state of a block from block state table - * @ni: NMBM instance structure - * @ba: block address - */ -static uint32_t nmbm_get_block_state(struct nmbm_instance *ni, uint32_t ba) -{ - return nmbm_get_block_state_raw(ni->block_state, ba); -} - -/* - * nmbm_set_block_state - Set state of a block to block state table - * @ni: NMBM instance structure - * @ba: block address - * @state: block state - * - * Set state of a block. If the block state changed, ni->block_state_changed - * will be increased. - */ -static bool nmbm_set_block_state(struct nmbm_instance *ni, uint32_t ba, - uint32_t state) -{ - uint32_t unit, shift, orig; - u32 uv; - - unit = ba / NMBM_BITMAP_BLOCKS_PER_UNIT; - shift = (ba % NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_BITS_PER_BLOCK; - - orig = (ni->block_state[unit] >> shift) & BLOCK_ST_MASK; - state &= BLOCK_ST_MASK; - - uv = ni->block_state[unit] & (~(BLOCK_ST_MASK << shift)); - uv |= state << shift; - ni->block_state[unit] = uv; - - if (orig != state) { - ni->block_state_changed++; - return true; - } - - return false; -} - -/* - * nmbm_block_walk_asc - Skip specified number of good blocks, ascending addr. - * @ni: NMBM instance structure - * @ba: start physical block address - * @nba: return physical block address after walk - * @count: number of good blocks to be skipped - * @limit: highest block address allowed for walking - * - * Start from @ba, skipping any bad blocks, counting @count good blocks, and - * return the next good block address. - * - * If no enough good blocks counted while @limit reached, false will be returned. - * - * If @count == 0, nearest good block address will be returned. - * @limit is not counted in walking. - */ -static bool nmbm_block_walk_asc(struct nmbm_instance *ni, uint32_t ba, - uint32_t *nba, uint32_t count, - uint32_t limit) -{ - int32_t nblock = count; - - if (limit >= ni->block_count) - limit = ni->block_count - 1; - - while (ba < limit) { - if (nmbm_get_block_state(ni, ba) == BLOCK_ST_GOOD) - nblock--; - - if (nblock < 0) { - *nba = ba; - return true; - } - - ba++; - } - - return false; -} - -/* - * nmbm_block_walk_desc - Skip specified number of good blocks, descending addr - * @ni: NMBM instance structure - * @ba: start physical block address - * @nba: return physical block address after walk - * @count: number of good blocks to be skipped - * @limit: lowest block address allowed for walking - * - * Start from @ba, skipping any bad blocks, counting @count good blocks, and - * return the next good block address. - * - * If no enough good blocks counted while @limit reached, false will be returned. - * - * If @count == 0, nearest good block address will be returned. - * @limit is not counted in walking. - */ -static bool nmbm_block_walk_desc(struct nmbm_instance *ni, uint32_t ba, - uint32_t *nba, uint32_t count, uint32_t limit) -{ - int32_t nblock = count; - - if (limit >= ni->block_count) - limit = ni->block_count - 1; - - while (ba > limit) { - if (nmbm_get_block_state(ni, ba) == BLOCK_ST_GOOD) - nblock--; - - if (nblock < 0) { - *nba = ba; - return true; - } - - ba--; - } - - return false; -} - -/* - * nmbm_block_walk - Skip specified number of good blocks from curr. block addr - * @ni: NMBM instance structure - * @ascending: whether to walk ascending - * @ba: start physical block address - * @nba: return physical block address after walk - * @count: number of good blocks to be skipped - * @limit: highest/lowest block address allowed for walking - * - * Start from @ba, skipping any bad blocks, counting @count good blocks, and - * return the next good block address. - * - * If no enough good blocks counted while @limit reached, false will be returned. - * - * If @count == 0, nearest good block address will be returned. - * @limit can be set to negative if no limit required. - * @limit is not counted in walking. - */ -static bool nmbm_block_walk(struct nmbm_instance *ni, bool ascending, - uint32_t ba, uint32_t *nba, int32_t count, - int32_t limit) -{ - if (ascending) - return nmbm_block_walk_asc(ni, ba, nba, count, limit); - - return nmbm_block_walk_desc(ni, ba, nba, count, limit); -} - -/* - * nmbm_scan_badblocks - Scan and record all bad blocks - * @ni: NMBM instance structure - * - * Scan the entire lower NAND chip and record all bad blocks in to block state - * table. - */ -static void nmbm_scan_badblocks(struct nmbm_instance *ni) -{ - uint32_t ba; - - for (ba = 0; ba < ni->block_count; ba++) { - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - nlog_info(ni, "Bad block %u [0x%08llx]\n", ba, - ba2addr(ni, ba)); - } - } -} - -/* - * nmbm_build_mapping_table - Build initial block mapping table - * @ni: NMBM instance structure - * - * The initial mapping table will be compatible with the stratage of - * factory production. - */ -static void nmbm_build_mapping_table(struct nmbm_instance *ni) -{ - uint32_t pb, lb; - - for (pb = 0, lb = 0; pb < ni->mgmt_start_ba; pb++) { - if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD) - continue; - - /* Always map to the next good block */ - ni->block_mapping[lb++] = pb; - } - - ni->data_block_count = lb; - - /* Unusable/Management blocks */ - for (pb = lb; pb < ni->block_count; pb++) - ni->block_mapping[pb] = -1; -} - -/* - * nmbm_erase_block_and_check - Erase a block and check its usability - * @ni: NMBM instance structure - * @ba: block address to be erased - * - * Erase a block anc check its usability - * - * Return true if the block is usable, false if erasure failure or the block - * has too many bitflips. - */ -static bool nmbm_erase_block_and_check(struct nmbm_instance *ni, uint32_t ba) -{ - uint64_t addr, off; - bool success; - int ret; - - success = nmbm_erase_phys_block(ni, ba2addr(ni, ba)); - if (!success) - return false; - - if (!ni->empty_page_ecc_ok) - return true; - - /* Check every page to make sure there aren't too many bitflips */ - - addr = ba2addr(ni, ba); - - for (off = 0; off < bmtd.blk_size; off += bmtd.pg_size) { - ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL); - if (ret == -EBADMSG) { - /* - * empty_page_ecc_ok means the empty page is - * still protected by ECC. So reading pages with ECC - * enabled and -EBADMSG means there are too many - * bitflips that can't be recovered, and the block - * containing the page should be marked bad. - */ - nlog_err(ni, - "Too many bitflips in empty page at 0x%llx\n", - addr + off); - return false; - } - } - - return true; -} - -/* - * nmbm_erase_range - Erase a range of blocks - * @ni: NMBM instance structure - * @ba: block address where the erasure will start - * @limit: top block address allowed for erasure - * - * Erase blocks within the specific range. Newly-found bad blocks will be - * marked. - * - * @limit is not counted into the allowed erasure address. - */ -static void nmbm_erase_range(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit) -{ - bool success; - - while (ba < limit) { - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - goto next_block; - - /* Insurance to detect unexpected bad block marked by user */ - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - goto next_block; - } - - success = nmbm_erase_block_and_check(ni, ba); - if (success) - goto next_block; - - nmbm_mark_phys_bad_block(ni, ba); - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - - next_block: - ba++; - } -} - -/* - * nmbm_write_repeated_data - Write critical data to a block with retry - * @ni: NMBM instance structure - * @ba: block address where the data will be written to - * @data: the data to be written - * @size: size of the data - * - * Write data to every page of the block. Success only if all pages within - * this block have been successfully written. - * - * Make sure data size is not bigger than one page. - * - * This function will write and verify every page for at most - * NMBM_TRY_COUNT times. - */ -static bool nmbm_write_repeated_data(struct nmbm_instance *ni, uint32_t ba, - const void *data, uint32_t size) -{ - uint64_t addr, off; - bool success; - int ret; - - if (size > bmtd.pg_size) - return false; - - addr = ba2addr(ni, ba); - - for (off = 0; off < bmtd.blk_size; off += bmtd.pg_size) { - /* Prepare page data. fill 0xff to unused region */ - memcpy(ni->page_cache, data, size); - memset(ni->page_cache + size, 0xff, ni->rawpage_size - size); - - success = nmbm_write_phys_page(ni, addr + off, ni->page_cache, NULL); - if (!success) - return false; - - /* Verify the data just written. ECC error indicates failure */ - ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL); - if (ret < 0) - return false; - - if (memcmp(ni->page_cache, data, size)) - return false; - } - - return true; -} - -/* - * nmbm_write_signature - Write signature to NAND chip - * @ni: NMBM instance structure - * @limit: top block address allowed for writing - * @signature: the signature to be written - * @signature_ba: the actual block address where signature is written to - * - * Write signature within a specific range, from chip bottom to limit. - * At most one block will be written. - * - * @limit is not counted into the allowed write address. - */ -static bool nmbm_write_signature(struct nmbm_instance *ni, uint32_t limit, - const struct nmbm_signature *signature, - uint32_t *signature_ba) -{ - uint32_t ba = ni->block_count - 1; - bool success; - - while (ba > limit) { - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - goto next_block; - - /* Insurance to detect unexpected bad block marked by user */ - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - goto next_block; - } - - success = nmbm_erase_block_and_check(ni, ba); - if (!success) - goto skip_bad_block; - - success = nmbm_write_repeated_data(ni, ba, signature, - sizeof(*signature)); - if (success) { - *signature_ba = ba; - return true; - } - - skip_bad_block: - nmbm_mark_phys_bad_block(ni, ba); - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - - next_block: - ba--; - }; - - return false; -} - -/* - * nmbn_read_data - Read data - * @ni: NMBM instance structure - * @addr: linear address where the data will be read from - * @data: the data to be read - * @size: the size of data - * - * Read data range. - * Every page will be tried for at most NMBM_TRY_COUNT times. - * - * Return 0 for success, positive value for corrected bitflip count, - * -EBADMSG for ecc error, other negative values for other errors - */ -static int nmbn_read_data(struct nmbm_instance *ni, uint64_t addr, void *data, - uint32_t size) -{ - uint64_t off = addr; - uint8_t *ptr = data; - uint32_t sizeremain = size, chunksize, leading; - int ret; - - while (sizeremain) { - leading = off & (bmtd.pg_size - 1); - chunksize = bmtd.pg_size - leading; - if (chunksize > sizeremain) - chunksize = sizeremain; - - if (chunksize == bmtd.pg_size) { - ret = nmbm_read_phys_page(ni, off - leading, ptr, NULL); - if (ret < 0) - return ret; - } else { - ret = nmbm_read_phys_page(ni, off - leading, - ni->page_cache, NULL); - if (ret < 0) - return ret; - - memcpy(ptr, ni->page_cache + leading, chunksize); - } - - off += chunksize; - ptr += chunksize; - sizeremain -= chunksize; - } - - return 0; -} - -/* - * nmbn_write_verify_data - Write data with validation - * @ni: NMBM instance structure - * @addr: linear address where the data will be written to - * @data: the data to be written - * @size: the size of data - * - * Write data and verify. - * Every page will be tried for at most NMBM_TRY_COUNT times. - */ -static bool nmbn_write_verify_data(struct nmbm_instance *ni, uint64_t addr, - const void *data, uint32_t size) -{ - uint64_t off = addr; - const uint8_t *ptr = data; - uint32_t sizeremain = size, chunksize, leading; - bool success; - int ret; - - while (sizeremain) { - leading = off & (bmtd.pg_size - 1); - chunksize = bmtd.pg_size - leading; - if (chunksize > sizeremain) - chunksize = sizeremain; - - /* Prepare page data. fill 0xff to unused region */ - memset(ni->page_cache, 0xff, ni->rawpage_size); - memcpy(ni->page_cache + leading, ptr, chunksize); - - success = nmbm_write_phys_page(ni, off - leading, - ni->page_cache, NULL); - if (!success) - return false; - - /* Verify the data just written. ECC error indicates failure */ - ret = nmbm_read_phys_page(ni, off - leading, ni->page_cache, NULL); - if (ret < 0) - return false; - - if (memcmp(ni->page_cache + leading, ptr, chunksize)) - return false; - - off += chunksize; - ptr += chunksize; - sizeremain -= chunksize; - } - - return true; -} - -/* - * nmbm_write_mgmt_range - Write management data into NAND within a range - * @ni: NMBM instance structure - * @addr: preferred start block address for writing - * @limit: highest block address allowed for writing - * @data: the data to be written - * @size: the size of data - * @actual_start_ba: actual start block address of data - * @actual_end_ba: block address after the end of data - * - * @limit is not counted into the allowed write address. - */ -static bool nmbm_write_mgmt_range(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit, const void *data, - uint32_t size, uint32_t *actual_start_ba, - uint32_t *actual_end_ba) -{ - const uint8_t *ptr = data; - uint32_t sizeremain = size, chunksize; - bool success; - - while (sizeremain && ba < limit) { - chunksize = sizeremain; - if (chunksize > bmtd.blk_size) - chunksize = bmtd.blk_size; - - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - goto next_block; - - /* Insurance to detect unexpected bad block marked by user */ - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - goto next_block; - } - - success = nmbm_erase_block_and_check(ni, ba); - if (!success) - goto skip_bad_block; - - success = nmbn_write_verify_data(ni, ba2addr(ni, ba), ptr, - chunksize); - if (!success) - goto skip_bad_block; - - if (sizeremain == size) - *actual_start_ba = ba; - - ptr += chunksize; - sizeremain -= chunksize; - - goto next_block; - - skip_bad_block: - nmbm_mark_phys_bad_block(ni, ba); - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - - next_block: - ba++; - } - - if (sizeremain) - return false; - - *actual_end_ba = ba; - - return true; -} - -/* - * nmbm_generate_info_table_cache - Generate info table cache data - * @ni: NMBM instance structure - * - * Generate info table cache data to be written into flash. - */ -static bool nmbm_generate_info_table_cache(struct nmbm_instance *ni) -{ - bool changed = false; - - memset(ni->info_table_cache, 0xff, ni->info_table_size); - - memcpy(ni->info_table_cache + ni->info_table.state_table_off, - ni->block_state, ni->state_table_size); - - memcpy(ni->info_table_cache + ni->info_table.mapping_table_off, - ni->block_mapping, ni->mapping_table_size); - - ni->info_table.header.magic = NMBM_MAGIC_INFO_TABLE; - ni->info_table.header.version = NMBM_VER; - ni->info_table.header.size = ni->info_table_size; - - if (ni->block_state_changed || ni->block_mapping_changed) { - ni->info_table.write_count++; - changed = true; - } - - memcpy(ni->info_table_cache, &ni->info_table, sizeof(ni->info_table)); - - nmbm_update_checksum((struct nmbm_header *)ni->info_table_cache); - - return changed; -} - -/* - * nmbm_write_info_table - Write info table into NAND within a range - * @ni: NMBM instance structure - * @ba: preferred start block address for writing - * @limit: highest block address allowed for writing - * @actual_start_ba: actual start block address of info table - * @actual_end_ba: block address after the end of info table - * - * @limit is counted into the allowed write address. - */ -static bool nmbm_write_info_table(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit, uint32_t *actual_start_ba, - uint32_t *actual_end_ba) -{ - return nmbm_write_mgmt_range(ni, ba, limit, ni->info_table_cache, - ni->info_table_size, actual_start_ba, - actual_end_ba); -} - -/* - * nmbm_mark_tables_clean - Mark info table `clean' - * @ni: NMBM instance structure - */ -static void nmbm_mark_tables_clean(struct nmbm_instance *ni) -{ - ni->block_state_changed = 0; - ni->block_mapping_changed = 0; -} - -/* - * nmbm_try_reserve_blocks - Reserve blocks with compromisation - * @ni: NMBM instance structure - * @ba: start physical block address - * @nba: return physical block address after reservation - * @count: number of good blocks to be skipped - * @min_count: minimum number of good blocks to be skipped - * @limit: highest/lowest block address allowed for walking - * - * Reserve specific blocks. If failed, try to reserve as many as possible. - */ -static bool nmbm_try_reserve_blocks(struct nmbm_instance *ni, uint32_t ba, - uint32_t *nba, uint32_t count, - int32_t min_count, int32_t limit) -{ - int32_t nblocks = count; - bool success; - - while (nblocks >= min_count) { - success = nmbm_block_walk(ni, true, ba, nba, nblocks, limit); - if (success) - return true; - - nblocks--; - } - - return false; -} - -/* - * nmbm_rebuild_info_table - Build main & backup info table from scratch - * @ni: NMBM instance structure - * @allow_no_gap: allow no spare blocks between two tables - */ -static bool nmbm_rebuild_info_table(struct nmbm_instance *ni) -{ - uint32_t table_start_ba, table_end_ba, next_start_ba; - uint32_t main_table_end_ba; - bool success; - - /* Set initial value */ - ni->main_table_ba = 0; - ni->backup_table_ba = 0; - ni->mapping_blocks_ba = ni->mapping_blocks_top_ba; - - /* Write main table */ - success = nmbm_write_info_table(ni, ni->mgmt_start_ba, - ni->mapping_blocks_top_ba, - &table_start_ba, &table_end_ba); - if (!success) { - /* Failed to write main table, data will be lost */ - nlog_err(ni, "Unable to write at least one info table!\n"); - nlog_err(ni, "Please save your data before power off!\n"); - ni->protected = 1; - return false; - } - - /* Main info table is successfully written, record its offset */ - ni->main_table_ba = table_start_ba; - main_table_end_ba = table_end_ba; - - /* Adjust mapping_blocks_ba */ - ni->mapping_blocks_ba = table_end_ba; - - nmbm_mark_tables_clean(ni); - - nlog_table_creation(ni, true, table_start_ba, table_end_ba); - - /* Reserve spare blocks for main info table. */ - success = nmbm_try_reserve_blocks(ni, table_end_ba, - &next_start_ba, - ni->info_table_spare_blocks, 0, - ni->mapping_blocks_top_ba - - size2blk(ni, ni->info_table_size)); - if (!success) { - /* There is no spare block. */ - nlog_debug(ni, "No room for backup info table\n"); - return true; - } - - /* Write backup info table. */ - success = nmbm_write_info_table(ni, next_start_ba, - ni->mapping_blocks_top_ba, - &table_start_ba, &table_end_ba); - if (!success) { - /* There is no enough blocks for backup table. */ - nlog_debug(ni, "No room for backup info table\n"); - return true; - } - - /* Backup table is successfully written, record its offset */ - ni->backup_table_ba = table_start_ba; - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = table_end_ba; - - /* Erase spare blocks of main table to clean possible interference data */ - nmbm_erase_range(ni, main_table_end_ba, ni->backup_table_ba); - - nlog_table_creation(ni, false, table_start_ba, table_end_ba); - - return true; -} - -/* - * nmbm_rescue_single_info_table - Rescue when there is only one info table - * @ni: NMBM instance structure - * - * This function is called when there is only one info table exists. - * This function may fail if we can't write new info table - */ -static bool nmbm_rescue_single_info_table(struct nmbm_instance *ni) -{ - uint32_t table_start_ba, table_end_ba, write_ba; - bool success; - - /* Try to write new info table in front of existing table */ - success = nmbm_write_info_table(ni, ni->mgmt_start_ba, - ni->main_table_ba, - &table_start_ba, - &table_end_ba); - if (success) { - /* - * New table becomes the main table, existing table becomes - * the backup table. - */ - ni->backup_table_ba = ni->main_table_ba; - ni->main_table_ba = table_start_ba; - - nmbm_mark_tables_clean(ni); - - /* Erase spare blocks of main table to clean possible interference data */ - nmbm_erase_range(ni, table_end_ba, ni->backup_table_ba); - - nlog_table_creation(ni, true, table_start_ba, table_end_ba); - - return true; - } - - /* Try to reserve spare blocks for existing table */ - success = nmbm_try_reserve_blocks(ni, ni->mapping_blocks_ba, &write_ba, - ni->info_table_spare_blocks, 0, - ni->mapping_blocks_top_ba - - size2blk(ni, ni->info_table_size)); - if (!success) { - nlog_warn(ni, "Failed to rescue single info table\n"); - return false; - } - - /* Try to write new info table next to the existing table */ - while (write_ba >= ni->mapping_blocks_ba) { - success = nmbm_write_info_table(ni, write_ba, - ni->mapping_blocks_top_ba, - &table_start_ba, - &table_end_ba); - if (success) - break; - - write_ba--; - } - - if (success) { - /* Erase spare blocks of main table to clean possible interference data */ - nmbm_erase_range(ni, ni->mapping_blocks_ba, table_start_ba); - - /* New table becomes the backup table */ - ni->backup_table_ba = table_start_ba; - ni->mapping_blocks_ba = table_end_ba; - - nmbm_mark_tables_clean(ni); - - nlog_table_creation(ni, false, table_start_ba, table_end_ba); - - return true; - } - - nlog_warn(ni, "Failed to rescue single info table\n"); - return false; -} - -/* - * nmbm_update_single_info_table - Update specific one info table - * @ni: NMBM instance structure - */ -static bool nmbm_update_single_info_table(struct nmbm_instance *ni, - bool update_main_table) -{ - uint32_t write_start_ba, write_limit, table_start_ba, table_end_ba; - bool success; - - /* Determine the write range */ - if (update_main_table) { - write_start_ba = ni->main_table_ba; - write_limit = ni->backup_table_ba; - } else { - write_start_ba = ni->backup_table_ba; - write_limit = ni->mapping_blocks_top_ba; - } - - success = nmbm_write_info_table(ni, write_start_ba, write_limit, - &table_start_ba, &table_end_ba); - if (success) { - if (update_main_table) { - ni->main_table_ba = table_start_ba; - } else { - ni->backup_table_ba = table_start_ba; - ni->mapping_blocks_ba = table_end_ba; - } - - nmbm_mark_tables_clean(ni); - - nlog_table_update(ni, update_main_table, table_start_ba, - table_end_ba); - - return true; - } - - if (update_main_table) { - /* - * If failed to update main table, make backup table the new - * main table, and call nmbm_rescue_single_info_table() - */ - nlog_warn(ni, "Unable to update %s info table\n", - update_main_table ? "Main" : "Backup"); - - ni->main_table_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - return nmbm_rescue_single_info_table(ni); - } - - /* Only one table left */ - ni->mapping_blocks_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - - return false; -} - -/* - * nmbm_rescue_main_info_table - Rescue when failed to write main info table - * @ni: NMBM instance structure - * - * This function is called when main info table failed to be written, and - * backup info table exists. - */ -static bool nmbm_rescue_main_info_table(struct nmbm_instance *ni) -{ - uint32_t tmp_table_start_ba, tmp_table_end_ba, main_table_start_ba; - uint32_t main_table_end_ba, write_ba; - uint32_t info_table_erasesize = size2blk(ni, ni->info_table_size); - bool success; - - /* Try to reserve spare blocks for existing backup info table */ - success = nmbm_try_reserve_blocks(ni, ni->mapping_blocks_ba, &write_ba, - ni->info_table_spare_blocks, 0, - ni->mapping_blocks_top_ba - - info_table_erasesize); - if (!success) { - /* There is no spare block. Backup info table becomes the main table. */ - nlog_err(ni, "No room for temporary info table\n"); - ni->main_table_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - return true; - } - - /* Try to write temporary info table into spare unmapped blocks */ - while (write_ba >= ni->mapping_blocks_ba) { - success = nmbm_write_info_table(ni, write_ba, - ni->mapping_blocks_top_ba, - &tmp_table_start_ba, - &tmp_table_end_ba); - if (success) - break; - - write_ba--; - } - - if (!success) { - /* Backup info table becomes the main table */ - nlog_err(ni, "Failed to update main info table\n"); - ni->main_table_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - return true; - } - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = tmp_table_end_ba; - - /* - * Now write main info table at the beginning of management area. - * This operation will generally destroy the original backup info - * table. - */ - success = nmbm_write_info_table(ni, ni->mgmt_start_ba, - tmp_table_start_ba, - &main_table_start_ba, - &main_table_end_ba); - if (!success) { - /* Temporary info table becomes the main table */ - ni->main_table_ba = tmp_table_start_ba; - ni->backup_table_ba = 0; - - nmbm_mark_tables_clean(ni); - - nlog_err(ni, "Failed to update main info table\n"); - - return true; - } - - /* Main info table has been successfully written, record its offset */ - ni->main_table_ba = main_table_start_ba; - - nmbm_mark_tables_clean(ni); - - nlog_table_creation(ni, true, main_table_start_ba, main_table_end_ba); - - /* - * Temporary info table becomes the new backup info table if it's - * not overwritten. - */ - if (main_table_end_ba <= tmp_table_start_ba) { - ni->backup_table_ba = tmp_table_start_ba; - - nlog_table_creation(ni, false, tmp_table_start_ba, - tmp_table_end_ba); - - return true; - } - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = main_table_end_ba; - - /* Try to reserve spare blocks for new main info table */ - success = nmbm_try_reserve_blocks(ni, main_table_end_ba, &write_ba, - ni->info_table_spare_blocks, 0, - ni->mapping_blocks_top_ba - - info_table_erasesize); - if (!success) { - /* There is no spare block. Only main table exists. */ - nlog_err(ni, "No room for backup info table\n"); - ni->backup_table_ba = 0; - return true; - } - - /* Write new backup info table. */ - while (write_ba >= main_table_end_ba) { - success = nmbm_write_info_table(ni, write_ba, - ni->mapping_blocks_top_ba, - &tmp_table_start_ba, - &tmp_table_end_ba); - if (success) - break; - - write_ba--; - } - - if (!success) { - nlog_err(ni, "No room for backup info table\n"); - ni->backup_table_ba = 0; - return true; - } - - /* Backup info table has been successfully written, record its offset */ - ni->backup_table_ba = tmp_table_start_ba; - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = tmp_table_end_ba; - - /* Erase spare blocks of main table to clean possible interference data */ - nmbm_erase_range(ni, main_table_end_ba, ni->backup_table_ba); - - nlog_table_creation(ni, false, tmp_table_start_ba, tmp_table_end_ba); - - return true; -} - -/* - * nmbm_update_info_table_once - Update info table once - * @ni: NMBM instance structure - * @force: force update - * - * Update both main and backup info table. Return true if at least one info - * table has been successfully written. - * This function only try to update info table once regard less of the result. - */ -static bool nmbm_update_info_table_once(struct nmbm_instance *ni, bool force) -{ - uint32_t table_start_ba, table_end_ba; - uint32_t main_table_limit; - bool success; - - /* Do nothing if there is no change */ - if (!nmbm_generate_info_table_cache(ni) && !force) - return true; - - /* Check whether both two tables exist */ - if (!ni->backup_table_ba) { - main_table_limit = ni->mapping_blocks_top_ba; - goto write_main_table; - } - - /* - * Write backup info table in its current range. - * Note that limit is set to mapping_blocks_top_off to provide as many - * spare blocks as possible for the backup table. If at last - * unmapped blocks are used by backup table, mapping_blocks_off will - * be adjusted. - */ - success = nmbm_write_info_table(ni, ni->backup_table_ba, - ni->mapping_blocks_top_ba, - &table_start_ba, &table_end_ba); - if (!success) { - /* - * There is nothing to do if failed to write backup table. - * Write the main table now. - */ - nlog_err(ni, "No room for backup table\n"); - ni->mapping_blocks_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - main_table_limit = ni->mapping_blocks_top_ba; - goto write_main_table; - } - - /* Backup table is successfully written, record its offset */ - ni->backup_table_ba = table_start_ba; - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = table_end_ba; - - nmbm_mark_tables_clean(ni); - - /* The normal limit of main table */ - main_table_limit = ni->backup_table_ba; - - nlog_table_update(ni, false, table_start_ba, table_end_ba); - -write_main_table: - if (!ni->main_table_ba) - goto rebuild_tables; - - /* Write main info table in its current range */ - success = nmbm_write_info_table(ni, ni->main_table_ba, - main_table_limit, &table_start_ba, - &table_end_ba); - if (!success) { - /* If failed to write main table, go rescue procedure */ - if (!ni->backup_table_ba) - goto rebuild_tables; - - return nmbm_rescue_main_info_table(ni); - } - - /* Main info table is successfully written, record its offset */ - ni->main_table_ba = table_start_ba; - - /* Adjust mapping_blocks_off */ - if (!ni->backup_table_ba) - ni->mapping_blocks_ba = table_end_ba; - - nmbm_mark_tables_clean(ni); - - nlog_table_update(ni, true, table_start_ba, table_end_ba); - - return true; - -rebuild_tables: - return nmbm_rebuild_info_table(ni); -} - -/* - * nmbm_update_info_table - Update info table - * @ni: NMBM instance structure - * - * Update both main and backup info table. Return true if at least one table - * has been successfully written. - * This function will try to update info table repeatedly until no new bad - * block found during updating. - */ -static bool nmbm_update_info_table(struct nmbm_instance *ni) -{ - bool success; - - if (ni->protected) - return true; - - while (ni->block_state_changed || ni->block_mapping_changed) { - success = nmbm_update_info_table_once(ni, false); - if (!success) { - nlog_err(ni, "Failed to update info table\n"); - return false; - } - } - - return true; -} - -/* - * nmbm_map_block - Map a bad block to a unused spare block - * @ni: NMBM instance structure - * @lb: logic block addr to map - */ -static bool nmbm_map_block(struct nmbm_instance *ni, uint32_t lb) -{ - uint32_t pb; - bool success; - - if (ni->mapping_blocks_ba == ni->mapping_blocks_top_ba) { - nlog_warn(ni, "No spare unmapped blocks.\n"); - return false; - } - - success = nmbm_block_walk(ni, false, ni->mapping_blocks_top_ba, &pb, 0, - ni->mapping_blocks_ba); - if (!success) { - nlog_warn(ni, "No spare unmapped blocks.\n"); - nmbm_update_info_table(ni); - ni->mapping_blocks_top_ba = ni->mapping_blocks_ba; - return false; - } - - ni->block_mapping[lb] = pb; - ni->mapping_blocks_top_ba--; - ni->block_mapping_changed++; - - nlog_info(ni, "Logic block %u mapped to physical block %u\n", lb, pb); - - return true; -} - -/* - * nmbm_create_info_table - Create info table(s) - * @ni: NMBM instance structure - * - * This function assumes that the chip has no existing info table(s) - */ -static bool nmbm_create_info_table(struct nmbm_instance *ni) -{ - uint32_t lb; - bool success; - - /* Set initial mapping_blocks_top_off */ - success = nmbm_block_walk(ni, false, ni->signature_ba, - &ni->mapping_blocks_top_ba, 1, - ni->mgmt_start_ba); - if (!success) { - nlog_err(ni, "No room for spare blocks\n"); - return false; - } - - /* Generate info table cache */ - nmbm_generate_info_table_cache(ni); - - /* Write info table */ - success = nmbm_rebuild_info_table(ni); - if (!success) { - nlog_err(ni, "Failed to build info tables\n"); - return false; - } - - /* Remap bad block(s) at end of data area */ - for (lb = ni->data_block_count; lb < ni->mgmt_start_ba; lb++) { - success = nmbm_map_block(ni, lb); - if (!success) - break; - - ni->data_block_count++; - } - - /* If state table and/or mapping table changed, update info table. */ - success = nmbm_update_info_table(ni); - if (!success) - return false; - - return true; -} - -/* - * nmbm_create_new - Create NMBM on a new chip - * @ni: NMBM instance structure - */ -static bool nmbm_create_new(struct nmbm_instance *ni) -{ - bool success; - - /* Determine the boundary of management blocks */ - ni->mgmt_start_ba = ni->block_count * (NMBM_MGMT_DIV - ni->max_ratio) / NMBM_MGMT_DIV; - - if (ni->max_reserved_blocks && ni->block_count - ni->mgmt_start_ba > ni->max_reserved_blocks) - ni->mgmt_start_ba = ni->block_count - ni->max_reserved_blocks; - - nlog_info(ni, "NMBM management region starts at block %u [0x%08llx]\n", - ni->mgmt_start_ba, ba2addr(ni, ni->mgmt_start_ba)); - - /* Fill block state table & mapping table */ - nmbm_scan_badblocks(ni); - nmbm_build_mapping_table(ni); - - /* Write signature */ - ni->signature.header.magic = NMBM_MAGIC_SIGNATURE; - ni->signature.header.version = NMBM_VER; - ni->signature.header.size = sizeof(ni->signature); - ni->signature.nand_size = bmtd.total_blks << bmtd.blk_shift; - ni->signature.block_size = bmtd.blk_size; - ni->signature.page_size = bmtd.pg_size; - ni->signature.spare_size = bmtd.mtd->oobsize; - ni->signature.mgmt_start_pb = ni->mgmt_start_ba; - ni->signature.max_try_count = NMBM_TRY_COUNT; - nmbm_update_checksum(&ni->signature.header); - - success = nmbm_write_signature(ni, ni->mgmt_start_ba, - &ni->signature, &ni->signature_ba); - if (!success) { - nlog_err(ni, "Failed to write signature to a proper offset\n"); - return false; - } - - nlog_info(ni, "Signature has been written to block %u [0x%08llx]\n", - ni->signature_ba, ba2addr(ni, ni->signature_ba)); - - /* Write info table(s) */ - success = nmbm_create_info_table(ni); - if (success) { - nlog_info(ni, "NMBM has been successfully created\n"); - return true; - } - - return false; -} - -/* - * nmbm_check_info_table_header - Check if a info table header is valid - * @ni: NMBM instance structure - * @data: pointer to the info table header - */ -static bool nmbm_check_info_table_header(struct nmbm_instance *ni, void *data) -{ - struct nmbm_info_table_header *ifthdr = data; - - if (ifthdr->header.magic != NMBM_MAGIC_INFO_TABLE) - return false; - - if (ifthdr->header.size != ni->info_table_size) - return false; - - if (ifthdr->mapping_table_off - ifthdr->state_table_off < ni->state_table_size) - return false; - - if (ni->info_table_size - ifthdr->mapping_table_off < ni->mapping_table_size) - return false; - - return true; -} - -/* - * nmbm_check_info_table - Check if a whole info table is valid - * @ni: NMBM instance structure - * @start_ba: start block address of this table - * @end_ba: end block address of this table - * @data: pointer to the info table header - * @mapping_blocks_top_ba: return the block address of top remapped block - */ -static bool nmbm_check_info_table(struct nmbm_instance *ni, uint32_t start_ba, - uint32_t end_ba, void *data, - uint32_t *mapping_blocks_top_ba) -{ - struct nmbm_info_table_header *ifthdr = data; - int32_t *block_mapping = (int32_t *)((uintptr_t)data + ifthdr->mapping_table_off); - u32 *block_state = (u32 *)((uintptr_t)data + ifthdr->state_table_off); - uint32_t minimum_mapping_pb = ni->signature_ba; - uint32_t ba; - - for (ba = 0; ba < ni->data_block_count; ba++) { - if ((block_mapping[ba] >= ni->data_block_count && block_mapping[ba] < end_ba) || - block_mapping[ba] == ni->signature_ba) - return false; - - if (block_mapping[ba] >= end_ba && block_mapping[ba] < minimum_mapping_pb) - minimum_mapping_pb = block_mapping[ba]; - } - - for (ba = start_ba; ba < end_ba; ba++) { - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - continue; - - if (nmbm_get_block_state_raw(block_state, ba) != BLOCK_ST_GOOD) - return false; - } - - *mapping_blocks_top_ba = minimum_mapping_pb - 1; - - return true; -} - -/* - * nmbm_try_load_info_table - Try to load info table from a address - * @ni: NMBM instance structure - * @ba: start block address of the info table - * @eba: return the block address after end of the table - * @write_count: return the write count of this table - * @mapping_blocks_top_ba: return the block address of top remapped block - * @table_loaded: used to record whether ni->info_table has valid data - */ -static bool nmbm_try_load_info_table(struct nmbm_instance *ni, uint32_t ba, - uint32_t *eba, uint32_t *write_count, - uint32_t *mapping_blocks_top_ba, - bool table_loaded) -{ - struct nmbm_info_table_header *ifthdr = (void *)ni->info_table_cache; - uint8_t *off = ni->info_table_cache; - uint32_t limit = ba + size2blk(ni, ni->info_table_size); - uint32_t start_ba = 0, chunksize, sizeremain = ni->info_table_size; - bool success, checkhdr = true; - int ret; - - while (sizeremain && ba < limit) { - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - goto next_block; - - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - goto next_block; - } - - chunksize = sizeremain; - if (chunksize > bmtd.blk_size) - chunksize = bmtd.blk_size; - - /* Assume block with ECC error has no info table data */ - ret = nmbn_read_data(ni, ba2addr(ni, ba), off, chunksize); - if (ret < 0) - goto skip_bad_block; - else if (ret > 0) - return false; - - if (checkhdr) { - success = nmbm_check_info_table_header(ni, off); - if (!success) - return false; - - start_ba = ba; - checkhdr = false; - } - - off += chunksize; - sizeremain -= chunksize; - - goto next_block; - - skip_bad_block: - /* Only mark bad in memory */ - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - - next_block: - ba++; - } - - if (sizeremain) - return false; - - success = nmbm_check_header(ni->info_table_cache, ni->info_table_size); - if (!success) - return false; - - *eba = ba; - *write_count = ifthdr->write_count; - - success = nmbm_check_info_table(ni, start_ba, ba, ni->info_table_cache, - mapping_blocks_top_ba); - if (!success) - return false; - - if (!table_loaded || ifthdr->write_count > ni->info_table.write_count) { - memcpy(&ni->info_table, ifthdr, sizeof(ni->info_table)); - memcpy(ni->block_state, - (uint8_t *)ifthdr + ifthdr->state_table_off, - ni->state_table_size); - memcpy(ni->block_mapping, - (uint8_t *)ifthdr + ifthdr->mapping_table_off, - ni->mapping_table_size); - ni->info_table.write_count = ifthdr->write_count; - } - - return true; -} - -/* - * nmbm_search_info_table - Search info table from specific address - * @ni: NMBM instance structure - * @ba: start block address to search - * @limit: highest block address allowed for searching - * @table_start_ba: return the start block address of this table - * @table_end_ba: return the block address after end of this table - * @write_count: return the write count of this table - * @mapping_blocks_top_ba: return the block address of top remapped block - * @table_loaded: used to record whether ni->info_table has valid data - */ -static bool nmbm_search_info_table(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit, uint32_t *table_start_ba, - uint32_t *table_end_ba, - uint32_t *write_count, - uint32_t *mapping_blocks_top_ba, - bool table_loaded) -{ - bool success; - - while (ba < limit - size2blk(ni, ni->info_table_size)) { - success = nmbm_try_load_info_table(ni, ba, table_end_ba, - write_count, - mapping_blocks_top_ba, - table_loaded); - if (success) { - *table_start_ba = ba; - return true; - } - - ba++; - } - - return false; -} - -/* - * nmbm_load_info_table - Load info table(s) from a chip - * @ni: NMBM instance structure - * @ba: start block address to search info table - * @limit: highest block address allowed for searching - */ -static bool nmbm_load_info_table(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit) -{ - uint32_t main_table_end_ba, backup_table_end_ba, table_end_ba; - uint32_t main_mapping_blocks_top_ba, backup_mapping_blocks_top_ba; - uint32_t main_table_write_count, backup_table_write_count; - uint32_t i; - bool success; - - /* Set initial value */ - ni->main_table_ba = 0; - ni->backup_table_ba = 0; - ni->info_table.write_count = 0; - ni->mapping_blocks_top_ba = ni->signature_ba - 1; - ni->data_block_count = ni->signature.mgmt_start_pb; - - /* Find first info table */ - success = nmbm_search_info_table(ni, ba, limit, &ni->main_table_ba, - &main_table_end_ba, &main_table_write_count, - &main_mapping_blocks_top_ba, false); - if (!success) { - nlog_warn(ni, "No valid info table found\n"); - return false; - } - - table_end_ba = main_table_end_ba; - - nlog_table_found(ni, true, main_table_write_count, ni->main_table_ba, - main_table_end_ba); - - /* Find second info table */ - success = nmbm_search_info_table(ni, main_table_end_ba, limit, - &ni->backup_table_ba, &backup_table_end_ba, - &backup_table_write_count, &backup_mapping_blocks_top_ba, true); - if (!success) { - nlog_warn(ni, "Second info table not found\n"); - } else { - table_end_ba = backup_table_end_ba; - - nlog_table_found(ni, false, backup_table_write_count, - ni->backup_table_ba, backup_table_end_ba); - } - - /* Pick mapping_blocks_top_ba */ - if (!ni->backup_table_ba) { - ni->mapping_blocks_top_ba= main_mapping_blocks_top_ba; - } else { - if (main_table_write_count >= backup_table_write_count) - ni->mapping_blocks_top_ba = main_mapping_blocks_top_ba; - else - ni->mapping_blocks_top_ba = backup_mapping_blocks_top_ba; - } - - /* Set final mapping_blocks_ba */ - ni->mapping_blocks_ba = table_end_ba; - - /* Set final data_block_count */ - for (i = ni->signature.mgmt_start_pb; i > 0; i--) { - if (ni->block_mapping[i - 1] >= 0) { - ni->data_block_count = i; - break; - } - } - - /* Regenerate the info table cache from the final selected info table */ - nmbm_generate_info_table_cache(ni); - - /* - * If only one table exists, try to write another table. - * If two tables have different write count, try to update info table - */ - if (!ni->backup_table_ba) { - success = nmbm_rescue_single_info_table(ni); - } else if (main_table_write_count != backup_table_write_count) { - /* Mark state & mapping tables changed */ - ni->block_state_changed = 1; - ni->block_mapping_changed = 1; - - success = nmbm_update_single_info_table(ni, - main_table_write_count < backup_table_write_count); - } else { - success = true; - } - - /* - * If there is no spare unmapped blocks, or still only one table - * exists, set the chip to read-only - */ - if (ni->mapping_blocks_ba == ni->mapping_blocks_top_ba) { - nlog_warn(ni, "No spare unmapped blocks. Device is now read-only\n"); - ni->protected = 1; - } else if (!success) { - nlog_warn(ni, "Only one info table found. Device is now read-only\n"); - ni->protected = 1; - } - - return true; -} - -/* - * nmbm_load_existing - Load NMBM from a new chip - * @ni: NMBM instance structure - */ -static bool nmbm_load_existing(struct nmbm_instance *ni) -{ - bool success; - - /* Calculate the boundary of management blocks */ - ni->mgmt_start_ba = ni->signature.mgmt_start_pb; - - nlog_debug(ni, "NMBM management region starts at block %u [0x%08llx]\n", - ni->mgmt_start_ba, ba2addr(ni, ni->mgmt_start_ba)); - - /* Look for info table(s) */ - success = nmbm_load_info_table(ni, ni->mgmt_start_ba, - ni->signature_ba); - if (success) { - nlog_info(ni, "NMBM has been successfully attached\n"); - return true; - } - - if (!ni->force_create) { - printk("not creating NMBM table\n"); - return false; - } - - /* Fill block state table & mapping table */ - nmbm_scan_badblocks(ni); - nmbm_build_mapping_table(ni); - - /* Write info table(s) */ - success = nmbm_create_info_table(ni); - if (success) { - nlog_info(ni, "NMBM has been successfully created\n"); - return true; - } - - return false; -} - -/* - * nmbm_find_signature - Find signature in the lower NAND chip - * @ni: NMBM instance structure - * @signature_ba: used for storing block address of the signature - * @signature_ba: return the actual block address of signature block - * - * Find a valid signature from a specific range in the lower NAND chip, - * from bottom (highest address) to top (lowest address) - * - * Return true if found. - */ -static bool nmbm_find_signature(struct nmbm_instance *ni, - struct nmbm_signature *signature, - uint32_t *signature_ba) -{ - struct nmbm_signature sig; - uint64_t off, addr; - uint32_t block_count, ba, limit; - bool success; - int ret; - - /* Calculate top and bottom block address */ - block_count = bmtd.total_blks; - ba = block_count; - limit = (block_count / NMBM_MGMT_DIV) * (NMBM_MGMT_DIV - ni->max_ratio); - if (ni->max_reserved_blocks && block_count - limit > ni->max_reserved_blocks) - limit = block_count - ni->max_reserved_blocks; - - while (ba >= limit) { - ba--; - addr = ba2addr(ni, ba); - - if (nmbm_check_bad_phys_block(ni, ba)) - continue; - - /* Check every page. - * As long as at leaset one page contains valid signature, - * the block is treated as a valid signature block. - */ - for (off = 0; off < bmtd.blk_size; - off += bmtd.pg_size) { - ret = nmbn_read_data(ni, addr + off, &sig, - sizeof(sig)); - if (ret) - continue; - - /* Check for header size and checksum */ - success = nmbm_check_header(&sig, sizeof(sig)); - if (!success) - continue; - - /* Check for header magic */ - if (sig.header.magic == NMBM_MAGIC_SIGNATURE) { - /* Found it */ - memcpy(signature, &sig, sizeof(sig)); - *signature_ba = ba; - return true; - } - } - }; - - return false; -} - -/* - * nmbm_calc_structure_size - Calculate the instance structure size - * @nld: NMBM lower device structure - */ -static size_t nmbm_calc_structure_size(void) -{ - uint32_t state_table_size, mapping_table_size, info_table_size; - uint32_t block_count; - - block_count = bmtd.total_blks; - - /* Calculate info table size */ - state_table_size = ((block_count + NMBM_BITMAP_BLOCKS_PER_UNIT - 1) / - NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_UNIT_SIZE; - mapping_table_size = block_count * sizeof(int32_t); - - info_table_size = ALIGN(sizeof(struct nmbm_info_table_header), - bmtd.pg_size); - info_table_size += ALIGN(state_table_size, bmtd.pg_size); - info_table_size += ALIGN(mapping_table_size, bmtd.pg_size); - - return info_table_size + state_table_size + mapping_table_size + - sizeof(struct nmbm_instance); -} - -/* - * nmbm_init_structure - Initialize members of instance structure - * @ni: NMBM instance structure - */ -static void nmbm_init_structure(struct nmbm_instance *ni) -{ - uint32_t pages_per_block, blocks_per_chip; - uintptr_t ptr; - - pages_per_block = bmtd.blk_size / bmtd.pg_size; - blocks_per_chip = bmtd.total_blks; - - ni->rawpage_size = bmtd.pg_size + bmtd.mtd->oobsize; - ni->rawblock_size = pages_per_block * ni->rawpage_size; - ni->rawchip_size = blocks_per_chip * ni->rawblock_size; - - /* Calculate number of block this chip */ - ni->block_count = blocks_per_chip; - - /* Calculate info table size */ - ni->state_table_size = ((ni->block_count + NMBM_BITMAP_BLOCKS_PER_UNIT - 1) / - NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_UNIT_SIZE; - ni->mapping_table_size = ni->block_count * sizeof(*ni->block_mapping); - - ni->info_table_size = ALIGN(sizeof(ni->info_table), - bmtd.pg_size); - ni->info_table.state_table_off = ni->info_table_size; - - ni->info_table_size += ALIGN(ni->state_table_size, - bmtd.pg_size); - ni->info_table.mapping_table_off = ni->info_table_size; - - ni->info_table_size += ALIGN(ni->mapping_table_size, - bmtd.pg_size); - - ni->info_table_spare_blocks = nmbm_get_spare_block_count( - size2blk(ni, ni->info_table_size)); - - /* Assign memory to members */ - ptr = (uintptr_t)ni + sizeof(*ni); - - ni->info_table_cache = (void *)ptr; - ptr += ni->info_table_size; - - ni->block_state = (void *)ptr; - ptr += ni->state_table_size; - - ni->block_mapping = (void *)ptr; - ptr += ni->mapping_table_size; - - ni->page_cache = bmtd.data_buf; - - /* Initialize block state table */ - ni->block_state_changed = 0; - memset(ni->block_state, 0xff, ni->state_table_size); - - /* Initialize block mapping table */ - ni->block_mapping_changed = 0; -} - -/* - * nmbm_attach - Attach to a lower device - * @ni: NMBM instance structure - */ -static int nmbm_attach(struct nmbm_instance *ni) -{ - bool success; - - if (!ni) - return -EINVAL; - - /* Initialize NMBM instance */ - nmbm_init_structure(ni); - - success = nmbm_find_signature(ni, &ni->signature, &ni->signature_ba); - if (!success) { - if (!ni->force_create) { - nlog_err(ni, "Signature not found\n"); - return -ENODEV; - } - - success = nmbm_create_new(ni); - if (!success) - return -ENODEV; - - return 0; - } - - nlog_info(ni, "Signature found at block %u [0x%08llx]\n", - ni->signature_ba, ba2addr(ni, ni->signature_ba)); - - if (ni->signature.header.version != NMBM_VER) { - nlog_err(ni, "NMBM version %u.%u is not supported\n", - NMBM_VERSION_MAJOR_GET(ni->signature.header.version), - NMBM_VERSION_MINOR_GET(ni->signature.header.version)); - return -EINVAL; - } - - if (ni->signature.nand_size != bmtd.total_blks << bmtd.blk_shift || - ni->signature.block_size != bmtd.blk_size || - ni->signature.page_size != bmtd.pg_size || - ni->signature.spare_size != bmtd.mtd->oobsize) { - nlog_err(ni, "NMBM configuration mismatch\n"); - return -EINVAL; - } - - success = nmbm_load_existing(ni); - if (!success) - return -ENODEV; - - return 0; -} - -static bool remap_block_nmbm(u16 block, u16 mapped_block, int copy_len) -{ - struct nmbm_instance *ni = bmtd.ni; - int new_block; - - if (block >= ni->data_block_count) - return false; - - nmbm_set_block_state(ni, mapped_block, BLOCK_ST_BAD); - if (!nmbm_map_block(ni, block)) - return false; - - new_block = ni->block_mapping[block]; - bbt_nand_erase(new_block); - if (copy_len > 0) - bbt_nand_copy(new_block, mapped_block, copy_len); - nmbm_update_info_table(ni); - - return true; -} - -static int get_mapping_block_index_nmbm(int block) -{ - struct nmbm_instance *ni = bmtd.ni; - - if (block >= ni->data_block_count) - return -1; - - return ni->block_mapping[block]; -} - -static int mtk_bmt_init_nmbm(struct device_node *np) -{ - struct nmbm_instance *ni; - int ret; - - ni = kzalloc(nmbm_calc_structure_size(), GFP_KERNEL); - if (!ni) - return -ENOMEM; - - bmtd.ni = ni; - - if (of_property_read_u32(np, "mediatek,bmt-max-ratio", &ni->max_ratio)) - ni->max_ratio = 1; - if (of_property_read_u32(np, "mediatek,bmt-max-reserved-blocks", - &ni->max_reserved_blocks)) - ni->max_reserved_blocks = 256; - if (of_property_read_bool(np, "mediatek,empty-page-ecc-protected")) - ni->empty_page_ecc_ok = true; - if (of_property_read_bool(np, "mediatek,bmt-force-create")) - ni->force_create = true; - - ret = nmbm_attach(ni); - if (ret) - goto out; - - bmtd.mtd->size = ni->data_block_count << bmtd.blk_shift; - - return 0; - -out: - kfree(ni); - bmtd.ni = NULL; - - return ret; -} - -static int mtk_bmt_debug_nmbm(void *data, u64 val) -{ - struct nmbm_instance *ni = bmtd.ni; - int i; - - switch (val) { - case 0: - for (i = 1; i < ni->data_block_count; i++) { - if (ni->block_mapping[i] < ni->mapping_blocks_ba) - continue; - - printk("remap [%x->%x]\n", i, ni->block_mapping[i]); - } - } - - return 0; -} - -static void unmap_block_nmbm(u16 block) -{ - struct nmbm_instance *ni = bmtd.ni; - int start, offset; - int new_block; - - if (block >= ni->data_block_count) - return; - - start = block; - offset = 0; - while (ni->block_mapping[start] >= ni->mapping_blocks_ba) { - start--; - offset++; - if (start < 0) - return; - } - - if (!offset) - return; - - new_block = ni->block_mapping[start] + offset; - nmbm_set_block_state(ni, new_block, BLOCK_ST_GOOD); - ni->block_mapping[block] = new_block; - ni->block_mapping_changed++; - - new_block = ni->signature_ba - 1; - for (block = 0; block < ni->data_block_count; block++) { - int cur = ni->block_mapping[block]; - - if (cur < ni->mapping_blocks_ba) - continue; - - if (cur <= new_block) - new_block = cur - 1; - } - - ni->mapping_blocks_top_ba = new_block; - - nmbm_update_info_table(ni); -} - -const struct mtk_bmt_ops mtk_bmt_nmbm_ops = { - .init = mtk_bmt_init_nmbm, - .remap_block = remap_block_nmbm, - .unmap_block = unmap_block_nmbm, - .get_mapping_block = get_mapping_block_index_nmbm, - .debug = mtk_bmt_debug_nmbm, -}; diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_v2.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_v2.c deleted file mode 100644 index 6b06948c0..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nand/mtk_bmt_v2.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Copyright (c) 2017 MediaTek Inc. - * Author: Xiangsheng Hou - * Copyright (c) 2020-2022 Felix Fietkau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include "mtk_bmt.h" - -struct bbbt { - char signature[3]; - /* This version is used to distinguish the legacy and new algorithm */ -#define BBMT_VERSION 2 - unsigned char version; - /* Below 2 tables will be written in SLC */ - u16 bb_tbl[]; -}; - -struct bbmt { - u16 block; -#define NO_MAPPED 0 -#define NORMAL_MAPPED 1 -#define BMT_MAPPED 2 - u16 mapped; -}; - -/* Maximum 8k blocks */ -#define BBPOOL_RATIO 2 -#define BB_TABLE_MAX bmtd.table_size -#define BMT_TABLE_MAX (BB_TABLE_MAX * BBPOOL_RATIO / 100) -#define BMT_TBL_DEF_VAL 0x0 - -static inline struct bbmt *bmt_tbl(struct bbbt *bbbt) -{ - return (struct bbmt *)&bbbt->bb_tbl[bmtd.table_size]; -} - -static u16 find_valid_block(u16 block) -{ - u8 fdm[4]; - int ret; - int loop = 0; - -retry: - if (block >= bmtd.total_blks) - return 0; - - ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size, - fdm, sizeof(fdm)); - /* Read the 1st byte of FDM to judge whether it's a bad - * or not - */ - if (ret || fdm[0] != 0xff) { - pr_info("nand: found bad block 0x%x\n", block); - if (loop >= bmtd.bb_max) { - pr_info("nand: FATAL ERR: too many bad blocks!!\n"); - return 0; - } - - loop++; - block++; - goto retry; - } - - return block; -} - -/* Find out all bad blocks, and fill in the mapping table */ -static int scan_bad_blocks(struct bbbt *bbt) -{ - int i; - u16 block = 0; - - /* First time download, the block0 MUST NOT be a bad block, - * this is guaranteed by vendor - */ - bbt->bb_tbl[0] = 0; - - /* - * Construct the mapping table of Normal data area(non-PMT/BMTPOOL) - * G - Good block; B - Bad block - * --------------------------- - * physical |G|G|B|G|B|B|G|G|G|G|B|G|B| - * --------------------------- - * What bb_tbl[i] looks like: - * physical block(i): - * 0 1 2 3 4 5 6 7 8 9 a b c - * mapped block(bb_tbl[i]): - * 0 1 3 6 7 8 9 b ...... - * ATTENTION: - * If new bad block ocurred(n), search bmt_tbl to find - * a available block(x), and fill in the bb_tbl[n] = x; - */ - for (i = 1; i < bmtd.pool_lba; i++) { - bbt->bb_tbl[i] = find_valid_block(bbt->bb_tbl[i - 1] + 1); - BBT_LOG("bb_tbl[0x%x] = 0x%x", i, bbt->bb_tbl[i]); - if (bbt->bb_tbl[i] == 0) - return -1; - } - - /* Physical Block start Address of BMT pool */ - bmtd.pool_pba = bbt->bb_tbl[i - 1] + 1; - if (bmtd.pool_pba >= bmtd.total_blks - 2) { - pr_info("nand: FATAL ERR: Too many bad blocks!!\n"); - return -1; - } - - BBT_LOG("pool_pba=0x%x", bmtd.pool_pba); - i = 0; - block = bmtd.pool_pba; - /* - * The bmt table is used for runtime bad block mapping - * G - Good block; B - Bad block - * --------------------------- - * physical |G|G|B|G|B|B|G|G|G|G|B|G|B| - * --------------------------- - * block: 0 1 2 3 4 5 6 7 8 9 a b c - * What bmt_tbl[i] looks like in initial state: - * i: - * 0 1 2 3 4 5 6 7 - * bmt_tbl[i].block: - * 0 1 3 6 7 8 9 b - * bmt_tbl[i].mapped: - * N N N N N N N B - * N - Not mapped(Available) - * M - Mapped - * B - BMT - * ATTENTION: - * BMT always in the last valid block in pool - */ - while ((block = find_valid_block(block)) != 0) { - bmt_tbl(bbt)[i].block = block; - bmt_tbl(bbt)[i].mapped = NO_MAPPED; - BBT_LOG("bmt_tbl[%d].block = 0x%x", i, block); - block++; - i++; - } - - /* i - How many available blocks in pool, which is the length of bmt_tbl[] - * bmtd.bmt_blk_idx - bmt_tbl[bmtd.bmt_blk_idx].block => the BMT block - */ - bmtd.bmt_blk_idx = i - 1; - bmt_tbl(bbt)[bmtd.bmt_blk_idx].mapped = BMT_MAPPED; - - if (i < 1) { - pr_info("nand: FATAL ERR: no space to store BMT!!\n"); - return -1; - } - - pr_info("[BBT] %d available blocks in BMT pool\n", i); - - return 0; -} - -static bool is_valid_bmt(unsigned char *buf, unsigned char *fdm) -{ - struct bbbt *bbt = (struct bbbt *)buf; - u8 *sig = (u8*)bbt->signature + MAIN_SIGNATURE_OFFSET; - - - if (memcmp(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3) == 0 && - memcmp(fdm + OOB_SIGNATURE_OFFSET, "bmt", 3) == 0) { - if (bbt->version == BBMT_VERSION) - return true; - } - BBT_LOG("[BBT] BMT Version not match,upgrage preloader and uboot please! sig=%02x%02x%02x, fdm=%02x%02x%02x", - sig[0], sig[1], sig[2], - fdm[1], fdm[2], fdm[3]); - return false; -} - -static u16 get_bmt_index(struct bbmt *bmt) -{ - int i = 0; - - while (bmt[i].block != BMT_TBL_DEF_VAL) { - if (bmt[i].mapped == BMT_MAPPED) - return i; - i++; - } - return 0; -} - -/* Write the Burner Bad Block Table to Nand Flash - * n - write BMT to bmt_tbl[n] - */ -static u16 upload_bmt(struct bbbt *bbt, int n) -{ - u16 block; - -retry: - if (n < 0 || bmt_tbl(bbt)[n].mapped == NORMAL_MAPPED) { - pr_info("nand: FATAL ERR: no space to store BMT!\n"); - return (u16)-1; - } - - block = bmt_tbl(bbt)[n].block; - BBT_LOG("n = 0x%x, block = 0x%x", n, block); - if (bbt_nand_erase(block)) { - bmt_tbl(bbt)[n].block = 0; - /* erase failed, try the previous block: bmt_tbl[n - 1].block */ - n--; - goto retry; - } - - /* The signature offset is fixed set to 0, - * oob signature offset is fixed set to 1 - */ - memcpy(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3); - bbt->version = BBMT_VERSION; - - if (write_bmt(block, (unsigned char *)bbt)) { - bmt_tbl(bbt)[n].block = 0; - - /* write failed, try the previous block in bmt_tbl[n - 1] */ - n--; - goto retry; - } - - /* Return the current index(n) of BMT pool (bmt_tbl[n]) */ - return n; -} - -static u16 find_valid_block_in_pool(struct bbbt *bbt) -{ - int i; - - if (bmtd.bmt_blk_idx == 0) - goto error; - - for (i = 0; i < bmtd.bmt_blk_idx; i++) { - if (bmt_tbl(bbt)[i].block != 0 && bmt_tbl(bbt)[i].mapped == NO_MAPPED) { - bmt_tbl(bbt)[i].mapped = NORMAL_MAPPED; - return bmt_tbl(bbt)[i].block; - } - } - -error: - pr_info("nand: FATAL ERR: BMT pool is run out!\n"); - return 0; -} - -/* We met a bad block, mark it as bad and map it to a valid block in pool, - * if it's a write failure, we need to write the data to mapped block - */ -static bool remap_block_v2(u16 block, u16 mapped_block, int copy_len) -{ - u16 new_block; - struct bbbt *bbt; - - bbt = bmtd.bbt; - new_block = find_valid_block_in_pool(bbt); - if (new_block == 0) - return false; - - /* Map new bad block to available block in pool */ - bbt->bb_tbl[block] = new_block; - - /* Erase new block */ - bbt_nand_erase(new_block); - if (copy_len > 0) - bbt_nand_copy(new_block, mapped_block, copy_len); - - bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx); - - return true; -} - -static int get_mapping_block_index_v2(int block) -{ - int start, end; - - if (block >= bmtd.pool_lba) - return block; - - if (!mapping_block_in_range(block, &start, &end)) - return block; - - return bmtd.bbt->bb_tbl[block]; -} - -static void -unmap_block_v2(u16 block) -{ - bmtd.bbt->bb_tbl[block] = block; - bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx); -} - -static unsigned long * -mtk_bmt_get_mapping_mask(void) -{ - struct bbmt *bbmt = bmt_tbl(bmtd.bbt); - int main_blocks = bmtd.mtd->size >> bmtd.blk_shift; - unsigned long *used; - int i, k; - - used = kcalloc(sizeof(unsigned long), BIT_WORD(bmtd.bmt_blk_idx) + 1, GFP_KERNEL); - if (!used) - return NULL; - - for (i = 1; i < main_blocks; i++) { - if (bmtd.bbt->bb_tbl[i] == i) - continue; - - for (k = 0; k < bmtd.bmt_blk_idx; k++) { - if (bmtd.bbt->bb_tbl[i] != bbmt[k].block) - continue; - - set_bit(k, used); - break; - } - } - - return used; -} - -static int mtk_bmt_debug_v2(void *data, u64 val) -{ - struct bbmt *bbmt = bmt_tbl(bmtd.bbt); - struct mtd_info *mtd = bmtd.mtd; - unsigned long *used; - int main_blocks = mtd->size >> bmtd.blk_shift; - int n_remap = 0; - int i; - - used = mtk_bmt_get_mapping_mask(); - if (!used) - return -ENOMEM; - - switch (val) { - case 0: - for (i = 1; i < main_blocks; i++) { - if (bmtd.bbt->bb_tbl[i] == i) - continue; - - printk("remap [%x->%x]\n", i, bmtd.bbt->bb_tbl[i]); - n_remap++; - } - for (i = 0; i <= bmtd.bmt_blk_idx; i++) { - char c; - - switch (bbmt[i].mapped) { - case NO_MAPPED: - continue; - case NORMAL_MAPPED: - c = 'm'; - if (test_bit(i, used)) - c = 'M'; - break; - case BMT_MAPPED: - c = 'B'; - break; - default: - c = 'X'; - break; - } - printk("[%x:%c] = 0x%x\n", i, c, bbmt[i].block); - } - break; - case 100: - for (i = 0; i <= bmtd.bmt_blk_idx; i++) { - if (bbmt[i].mapped != NORMAL_MAPPED) - continue; - - if (test_bit(i, used)) - continue; - - n_remap++; - bbmt[i].mapped = NO_MAPPED; - printk("free block [%d:%x]\n", i, bbmt[i].block); - } - if (n_remap) - bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx); - break; - } - - kfree(used); - - return 0; -} - -static int mtk_bmt_init_v2(struct device_node *np) -{ - u32 bmt_pool_size, bmt_table_size; - u32 bufsz, block; - u16 pmt_block; - - if (of_property_read_u32(np, "mediatek,bmt-pool-size", - &bmt_pool_size) != 0) - bmt_pool_size = 80; - - if (of_property_read_u8(np, "mediatek,bmt-oob-offset", - &bmtd.oob_offset) != 0) - bmtd.oob_offset = 0; - - if (of_property_read_u32(np, "mediatek,bmt-table-size", - &bmt_table_size) != 0) - bmt_table_size = 0x2000U; - - bmtd.table_size = bmt_table_size; - - pmt_block = bmtd.total_blks - bmt_pool_size - 2; - - bmtd.mtd->size = pmt_block << bmtd.blk_shift; - - /* - * --------------------------------------- - * | PMT(2blks) | BMT POOL(totalblks * 2%) | - * --------------------------------------- - * ^ ^ - * | | - * pmt_block pmt_block + 2blocks(pool_lba) - * - * ATTETION!!!!!! - * The blocks ahead of the boundary block are stored in bb_tbl - * and blocks behind are stored in bmt_tbl - */ - - bmtd.pool_lba = (u16)(pmt_block + 2); - bmtd.bb_max = bmtd.total_blks * BBPOOL_RATIO / 100; - - bufsz = round_up(sizeof(struct bbbt) + - bmt_table_size * sizeof(struct bbmt), bmtd.pg_size); - bmtd.bmt_pgs = bufsz >> bmtd.pg_shift; - - bmtd.bbt_buf = kzalloc(bufsz, GFP_KERNEL); - if (!bmtd.bbt_buf) - return -ENOMEM; - - memset(bmtd.bbt_buf, 0xff, bufsz); - - /* Scanning start from the first page of the last block - * of whole flash - */ - bmtd.bbt = NULL; - for (u16 block = bmtd.total_blks - 1; !bmtd.bbt && block >= bmtd.pool_lba; block--) { - u8 fdm[4]; - - if (bbt_nand_read(blk_pg(block), bmtd.bbt_buf, bufsz, fdm, sizeof(fdm))) { - /* Read failed, try the previous block */ - continue; - } - - if (!is_valid_bmt(bmtd.bbt_buf, fdm)) { - /* No valid BMT found, try the previous block */ - continue; - } - - bmtd.bmt_blk_idx = get_bmt_index(bmt_tbl((struct bbbt *)bmtd.bbt_buf)); - if (bmtd.bmt_blk_idx == 0) { - pr_info("[BBT] FATAL ERR: bmt block index is wrong!\n"); - break; - } - - pr_info("[BBT] BMT.v2 is found at 0x%x\n", block); - bmtd.bbt = (struct bbbt *)bmtd.bbt_buf; - } - - if (!bmtd.bbt) { - /* BMT not found */ - if (bmtd.total_blks > BB_TABLE_MAX + BMT_TABLE_MAX) { - pr_info("nand: FATAL: Too many blocks, can not support!\n"); - return -1; - } - - bmtd.bbt = (struct bbbt *)bmtd.bbt_buf; - memset(bmt_tbl(bmtd.bbt), BMT_TBL_DEF_VAL, - bmtd.table_size * sizeof(struct bbmt)); - - if (scan_bad_blocks(bmtd.bbt)) - return -1; - - /* BMT always in the last valid block in pool */ - bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx); - block = bmt_tbl(bmtd.bbt)[bmtd.bmt_blk_idx].block; - pr_notice("[BBT] BMT.v2 is written into PBA:0x%x\n", block); - - if (bmtd.bmt_blk_idx == 0) - pr_info("nand: Warning: no available block in BMT pool!\n"); - else if (bmtd.bmt_blk_idx == (u16)-1) - return -1; - } - - return 0; -} - - -const struct mtk_bmt_ops mtk_bmt_v2_ops = { - .sig = "bmt", - .sig_len = 3, - .init = mtk_bmt_init_v2, - .remap_block = remap_block_v2, - .unmap_block = unmap_block_v2, - .get_mapping_block = get_mapping_block_index_v2, - .debug = mtk_bmt_debug_v2, -}; diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/Kconfig b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/Kconfig similarity index 100% rename from feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/Kconfig rename to feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/Kconfig diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/Makefile b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/Makefile similarity index 100% rename from feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/Makefile rename to feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/Makefile diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-core.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-core.c similarity index 100% rename from feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-core.c rename to feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-core.c diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-debug.h b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-debug.h similarity index 96% rename from feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-debug.h rename to feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-debug.h index 7f9dfed9e..582118333 100644 --- a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-debug.h +++ b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-debug.h @@ -1,20 +1,20 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. - * - * Debug addons for NAND Mapped-block Management (NMBM) - * - * Author: Weijie Gao - */ - -#ifndef _NMBM_DEBUG_H_ -#define _NMBM_DEBUG_H_ - -#define nmbm_mark_block_color_normal(ni, start_ba, end_ba) -#define nmbm_mark_block_color_bad(ni, ba) -#define nmbm_mark_block_color_mgmt(ni, start_ba, end_ba) -#define nmbm_mark_block_color_signature(ni, ba) -#define nmbm_mark_block_color_info_table(ni, start_ba, end_ba) -#define nmbm_mark_block_color_mapped(ni, ba) - -#endif /* _NMBM_DEBUG_H_ */ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. + * + * Debug addons for NAND Mapped-block Management (NMBM) + * + * Author: Weijie Gao + */ + +#ifndef _NMBM_DEBUG_H_ +#define _NMBM_DEBUG_H_ + +#define nmbm_mark_block_color_normal(ni, start_ba, end_ba) +#define nmbm_mark_block_color_bad(ni, ba) +#define nmbm_mark_block_color_mgmt(ni, start_ba, end_ba) +#define nmbm_mark_block_color_signature(ni, ba) +#define nmbm_mark_block_color_info_table(ni, start_ba, end_ba) +#define nmbm_mark_block_color_mapped(ni, ba) + +#endif /* _NMBM_DEBUG_H_ */ diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-debug.inl b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-debug.inl similarity index 100% rename from feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-debug.inl rename to feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-debug.inl diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-mtd.c similarity index 100% rename from feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c rename to feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-mtd.c diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-private.h b/feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-private.h similarity index 100% rename from feeds/mediatek-sdk/mediatek/files-5.4/drivers/mtd/nmbm/nmbm-private.h rename to feeds/mediatek-sdk/mediatek/files/drivers/mtd/nmbm/nmbm-private.h diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/ar8216.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/ar8216.c index 5e248f856..556c3c86f 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/ar8216.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/ar8216.c @@ -513,8 +513,6 @@ ar8216_read_port_link(struct ar8xxx_priv *priv, int port, } } -#ifdef CONFIG_ETHERNET_PACKET_MANGLE - static struct sk_buff * ar8216_mangle_tx(struct net_device *dev, struct sk_buff *skb) { @@ -581,8 +579,6 @@ ar8216_mangle_rx(struct net_device *dev, struct sk_buff *skb) buf[15 + 2] = vlan & 0xff; } -#endif - int ar8216_wait_bit(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val) { @@ -891,7 +887,7 @@ ar8216_phy_write(struct ar8xxx_priv *priv, int addr, int regnum, u16 val) static int ar8229_hw_init(struct ar8xxx_priv *priv) { - phy_interface_t phy_if_mode; + int phy_if_mode; if (priv->initialized) return 0; @@ -899,7 +895,7 @@ ar8229_hw_init(struct ar8xxx_priv *priv) ar8xxx_write(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET); ar8xxx_reg_wait(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET, 0, 1000); - of_get_phy_mode(priv->pdev->of_node, &phy_if_mode); + phy_if_mode = of_get_phy_mode(priv->pdev->of_node); if (phy_if_mode == PHY_INTERFACE_MODE_GMII) { ar8xxx_write(priv, AR8229_REG_OPER_MODE0, @@ -2425,9 +2421,7 @@ static int ar8xxx_phy_config_init(struct phy_device *phydev) { struct ar8xxx_priv *priv = phydev->priv; -#ifdef CONFIG_ETHERNET_PACKET_MANGLE struct net_device *dev = phydev->attached_dev; -#endif int ret; if (WARN_ON(!priv)) @@ -2455,15 +2449,13 @@ ar8xxx_phy_config_init(struct phy_device *phydev) if (ret) return ret; -#ifdef CONFIG_ETHERNET_PACKET_MANGLE /* VID fixup only needed on ar8216 */ if (chip_is_ar8216(priv)) { dev->phy_ptr = priv; - dev->extra_priv_flags |= IFF_NO_IP_ALIGN; + dev->priv_flags |= IFF_NO_IP_ALIGN; dev->eth_mangle_rx = ar8216_mangle_rx; dev->eth_mangle_tx = ar8216_mangle_tx; } -#endif return 0; } @@ -2692,12 +2684,10 @@ ar8xxx_phy_detach(struct phy_device *phydev) if (!dev) return; -#ifdef CONFIG_ETHERNET_PACKET_MANGLE dev->phy_ptr = NULL; - dev->extra_priv_flags &= ~IFF_NO_IP_ALIGN; + dev->priv_flags &= ~IFF_NO_IP_ALIGN; dev->eth_mangle_rx = NULL; dev->eth_mangle_tx = NULL; -#endif } static void @@ -2725,6 +2715,13 @@ ar8xxx_phy_remove(struct phy_device *phydev) ar8xxx_free(priv); } +static int +ar8xxx_phy_soft_reset(struct phy_device *phydev) +{ + /* we don't need an extra reset */ + return 0; +} + static struct phy_driver ar8xxx_phy_driver[] = { { .phy_id = 0x004d0000, @@ -2736,6 +2733,7 @@ static struct phy_driver ar8xxx_phy_driver[] = { .config_init = ar8xxx_phy_config_init, .config_aneg = ar8xxx_phy_config_aneg, .read_status = ar8xxx_phy_read_status, + .soft_reset = ar8xxx_phy_soft_reset, .get_features = ar8xxx_get_features, } }; diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/ar8327.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/ar8327.c index 331314955..dce52ce0e 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/ar8327.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/ar8327.c @@ -183,7 +183,7 @@ ar8327_phy_fixup(struct ar8xxx_priv *priv, int phy) case 2: ar8xxx_phy_mmd_write(priv, phy, 0x7, 0x3c, 0x0); - fallthrough; + /* fallthrough */ case 4: ar8xxx_phy_mmd_write(priv, phy, 0x3, 0x800d, 0x803f); ar8xxx_phy_dbg_write(priv, phy, 0x3d, 0x6860); diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_common.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_common.c index d5f9bfc2f..030c5c86d 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_common.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_common.c @@ -506,9 +506,15 @@ static int b53_configure_ports_of(struct b53_device *dev) if (fixed_link) { u32 spd; u8 po = GMII_PO_LINK; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) phy_interface_t mode; +#else + int mode = of_get_phy_mode(pn); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) of_get_phy_mode(pn, &mode); +#endif if (!of_property_read_u32(fixed_link, "speed", &spd)) { switch (spd) { @@ -523,7 +529,7 @@ static int b53_configure_ports_of(struct b53_device *dev) po |= PORT_OVERRIDE_SPEED_2000M; else po |= GMII_PO_SPEED_2000M; - fallthrough; + /* fall through */ case 1000: po |= GMII_PO_SPEED_1000M; break; @@ -1611,8 +1617,8 @@ static int b53_switch_init(struct b53_device *dev) return b53_switch_reset(dev); } -struct b53_device *b53_swconfig_switch_alloc(struct device *base, struct b53_io_ops *ops, - void *priv) +struct b53_device *b53_switch_alloc(struct device *base, struct b53_io_ops *ops, + void *priv) { struct b53_device *dev; @@ -1627,9 +1633,9 @@ struct b53_device *b53_swconfig_switch_alloc(struct device *base, struct b53_io_ return dev; } -EXPORT_SYMBOL(b53_swconfig_switch_alloc); +EXPORT_SYMBOL(b53_switch_alloc); -int b53_swconfig_switch_detect(struct b53_device *dev) +int b53_switch_detect(struct b53_device *dev) { u32 id32; u16 tmp; @@ -1694,9 +1700,9 @@ int b53_swconfig_switch_detect(struct b53_device *dev) return b53_read8(dev, B53_MGMT_PAGE, B53_REV_ID, &dev->core_rev); } -EXPORT_SYMBOL(b53_swconfig_switch_detect); +EXPORT_SYMBOL(b53_switch_detect); -int b53_swconfig_switch_register(struct b53_device *dev) +int b53_switch_register(struct b53_device *dev) { int ret; @@ -1706,7 +1712,7 @@ int b53_swconfig_switch_register(struct b53_device *dev) dev->sw_dev.alias = dev->pdata->alias; } - if (!dev->chip_id && b53_swconfig_switch_detect(dev)) + if (!dev->chip_id && b53_switch_detect(dev)) return -EINVAL; ret = b53_switch_init(dev); @@ -1717,7 +1723,7 @@ int b53_swconfig_switch_register(struct b53_device *dev) return register_switch(&dev->sw_dev, NULL); } -EXPORT_SYMBOL(b53_swconfig_switch_register); +EXPORT_SYMBOL(b53_switch_register); MODULE_AUTHOR("Jonas Gorski "); MODULE_DESCRIPTION("B53 switch library"); diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_mdio.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_mdio.c index c85df1f30..98cdbffe7 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_mdio.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_mdio.c @@ -280,7 +280,7 @@ static int b53_phy_probe(struct phy_device *phydev) if (phydev->mdio.addr != B53_PSEUDO_PHY && phydev->mdio.addr != 0) return -ENODEV; - dev = b53_swconfig_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus); + dev = b53_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus); if (!dev) return -ENOMEM; @@ -290,7 +290,7 @@ static int b53_phy_probe(struct phy_device *phydev) dev->pdata = NULL; mutex_init(&dev->reg_mutex); - ret = b53_swconfig_switch_detect(dev); + ret = b53_switch_detect(dev); if (ret) return ret; @@ -302,7 +302,7 @@ static int b53_phy_probe(struct phy_device *phydev) linkmode_copy(phydev->advertising, phydev->supported); - ret = b53_swconfig_switch_register(dev); + ret = b53_switch_register(dev); if (ret) { dev_err(dev->dev, "failed to register switch: %i\n", ret); return ret; @@ -361,6 +361,26 @@ static int b53_phy_read_status(struct phy_device *phydev) return 0; } +static const struct of_device_id b53_of_match_1[] = { + { .compatible = "brcm,bcm5325" }, + { .compatible = "brcm,bcm5395" }, + { .compatible = "brcm,bcm5397" }, + { .compatible = "brcm,bcm5398" }, + { /* sentinel */ }, +}; + +static const struct of_device_id b53_of_match_2[] = { + { .compatible = "brcm,bcm53115" }, + { .compatible = "brcm,bcm53125" }, + { .compatible = "brcm,bcm53128" }, + { /* sentinel */ }, +}; + +static const struct of_device_id b53_of_match_3[] = { + { .compatible = "brcm,bcm5365" }, + { /* sentinel */ }, +}; + /* BCM5325, BCM539x */ static struct phy_driver b53_phy_driver_id1 = { .phy_id = 0x0143bc00, @@ -372,6 +392,10 @@ static struct phy_driver b53_phy_driver_id1 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, + .mdiodrv.driver = { + .name = "bcm539x", + .of_match_table = b53_of_match_1, + }, }; /* BCM53125, BCM53128 */ @@ -385,6 +409,10 @@ static struct phy_driver b53_phy_driver_id2 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, + .mdiodrv.driver = { + .name = "bcm531xx", + .of_match_table = b53_of_match_2, + }, }; /* BCM5365 */ @@ -398,6 +426,10 @@ static struct phy_driver b53_phy_driver_id3 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, + .mdiodrv.driver = { + .name = "bcm5365", + .of_match_table = b53_of_match_3, + }, }; int __init b53_phy_driver_register(void) diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_mmap.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_mmap.c index 0a21ff1de..ab1895e9b 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_mmap.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_mmap.c @@ -205,7 +205,7 @@ static int b53_mmap_probe(struct platform_device *pdev) if (!pdata) return -EINVAL; - dev = b53_swconfig_switch_alloc(&pdev->dev, &b53_mmap_ops, pdata->regs); + dev = b53_switch_alloc(&pdev->dev, &b53_mmap_ops, pdata->regs); if (!dev) return -ENOMEM; @@ -214,7 +214,7 @@ static int b53_mmap_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - return b53_swconfig_switch_register(dev); + return b53_switch_register(dev); } static int b53_mmap_remove(struct platform_device *pdev) diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_priv.h b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_priv.h index e455c755b..37c17aeb2 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_priv.h +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_priv.h @@ -183,12 +183,12 @@ static inline struct b53_device *sw_to_b53(struct switch_dev *sw) return container_of(sw, struct b53_device, sw_dev); } -struct b53_device *b53_swconfig_switch_alloc(struct device *base, struct b53_io_ops *ops, - void *priv); +struct b53_device *b53_switch_alloc(struct device *base, struct b53_io_ops *ops, + void *priv); -int b53_swconfig_switch_detect(struct b53_device *dev); +int b53_switch_detect(struct b53_device *dev); -int b53_swconfig_switch_register(struct b53_device *dev); +int b53_switch_register(struct b53_device *dev); static inline void b53_switch_remove(struct b53_device *dev) { diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_spi.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_spi.c index 400454df1..efc8f7ee8 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_spi.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_spi.c @@ -288,14 +288,14 @@ static int b53_spi_probe(struct spi_device *spi) struct b53_device *dev; int ret; - dev = b53_swconfig_switch_alloc(&spi->dev, &b53_spi_ops, spi); + dev = b53_switch_alloc(&spi->dev, &b53_spi_ops, spi); if (!dev) return -ENOMEM; if (spi->dev.platform_data) dev->pdata = spi->dev.platform_data; - ret = b53_swconfig_switch_register(dev); + ret = b53_switch_register(dev); if (ret) return ret; diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_srab.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_srab.c index ead5209cf..012daa3a5 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_srab.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/b53/b53_srab.c @@ -342,7 +342,7 @@ static int b53_srab_probe(struct platform_device *pdev) if (!pdata) return -EINVAL; - dev = b53_swconfig_switch_alloc(&pdev->dev, &b53_srab_ops, pdata->regs); + dev = b53_switch_alloc(&pdev->dev, &b53_srab_ops, pdata->regs); if (!dev) return -ENOMEM; @@ -351,7 +351,7 @@ static int b53_srab_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - return b53_swconfig_switch_register(dev); + return b53_switch_register(dev); } static int b53_srab_remove(struct platform_device *pdev) diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/mvswitch.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/mvswitch.c new file mode 100644 index 000000000..bd3b9e1ad --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/mvswitch.c @@ -0,0 +1,446 @@ +/* + * Marvell 88E6060 switch driver + * Copyright (c) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License v2 as published by the + * Free Software Foundation + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "mvswitch.h" + +/* Undefine this to use trailer mode instead. + * I don't know if header mode works with all chips */ +#define HEADER_MODE 1 + +MODULE_DESCRIPTION("Marvell 88E6060 Switch driver"); +MODULE_AUTHOR("Felix Fietkau"); +MODULE_LICENSE("GPL"); + +#define MVSWITCH_MAGIC 0x88E6060 + +struct mvswitch_priv { + netdev_features_t orig_features; + u8 vlans[16]; +}; + +#define to_mvsw(_phy) ((struct mvswitch_priv *) (_phy)->priv) + +static inline u16 +r16(struct phy_device *phydev, int addr, int reg) +{ + struct mii_bus *bus = phydev->mdio.bus; + + return bus->read(bus, addr, reg); +} + +static inline void +w16(struct phy_device *phydev, int addr, int reg, u16 val) +{ + struct mii_bus *bus = phydev->mdio.bus; + + bus->write(bus, addr, reg, val); +} + + +static struct sk_buff * +mvswitch_mangle_tx(struct net_device *dev, struct sk_buff *skb) +{ + struct mvswitch_priv *priv; + char *buf = NULL; + u16 vid; + + priv = dev->phy_ptr; + if (unlikely(!priv)) + goto error; + + if (unlikely(skb->len < 16)) + goto error; + +#ifdef HEADER_MODE + if (__vlan_hwaccel_get_tag(skb, &vid)) + goto error; + + if (skb_cloned(skb) || (skb->len <= 62) || (skb_headroom(skb) < MV_HEADER_SIZE)) { + if (pskb_expand_head(skb, MV_HEADER_SIZE, (skb->len < 62 ? 62 - skb->len : 0), GFP_ATOMIC)) + goto error_expand; + if (skb->len < 62) + skb->len = 62; + } + buf = skb_push(skb, MV_HEADER_SIZE); +#else + if (__vlan_get_tag(skb, &vid)) + goto error; + + if (unlikely((vid > 15 || !priv->vlans[vid]))) + goto error; + + if (skb->len <= 64) { + if (pskb_expand_head(skb, 0, 64 + MV_TRAILER_SIZE - skb->len, GFP_ATOMIC)) + goto error_expand; + + buf = skb->data + 64; + skb->len = 64 + MV_TRAILER_SIZE; + } else { + if (skb_cloned(skb) || unlikely(skb_tailroom(skb) < 4)) { + if (pskb_expand_head(skb, 0, 4, GFP_ATOMIC)) + goto error_expand; + } + buf = skb_put(skb, 4); + } + + /* move the ethernet header 4 bytes forward, overwriting the vlan tag */ + memmove(skb->data + 4, skb->data, 12); + skb->data += 4; + skb->len -= 4; + skb->mac_header += 4; +#endif + + if (!buf) + goto error; + + +#ifdef HEADER_MODE + /* prepend the tag */ + *((__be16 *) buf) = cpu_to_be16( + ((vid << MV_HEADER_VLAN_S) & MV_HEADER_VLAN_M) | + ((priv->vlans[vid] << MV_HEADER_PORTS_S) & MV_HEADER_PORTS_M) + ); +#else + /* append the tag */ + *((__be32 *) buf) = cpu_to_be32(( + (MV_TRAILER_OVERRIDE << MV_TRAILER_FLAGS_S) | + ((priv->vlans[vid] & MV_TRAILER_PORTS_M) << MV_TRAILER_PORTS_S) + )); +#endif + + return skb; + +error_expand: + if (net_ratelimit()) + printk("%s: failed to expand/update skb for the switch\n", dev->name); + +error: + /* any errors? drop the packet! */ + dev_kfree_skb_any(skb); + return NULL; +} + +static void +mvswitch_mangle_rx(struct net_device *dev, struct sk_buff *skb) +{ + struct mvswitch_priv *priv; + unsigned char *buf; + int vlan = -1; + int i; + + priv = dev->phy_ptr; + if (WARN_ON_ONCE(!priv)) + return; + +#ifdef HEADER_MODE + buf = skb->data; + skb_pull(skb, MV_HEADER_SIZE); +#else + buf = skb->data + skb->len - MV_TRAILER_SIZE; + if (buf[0] != 0x80) + return; +#endif + + /* look for the vlan matching the incoming port */ + for (i = 0; i < ARRAY_SIZE(priv->vlans); i++) { + if ((1 << buf[1]) & priv->vlans[i]) + vlan = i; + } + + if (vlan == -1) + return; + + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan); +} + + +static int +mvswitch_wait_mask(struct phy_device *pdev, int addr, int reg, u16 mask, u16 val) +{ + int i = 100; + u16 r; + + do { + r = r16(pdev, addr, reg) & mask; + if (r == val) + return 0; + } while(--i > 0); + return -ETIMEDOUT; +} + +static int +mvswitch_config_init(struct phy_device *pdev) +{ + struct mvswitch_priv *priv = to_mvsw(pdev); + struct net_device *dev = pdev->attached_dev; + u8 vlmap = 0; + int i; + + if (!dev) + return -EINVAL; + + printk("%s: Marvell 88E6060 PHY driver attached.\n", dev->name); + linkmode_zero(pdev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pdev->supported); + linkmode_copy(pdev->advertising, pdev->supported); + dev->phy_ptr = priv; + pdev->irq = PHY_POLL; +#ifdef HEADER_MODE + dev->flags |= IFF_PROMISC; +#endif + + /* initialize default vlans */ + for (i = 0; i < MV_PORTS; i++) + priv->vlans[(i == MV_WANPORT ? 2 : 1)] |= (1 << i); + + /* before entering reset, disable all ports */ + for (i = 0; i < MV_PORTS; i++) + w16(pdev, MV_PORTREG(CONTROL, i), 0x00); + + msleep(2); /* wait for the status change to settle in */ + + /* put the ATU in reset */ + w16(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET); + + i = mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET, 0); + if (i < 0) { + printk("%s: Timeout waiting for the switch to reset.\n", dev->name); + return i; + } + + /* set the ATU flags */ + w16(pdev, MV_SWITCHREG(ATU_CTRL), + MV_ATUCTL_NO_LEARN | + MV_ATUCTL_ATU_1K | + MV_ATUCTL_AGETIME(MV_ATUCTL_AGETIME_MIN) /* minimum without disabling ageing */ + ); + + /* initialize the cpu port */ + w16(pdev, MV_PORTREG(CONTROL, MV_CPUPORT), +#ifdef HEADER_MODE + MV_PORTCTRL_HEADER | +#else + MV_PORTCTRL_RXTR | + MV_PORTCTRL_TXTR | +#endif + MV_PORTCTRL_ENABLED + ); + /* wait for the phy change to settle in */ + msleep(2); + for (i = 0; i < MV_PORTS; i++) { + u8 pvid = 0; + int j; + + vlmap = 0; + + /* look for the matching vlan */ + for (j = 0; j < ARRAY_SIZE(priv->vlans); j++) { + if (priv->vlans[j] & (1 << i)) { + vlmap = priv->vlans[j]; + pvid = j; + } + } + /* leave port unconfigured if it's not part of a vlan */ + if (!vlmap) + continue; + + /* add the cpu port to the allowed destinations list */ + vlmap |= (1 << MV_CPUPORT); + + /* take port out of its own vlan destination map */ + vlmap &= ~(1 << i); + + /* apply vlan settings */ + w16(pdev, MV_PORTREG(VLANMAP, i), + MV_PORTVLAN_PORTS(vlmap) | + MV_PORTVLAN_ID(i) + ); + + /* re-enable port */ + w16(pdev, MV_PORTREG(CONTROL, i), + MV_PORTCTRL_ENABLED + ); + } + + w16(pdev, MV_PORTREG(VLANMAP, MV_CPUPORT), + MV_PORTVLAN_ID(MV_CPUPORT) + ); + + /* set the port association vector */ + for (i = 0; i <= MV_PORTS; i++) { + w16(pdev, MV_PORTREG(ASSOC, i), + MV_PORTASSOC_PORTS(1 << i) + ); + } + + /* init switch control */ + w16(pdev, MV_SWITCHREG(CTRL), + MV_SWITCHCTL_MSIZE | + MV_SWITCHCTL_DROP + ); + + dev->eth_mangle_rx = mvswitch_mangle_rx; + dev->eth_mangle_tx = mvswitch_mangle_tx; + priv->orig_features = dev->features; + +#ifdef HEADER_MODE + dev->priv_flags |= IFF_NO_IP_ALIGN; + dev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; +#else + dev->features |= NETIF_F_HW_VLAN_CTAG_RX; +#endif + + return 0; +} + +static int +mvswitch_read_status(struct phy_device *pdev) +{ + pdev->speed = SPEED_100; + pdev->duplex = DUPLEX_FULL; + pdev->link = 1; + + /* XXX ugly workaround: we can't force the switch + * to gracefully handle hosts moving from one port to another, + * so we have to regularly clear the ATU database */ + + /* wait for the ATU to become available */ + mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0); + + /* flush the ATU */ + w16(pdev, MV_SWITCHREG(ATU_OP), + MV_ATUOP_INPROGRESS | + MV_ATUOP_FLUSH_ALL + ); + + /* wait for operation to complete */ + mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0); + + return 0; +} + +static int +mvswitch_aneg_done(struct phy_device *phydev) +{ + return 1; /* Return any positive value */ +} + +static int +mvswitch_config_aneg(struct phy_device *phydev) +{ + return 0; +} + +static void +mvswitch_detach(struct phy_device *pdev) +{ + struct mvswitch_priv *priv = to_mvsw(pdev); + struct net_device *dev = pdev->attached_dev; + + if (!dev) + return; + + dev->phy_ptr = NULL; + dev->eth_mangle_rx = NULL; + dev->eth_mangle_tx = NULL; + dev->features = priv->orig_features; + dev->priv_flags &= ~IFF_NO_IP_ALIGN; +} + +static void +mvswitch_remove(struct phy_device *pdev) +{ + struct mvswitch_priv *priv = to_mvsw(pdev); + + kfree(priv); +} + +static int +mvswitch_probe(struct phy_device *pdev) +{ + struct mvswitch_priv *priv; + + priv = kzalloc(sizeof(struct mvswitch_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + pdev->priv = priv; + + return 0; +} + +static int +mvswitch_fixup(struct phy_device *dev) +{ + struct mii_bus *bus = dev->mdio.bus; + u16 reg; + + if (dev->mdio.addr != 0x10) + return 0; + + reg = bus->read(bus, MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK; + if (reg != MV_IDENT_VALUE) + return 0; + + dev->phy_id = MVSWITCH_MAGIC; + return 0; +} + + +static struct phy_driver mvswitch_driver = { + .name = "Marvell 88E6060", + .phy_id = MVSWITCH_MAGIC, + .phy_id_mask = 0xffffffff, + .features = PHY_BASIC_FEATURES, + .probe = &mvswitch_probe, + .remove = &mvswitch_remove, + .detach = &mvswitch_detach, + .config_init = &mvswitch_config_init, + .config_aneg = &mvswitch_config_aneg, + .aneg_done = &mvswitch_aneg_done, + .read_status = &mvswitch_read_status, +}; + +static int __init +mvswitch_init(void) +{ + phy_register_fixup_for_id(PHY_ANY_ID, mvswitch_fixup); + return phy_driver_register(&mvswitch_driver, THIS_MODULE); +} + +static void __exit +mvswitch_exit(void) +{ + phy_driver_unregister(&mvswitch_driver); +} + +module_init(mvswitch_init); +module_exit(mvswitch_exit); diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/mvswitch.h b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/mvswitch.h new file mode 100644 index 000000000..ab2a1a126 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/mvswitch.h @@ -0,0 +1,145 @@ +/* + * Marvell 88E6060 switch driver + * Copyright (c) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License v2 as published by the + * Free Software Foundation + */ +#ifndef __MVSWITCH_H +#define __MVSWITCH_H + +#define MV_HEADER_SIZE 2 +#define MV_HEADER_PORTS_M 0x001f +#define MV_HEADER_PORTS_S 0 +#define MV_HEADER_VLAN_M 0xf000 +#define MV_HEADER_VLAN_S 12 + +#define MV_TRAILER_SIZE 4 +#define MV_TRAILER_PORTS_M 0x1f +#define MV_TRAILER_PORTS_S 16 +#define MV_TRAILER_FLAGS_S 24 +#define MV_TRAILER_OVERRIDE 0x80 + + +#define MV_PORTS 5 +#define MV_WANPORT 4 +#define MV_CPUPORT 5 + +#define MV_BASE 0x10 + +#define MV_PHYPORT_BASE (MV_BASE + 0x0) +#define MV_PHYPORT(_n) (MV_PHYPORT_BASE + (_n)) +#define MV_SWITCHPORT_BASE (MV_BASE + 0x8) +#define MV_SWITCHPORT(_n) (MV_SWITCHPORT_BASE + (_n)) +#define MV_SWITCHREGS (MV_BASE + 0xf) + +enum { + MV_PHY_CONTROL = 0x00, + MV_PHY_STATUS = 0x01, + MV_PHY_IDENT0 = 0x02, + MV_PHY_IDENT1 = 0x03, + MV_PHY_ANEG = 0x04, + MV_PHY_LINK_ABILITY = 0x05, + MV_PHY_ANEG_EXPAND = 0x06, + MV_PHY_XMIT_NEXTP = 0x07, + MV_PHY_LINK_NEXTP = 0x08, + MV_PHY_CONTROL1 = 0x10, + MV_PHY_STATUS1 = 0x11, + MV_PHY_INTR_EN = 0x12, + MV_PHY_INTR_STATUS = 0x13, + MV_PHY_INTR_PORT = 0x14, + MV_PHY_RECV_COUNTER = 0x16, + MV_PHY_LED_PARALLEL = 0x16, + MV_PHY_LED_STREAM = 0x17, + MV_PHY_LED_CTRL = 0x18, + MV_PHY_LED_OVERRIDE = 0x19, + MV_PHY_VCT_CTRL = 0x1a, + MV_PHY_VCT_STATUS = 0x1b, + MV_PHY_CONTROL2 = 0x1e +}; +#define MV_PHYREG(_type, _port) MV_PHYPORT(_port), MV_PHY_##_type + +enum { + MV_PORT_STATUS = 0x00, + MV_PORT_IDENT = 0x03, + MV_PORT_CONTROL = 0x04, + MV_PORT_VLANMAP = 0x06, + MV_PORT_ASSOC = 0x0b, + MV_PORT_RXCOUNT = 0x10, + MV_PORT_TXCOUNT = 0x11, +}; +#define MV_PORTREG(_type, _port) MV_SWITCHPORT(_port), MV_PORT_##_type + +enum { + MV_PORTCTRL_BLOCK = (1 << 0), + MV_PORTCTRL_LEARN = (2 << 0), + MV_PORTCTRL_ENABLED = (3 << 0), + MV_PORTCTRL_VLANTUN = (1 << 7), /* Enforce VLANs on packets */ + MV_PORTCTRL_RXTR = (1 << 8), /* Enable Marvell packet trailer for ingress */ + MV_PORTCTRL_HEADER = (1 << 11), /* Enable Marvell packet header mode for port */ + MV_PORTCTRL_TXTR = (1 << 14), /* Enable Marvell packet trailer for egress */ + MV_PORTCTRL_FORCEFL = (1 << 15), /* force flow control */ +}; + +#define MV_PORTVLAN_ID(_n) (((_n) & 0xf) << 12) +#define MV_PORTVLAN_PORTS(_n) ((_n) & 0x3f) + +#define MV_PORTASSOC_PORTS(_n) ((_n) & 0x1f) +#define MV_PORTASSOC_MONITOR (1 << 15) + +enum { + MV_SWITCH_MAC0 = 0x01, + MV_SWITCH_MAC1 = 0x02, + MV_SWITCH_MAC2 = 0x03, + MV_SWITCH_CTRL = 0x04, + MV_SWITCH_ATU_CTRL = 0x0a, + MV_SWITCH_ATU_OP = 0x0b, + MV_SWITCH_ATU_DATA = 0x0c, + MV_SWITCH_ATU_MAC0 = 0x0d, + MV_SWITCH_ATU_MAC1 = 0x0e, + MV_SWITCH_ATU_MAC2 = 0x0f, +}; +#define MV_SWITCHREG(_type) MV_SWITCHREGS, MV_SWITCH_##_type + +enum { + MV_SWITCHCTL_EEIE = (1 << 0), /* EEPROM interrupt enable */ + MV_SWITCHCTL_PHYIE = (1 << 1), /* PHY interrupt enable */ + MV_SWITCHCTL_ATUDONE= (1 << 2), /* ATU done interrupt enable */ + MV_SWITCHCTL_ATUIE = (1 << 3), /* ATU interrupt enable */ + MV_SWITCHCTL_CTRMODE= (1 << 8), /* statistics for rx and tx errors */ + MV_SWITCHCTL_RELOAD = (1 << 9), /* reload registers from eeprom */ + MV_SWITCHCTL_MSIZE = (1 << 10), /* increase maximum frame size */ + MV_SWITCHCTL_DROP = (1 << 13), /* discard frames with excessive collisions */ +}; + +enum { +#define MV_ATUCTL_AGETIME_MIN 16 +#define MV_ATUCTL_AGETIME_MAX 4080 +#define MV_ATUCTL_AGETIME(_n) ((((_n) / 16) & 0xff) << 4) + MV_ATUCTL_ATU_256 = (0 << 12), + MV_ATUCTL_ATU_512 = (1 << 12), + MV_ATUCTL_ATU_1K = (2 << 12), + MV_ATUCTL_ATUMASK = (3 << 12), + MV_ATUCTL_NO_LEARN = (1 << 14), + MV_ATUCTL_RESET = (1 << 15), +}; + +enum { +#define MV_ATUOP_DBNUM(_n) ((_n) & 0x0f) + + MV_ATUOP_NOOP = (0 << 12), + MV_ATUOP_FLUSH_ALL = (1 << 12), + MV_ATUOP_FLUSH_U = (2 << 12), + MV_ATUOP_LOAD_DB = (3 << 12), + MV_ATUOP_GET_NEXT = (4 << 12), + MV_ATUOP_FLUSH_DB = (5 << 12), + MV_ATUOP_FLUSH_DB_UU= (6 << 12), + + MV_ATUOP_INPROGRESS = (1 << 15), +}; + +#define MV_IDENT_MASK 0xfff0 +#define MV_IDENT_VALUE 0x0600 + +#endif diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/psb6970.c b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/psb6970.c index 2587b9991..6cee75734 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/psb6970.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/net/phy/psb6970.c @@ -60,13 +60,11 @@ struct psb6970_priv { struct mutex reg_mutex; /* all fields below are cleared on reset */ - struct_group(psb6970_priv_volatile, - bool vlan; - u16 vlan_id[PSB6970_MAX_VLANS]; - u8 vlan_table[PSB6970_MAX_VLANS]; - u8 vlan_tagged; - u16 pvid[PSB6970_NUM_PORTS]; - ); + bool vlan; + u16 vlan_id[PSB6970_MAX_VLANS]; + u8 vlan_table[PSB6970_MAX_VLANS]; + u8 vlan_tagged; + u16 pvid[PSB6970_NUM_PORTS]; }; #define to_psb6970(_dev) container_of(_dev, struct psb6970_priv, dev) @@ -274,8 +272,8 @@ static int psb6970_reset_switch(struct switch_dev *dev) mutex_lock(&priv->reg_mutex); - memset(&priv->psb6970_priv_volatile, 0, - sizeof(priv->psb6970_priv_volatile)); + memset(&priv->vlan, 0, sizeof(struct psb6970_priv) - + offsetof(struct psb6970_priv, vlan)); for (i = 0; i < PSB6970_MAX_VLANS; i++) priv->vlan_id[i] = i; @@ -309,6 +307,7 @@ static const struct switch_dev_ops psb6970_ops = { static int psb6970_config_init(struct phy_device *pdev) { struct psb6970_priv *priv; + struct net_device *dev = pdev->attached_dev; struct switch_dev *swdev; int ret; @@ -356,6 +355,8 @@ static int psb6970_config_init(struct phy_device *pdev) goto done; } + dev->phy_ptr = priv; + done: return ret; } diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/Kconfig b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/Kconfig index 1dc027815..7499ba1e1 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/Kconfig +++ b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/Kconfig @@ -1,5 +1,6 @@ menuconfig MIKROTIK bool "Platform support for MikroTik RouterBoard virtual devices" + default n help Say Y here to get to see options for the MikroTik RouterBoard platform. This option alone does not add any kernel code. diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/rb_hardconfig.c b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/rb_hardconfig.c index bd0469d5e..e6a692889 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/rb_hardconfig.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/rb_hardconfig.c @@ -39,7 +39,7 @@ #include "routerboot.h" -#define RB_HARDCONFIG_VER "0.07" +#define RB_HARDCONFIG_VER "0.06" #define RB_HC_PR_PFX "[rb_hardconfig] " /* ID values for hardware settings */ @@ -676,9 +676,10 @@ static ssize_t hc_wlan_data_bin_read(struct file *filp, struct kobject *kobj, return count; } -int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) +int __init rb_hardconfig_init(struct kobject *rb_kobj) { struct kobject *hc_wlan_kobj; + struct mtd_info *mtd; size_t bytes_read, buflen, outlen; const u8 *buf; void *outbuf; @@ -689,19 +690,20 @@ int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) hc_kobj = NULL; hc_wlan_kobj = NULL; - ret = __get_mtd_device(mtd); - if (ret) + // TODO allow override + mtd = get_mtd_device_nm(RB_MTD_HARD_CONFIG); + if (IS_ERR(mtd)) return -ENODEV; hc_buflen = mtd->size; hc_buf = kmalloc(hc_buflen, GFP_KERNEL); if (!hc_buf) { - __put_mtd_device(mtd); + put_mtd_device(mtd); return -ENOMEM; } ret = mtd_read(mtd, 0, hc_buflen, &bytes_read, hc_buf); - __put_mtd_device(mtd); + put_mtd_device(mtd); if (ret) goto fail; @@ -816,10 +818,8 @@ fail: return ret; } -void rb_hardconfig_exit(void) +void __exit rb_hardconfig_exit(void) { kobject_put(hc_kobj); - hc_kobj = NULL; kfree(hc_buf); - hc_buf = NULL; } diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/rb_softconfig.c b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/rb_softconfig.c index 5acff6aa9..070bd32d5 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/rb_softconfig.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/rb_softconfig.c @@ -56,12 +56,23 @@ #include "routerboot.h" -#define RB_SOFTCONFIG_VER "0.05" +#define RB_SOFTCONFIG_VER "0.03" #define RB_SC_PR_PFX "[rb_softconfig] " -#define RB_SC_HAS_WRITE_SUPPORT true -#define RB_SC_WMODE S_IWUSR -#define RB_SC_RMODE S_IRUSR +/* + * mtd operations before 4.17 are asynchronous, not handled by this code + * Also make the driver act read-only if 4K_SECTORS are not enabled, since they + * are require to handle partial erasing of the small soft_config partition. + */ +#if defined(CONFIG_MTD_SPI_NOR_USE_4K_SECTORS) + #define RB_SC_HAS_WRITE_SUPPORT true + #define RB_SC_WMODE S_IWUSR + #define RB_SC_RMODE S_IRUSR +#else + #define RB_SC_HAS_WRITE_SUPPORT false + #define RB_SC_WMODE 0 + #define RB_SC_RMODE S_IRUSR +#endif /* ID values for software settings */ #define RB_SCID_UART_SPEED 0x01 // u32*1 @@ -694,8 +705,9 @@ mtdfail: static struct kobj_attribute sc_kattrcommit = __ATTR(commit, RB_SC_RMODE|RB_SC_WMODE, sc_commit_show, sc_commit_store); -int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) +int __init rb_softconfig_init(struct kobject *rb_kobj) { + struct mtd_info *mtd; size_t bytes_read, buflen; const u8 *buf; int i, ret; @@ -704,19 +716,20 @@ int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) sc_buf = NULL; sc_kobj = NULL; - ret = __get_mtd_device(mtd); - if (ret) + // TODO allow override + mtd = get_mtd_device_nm(RB_MTD_SOFT_CONFIG); + if (IS_ERR(mtd)) return -ENODEV; sc_buflen = mtd->size; sc_buf = kmalloc(sc_buflen, GFP_KERNEL); if (!sc_buf) { - __put_mtd_device(mtd); + put_mtd_device(mtd); return -ENOMEM; } ret = mtd_read(mtd, 0, sc_buflen, &bytes_read, sc_buf); - __put_mtd_device(mtd); + put_mtd_device(mtd); if (ret) goto fail; @@ -786,10 +799,8 @@ fail: return ret; } -void rb_softconfig_exit(void) +void __exit rb_softconfig_exit(void) { kobject_put(sc_kobj); - sc_kobj = NULL; kfree(sc_buf); - sc_buf = NULL; } diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/routerboot.c b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/routerboot.c index 96f246091..4c8c0bfac 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/routerboot.c +++ b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/routerboot.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "routerboot.h" @@ -161,57 +160,25 @@ fail: return ret; } -static void routerboot_mtd_notifier_add(struct mtd_info *mtd) -{ - /* Currently routerboot is only known to live on NOR flash */ - if (mtd->type != MTD_NORFLASH) - return; - - /* - * We ignore the following return values and always register. - * These init() routines are designed so that their failed state is - * always manageable by the corresponding exit() calls. - * Notifier is called with MTD mutex held: use __get/__put variants. - * TODO: allow partition names override - */ - if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) - rb_hardconfig_init(rb_kobj, mtd); - else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) - rb_softconfig_init(rb_kobj, mtd); -} - -static void routerboot_mtd_notifier_remove(struct mtd_info *mtd) -{ - if (mtd->type != MTD_NORFLASH) - return; - - if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) - rb_hardconfig_exit(); - else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) - rb_softconfig_exit(); -} - -/* Note: using a notifier prevents qualifying init()/exit() functions with __init/__exit */ -static struct mtd_notifier routerboot_mtd_notifier = { - .add = routerboot_mtd_notifier_add, - .remove = routerboot_mtd_notifier_remove, -}; - static int __init routerboot_init(void) { rb_kobj = kobject_create_and_add("mikrotik", firmware_kobj); if (!rb_kobj) return -ENOMEM; - register_mtd_user(&routerboot_mtd_notifier); + /* + * We ignore the following return values and always register. + * These init() routines are designed so that their failed state is + * always manageable by the corresponding exit() calls. + */ + rb_hardconfig_init(rb_kobj); + rb_softconfig_init(rb_kobj); return 0; } static void __exit routerboot_exit(void) { - unregister_mtd_user(&routerboot_mtd_notifier); - /* Exit routines are idempotent */ rb_softconfig_exit(); rb_hardconfig_exit(); kobject_put(rb_kobj); // recursive afaict diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/routerboot.h b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/routerboot.h index e858a524a..67d89808d 100644 --- a/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/routerboot.h +++ b/feeds/mediatek-sdk/mediatek/files/drivers/platform/mikrotik/routerboot.h @@ -25,11 +25,11 @@ int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const u16 tag_id, u16 *pld_ofs, u16 *pld_len); int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen); -int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd); -void rb_hardconfig_exit(void); +int __init rb_hardconfig_init(struct kobject *rb_kobj); +void __exit rb_hardconfig_exit(void); -int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd); -void rb_softconfig_exit(void); +int __init rb_softconfig_init(struct kobject *rb_kobj); +void __exit rb_softconfig_exit(void); ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf); ssize_t routerboot_tag_show_u32s(const u8 *pld, u16 pld_len, char *buf); diff --git a/feeds/mediatek-sdk/mediatek/files/drivers/ssb/fallback-sprom.c b/feeds/mediatek-sdk/mediatek/files/drivers/ssb/fallback-sprom.c deleted file mode 100644 index 26f0fd2f0..000000000 --- a/feeds/mediatek-sdk/mediatek/files/drivers/ssb/fallback-sprom.c +++ /dev/null @@ -1,744 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * SSB Fallback SPROM Driver - * - * Copyright (C) 2020 Álvaro Fernández Rojas - * Copyright (C) 2014 Jonas Gorski - * Copyright (C) 2008 Maxime Bizon - * Copyright (C) 2008 Florian Fainelli - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SSB_FBS_MAX_SIZE 440 - -/* Get the word-offset for a SSB_SPROM_XXX define. */ -#define SPOFF(offset) ((offset) / sizeof(u16)) -/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */ -#define SPEX16(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) -#define SPEX32(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \ - in[SPOFF(_offset)]) & (_mask)) >> (_shift)) -#define SPEX(_outvar, _offset, _mask, _shift) \ - SPEX16(_outvar, _offset, _mask, _shift) - -#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \ - do { \ - SPEX(_field[0], _offset + 0, _mask, _shift); \ - SPEX(_field[1], _offset + 2, _mask, _shift); \ - SPEX(_field[2], _offset + 4, _mask, _shift); \ - SPEX(_field[3], _offset + 6, _mask, _shift); \ - SPEX(_field[4], _offset + 8, _mask, _shift); \ - SPEX(_field[5], _offset + 10, _mask, _shift); \ - SPEX(_field[6], _offset + 12, _mask, _shift); \ - SPEX(_field[7], _offset + 14, _mask, _shift); \ - } while (0) - -struct ssb_fbs { - struct device *dev; - struct list_head list; - struct ssb_sprom sprom; - u32 pci_bus; - u32 pci_dev; - bool devid_override; -}; - -static DEFINE_SPINLOCK(ssb_fbs_lock); -static struct list_head ssb_fbs_list = LIST_HEAD_INIT(ssb_fbs_list); - -int ssb_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out) -{ - struct ssb_fbs *pos; - u32 pci_bus, pci_dev; - - if (bus->bustype != SSB_BUSTYPE_PCI) - return -ENOENT; - - pci_bus = bus->host_pci->bus->number; - pci_dev = PCI_SLOT(bus->host_pci->devfn); - - list_for_each_entry(pos, &ssb_fbs_list, list) { - if (pos->pci_bus != pci_bus || - pos->pci_dev != pci_dev) - continue; - - if (pos->devid_override) - bus->host_pci->device = pos->sprom.dev_id; - - memcpy(out, &pos->sprom, sizeof(struct ssb_sprom)); - dev_info(pos->dev, "requested by [%x:%x]", - pos->pci_bus, pos->pci_dev); - - return 0; - } - - pr_err("unable to fill SPROM for [%x:%x]\n", pci_bus, pci_dev); - - return -EINVAL; -} - -static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset, - u16 mask, u16 shift) -{ - u16 v; - u8 gain; - - v = in[SPOFF(offset)]; - gain = (v & mask) >> shift; - if (gain == 0xFF) - gain = 2; /* If unset use 2dBm */ - if (sprom_revision == 1) { - /* Convert to Q5.2 */ - gain <<= 2; - } else { - /* Q5.2 Fractional part is stored in 0xC0 */ - gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); - } - - return (s8)gain; -} - -static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in) -{ - SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); - SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); - SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); - SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); - SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); - SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); - SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); - SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); - SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); - SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, - SSB_SPROM2_MAXP_A_LO_SHIFT); -} - -static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) -{ - SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); - SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, - SSB_SPROM1_ETHPHY_ET1A_SHIFT); - SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); - SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); - SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); - SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); - if (out->revision == 1) - SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, - SSB_SPROM1_BINF_CCODE_SHIFT); - SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, - SSB_SPROM1_BINF_ANTA_SHIFT); - SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, - SSB_SPROM1_BINF_ANTBG_SHIFT); - SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); - SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); - SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); - SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0); - SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0); - SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0); - SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1, - SSB_SPROM1_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3, - SSB_SPROM1_GPIOB_P3_SHIFT); - SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A, - SSB_SPROM1_MAXPWR_A_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); - SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, - SSB_SPROM1_ITSSI_A_SHIFT); - SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); - SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); - - SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); - - /* Extract the antenna gain values. */ - out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, - SSB_SPROM1_AGAIN, - SSB_SPROM1_AGAIN_BG, - SSB_SPROM1_AGAIN_BG_SHIFT); - out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, - SSB_SPROM1_AGAIN, - SSB_SPROM1_AGAIN_A, - SSB_SPROM1_AGAIN_A_SHIFT); - if (out->revision >= 2) - sprom_extract_r23(out, in); -} - -/* Revs 4 5 and 8 have partially shared layout */ -static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) -{ - SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, - SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT); - SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, - SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT); - SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, - SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT); - SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, - SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT); - - SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, - SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT); - SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, - SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT); - SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, - SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT); - SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, - SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT); - - SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, - SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT); - SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, - SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT); - SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, - SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT); - SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, - SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT); - - SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, - SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT); - SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, - SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT); - SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, - SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT); - SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, - SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT); -} - -static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) -{ - static const u16 pwr_info_offset[] = { - SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1, - SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3 - }; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != - ARRAY_SIZE(out->core_pwr_info)); - - SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); - SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, - SSB_SPROM4_ETHPHY_ET1A_SHIFT); - SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); - SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); - if (out->revision == 4) { - SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); - SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); - SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); - SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0); - SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0); - } else { - SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0); - SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); - SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); - SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); - SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0); - } - SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, - SSB_SPROM4_ANTAVAIL_A_SHIFT); - SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, - SSB_SPROM4_ANTAVAIL_BG_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0); - SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG, - SSB_SPROM4_ITSSI_BG_SHIFT); - SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0); - SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A, - SSB_SPROM4_ITSSI_A_SHIFT); - if (out->revision == 4) { - SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1, - SSB_SPROM4_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, - SSB_SPROM4_GPIOB_P3_SHIFT); - } else { - SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1, - SSB_SPROM5_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3, - SSB_SPROM5_GPIOB_P3_SHIFT); - } - - /* Extract the antenna gain values. */ - out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, - SSB_SPROM4_AGAIN01, - SSB_SPROM4_AGAIN0, - SSB_SPROM4_AGAIN0_SHIFT); - out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, - SSB_SPROM4_AGAIN01, - SSB_SPROM4_AGAIN1, - SSB_SPROM4_AGAIN1_SHIFT); - out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, - SSB_SPROM4_AGAIN23, - SSB_SPROM4_AGAIN2, - SSB_SPROM4_AGAIN2_SHIFT); - out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, - SSB_SPROM4_AGAIN23, - SSB_SPROM4_AGAIN3, - SSB_SPROM4_AGAIN3_SHIFT); - - /* Extract cores power info info */ - for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { - u16 o = pwr_info_offset[i]; - - SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, - SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, - SSB_SPROM4_2G_MAXP, 0); - - SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0); - - SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, - SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, - SSB_SPROM4_5G_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP, - SSB_SPROM4_5GH_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP, - SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT); - - SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0); - } - - sprom_extract_r458(out, in); - - /* TODO - get remaining rev 4 stuff needed */ -} - -static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) -{ - int i; - u16 o; - static const u16 pwr_info_offset[] = { - SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, - SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 - }; - BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != - ARRAY_SIZE(out->core_pwr_info)); - - SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); - SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); - SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); - SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); - SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); - SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0); - SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0); - SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, - SSB_SPROM8_ANTAVAIL_A_SHIFT); - SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, - SSB_SPROM8_ANTAVAIL_BG_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); - SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, - SSB_SPROM8_ITSSI_BG_SHIFT); - SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); - SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, - SSB_SPROM8_ITSSI_A_SHIFT); - SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); - SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, - SSB_SPROM8_MAXP_AL_SHIFT); - SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, - SSB_SPROM8_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, - SSB_SPROM8_GPIOB_P3_SHIFT); - SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); - SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, - SSB_SPROM8_TRI5G_SHIFT); - SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); - SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, - SSB_SPROM8_TRI5GH_SHIFT); - SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0); - SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, - SSB_SPROM8_RXPO5G_SHIFT); - SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); - SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, - SSB_SPROM8_RSSISMC2G_SHIFT); - SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, - SSB_SPROM8_RSSISAV2G_SHIFT); - SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, - SSB_SPROM8_BXA2G_SHIFT); - SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); - SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, - SSB_SPROM8_RSSISMC5G_SHIFT); - SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, - SSB_SPROM8_RSSISAV5G_SHIFT); - SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, - SSB_SPROM8_BXA5G_SHIFT); - SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0); - SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0); - SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0); - SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0); - SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0); - SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0); - SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0); - SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0); - SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0); - SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0); - SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0); - SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0); - SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0); - SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0); - SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0); - SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0); - SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); - - /* Extract the antenna gain values. */ - out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, - SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN0, - SSB_SPROM8_AGAIN0_SHIFT); - out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, - SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN1, - SSB_SPROM8_AGAIN1_SHIFT); - out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, - SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN2, - SSB_SPROM8_AGAIN2_SHIFT); - out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, - SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN3, - SSB_SPROM8_AGAIN3_SHIFT); - - /* Extract cores power info info */ - for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { - o = pwr_info_offset[i]; - SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI, - SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI, - SSB_SPROM8_2G_MAXP, 0); - - SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0); - - SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI, - SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI, - SSB_SPROM8_5G_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP, - SSB_SPROM8_5GH_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP, - SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT); - - SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0); - } - - /* Extract FEM info */ - SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); - SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); - SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); - SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); - SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); - - SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); - SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); - SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); - SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); - SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); - - SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, - SSB_SPROM8_LEDDC_ON_SHIFT); - SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF, - SSB_SPROM8_LEDDC_OFF_SHIFT); - - SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN, - SSB_SPROM8_TXRXC_TXCHAIN_SHIFT); - SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN, - SSB_SPROM8_TXRXC_RXCHAIN_SHIFT); - SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH, - SSB_SPROM8_TXRXC_SWITCH_SHIFT); - - SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0); - - SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0); - - SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP, - SSB_SPROM8_RAWTS_RAWTEMP_SHIFT); - SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER, - SSB_SPROM8_RAWTS_MEASPOWER_SHIFT); - SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX, - SSB_SPROM8_OPT_CORRX_TEMP_SLOPE, - SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT); - SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX, - SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT); - SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX, - SSB_SPROM8_OPT_CORRX_TEMP_OPTION, - SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT); - SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP, - SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR, - SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT); - SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP, - SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP, - SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT); - SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL, - SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT); - - SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0); - SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0); - SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0); - SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0); - - SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH, - SSB_SPROM8_THERMAL_TRESH_SHIFT); - SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET, - SSB_SPROM8_THERMAL_OFFSET_SHIFT); - SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA, - SSB_SPROM8_TEMPDELTA_PHYCAL, - SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT); - SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD, - SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT); - SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA, - SSB_SPROM8_TEMPDELTA_HYSTERESIS, - SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT); - sprom_extract_r458(out, in); - - /* TODO - get remaining rev 8 stuff needed */ -} - -static int sprom_extract(struct ssb_fbs *priv, const u16 *in, u16 size) -{ - struct ssb_sprom *out = &priv->sprom; - - memset(out, 0, sizeof(*out)); - - out->revision = in[size - 1] & 0x00FF; - - switch (out->revision) { - case 1: - case 2: - case 3: - sprom_extract_r123(out, in); - break; - case 4: - case 5: - sprom_extract_r45(out, in); - break; - case 8: - sprom_extract_r8(out, in); - break; - default: - dev_warn(priv->dev, - "Unsupported SPROM revision %d detected." - " Will extract v1\n", - out->revision); - out->revision = 1; - sprom_extract_r123(out, in); - } - - if (out->boardflags_lo == 0xFFFF) - out->boardflags_lo = 0; /* per specs */ - if (out->boardflags_hi == 0xFFFF) - out->boardflags_hi = 0; /* per specs */ - - return 0; -} - -static void ssb_fbs_fixup(struct ssb_fbs *priv, u16 *sprom) -{ - struct device_node *node = priv->dev->of_node; - u32 fixups, off, val; - int i = 0; - - if (!of_get_property(node, "brcm,sprom-fixups", &fixups)) - return; - - fixups /= sizeof(u32); - - dev_info(priv->dev, "patching SPROM with %u fixups...\n", fixups >> 1); - - while (i < fixups) { - if (of_property_read_u32_index(node, "brcm,sprom-fixups", - i++, &off)) { - dev_err(priv->dev, "error reading fixup[%u] offset\n", - i - 1); - return; - } - - if (of_property_read_u32_index(node, "brcm,sprom-fixups", - i++, &val)) { - dev_err(priv->dev, "error reading fixup[%u] value\n", - i - 1); - return; - } - - dev_dbg(priv->dev, "fixup[%d]=0x%04x\n", off, val); - - sprom[off] = val; - } -} - -static bool sprom_override_devid(struct ssb_fbs *priv, struct ssb_sprom *out, - const u16 *in) -{ - SPEX(dev_id, SSB_SPROM1_PID, 0xFFFF, 0); - return !!out->dev_id; -} - -static int ssb_fbs_set(struct ssb_fbs *priv, struct device_node *node) -{ - struct ssb_sprom *sprom = &priv->sprom; - const struct firmware *fw; - const char *sprom_name; - int err; - - if (of_property_read_string(node, "brcm,sprom", &sprom_name)) - sprom_name = NULL; - - if (sprom_name) { - err = request_firmware_direct(&fw, sprom_name, priv->dev); - if (err) - dev_err(priv->dev, "%s load error\n", sprom_name); - } else { - err = -ENOENT; - } - - if (err) { - sprom->revision = 0x02; - sprom->board_rev = 0x0017; - sprom->country_code = 0x00; - sprom->ant_available_bg = 0x03; - sprom->pa0b0 = 0x15ae; - sprom->pa0b1 = 0xfa85; - sprom->pa0b2 = 0xfe8d; - sprom->pa1b0 = 0xffff; - sprom->pa1b1 = 0xffff; - sprom->pa1b2 = 0xffff; - sprom->gpio0 = 0xff; - sprom->gpio1 = 0xff; - sprom->gpio2 = 0xff; - sprom->gpio3 = 0xff; - sprom->maxpwr_bg = 0x4c; - sprom->itssi_bg = 0x00; - sprom->boardflags_lo = 0x2848; - sprom->boardflags_hi = 0x0000; - priv->devid_override = false; - - dev_warn(priv->dev, "using basic SPROM\n"); - } else { - size_t size = min(fw->size, (size_t) SSB_FBS_MAX_SIZE); - u16 tmp_sprom[SSB_FBS_MAX_SIZE >> 1]; - u32 i, j; - - for (i = 0, j = 0; i < size; i += 2, j++) - tmp_sprom[j] = (fw->data[i] << 8) | fw->data[i + 1]; - - release_firmware(fw); - ssb_fbs_fixup(priv, tmp_sprom); - sprom_extract(priv, tmp_sprom, size >> 1); - - priv->devid_override = sprom_override_devid(priv, sprom, - tmp_sprom); - } - - return 0; -} - -static int ssb_fbs_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; - struct ssb_fbs *priv; - unsigned long flags; - u8 mac[ETH_ALEN]; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->dev = dev; - - ssb_fbs_set(priv, node); - - of_property_read_u32(node, "pci-bus", &priv->pci_bus); - of_property_read_u32(node, "pci-dev", &priv->pci_dev); - - of_get_mac_address(node, mac); - if (is_valid_ether_addr(mac)) { - dev_info(dev, "mtd mac %pM\n", mac); - } else { - random_ether_addr(mac); - dev_info(dev, "random mac %pM\n", mac); - } - - memcpy(priv->sprom.il0mac, mac, ETH_ALEN); - memcpy(priv->sprom.et0mac, mac, ETH_ALEN); - memcpy(priv->sprom.et1mac, mac, ETH_ALEN); - memcpy(priv->sprom.et2mac, mac, ETH_ALEN); - - spin_lock_irqsave(&ssb_fbs_lock, flags); - list_add(&priv->list, &ssb_fbs_list); - spin_unlock_irqrestore(&ssb_fbs_lock, flags); - - dev_info(dev, "registered SPROM for [%x:%x]\n", - priv->pci_bus, priv->pci_dev); - - return 0; -} - -static const struct of_device_id ssb_fbs_of_match[] = { - { .compatible = "brcm,ssb-sprom", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, ssb_fbs_of_match); - -static struct platform_driver ssb_fbs_driver = { - .probe = ssb_fbs_probe, - .driver = { - .name = "ssb-sprom", - .of_match_table = ssb_fbs_of_match, - }, -}; - -int __init ssb_fbs_register(void) -{ - return platform_driver_register(&ssb_fbs_driver); -} diff --git a/feeds/mediatek-sdk/mediatek/files/include/linux/mtd/mtk_bmt.h b/feeds/mediatek-sdk/mediatek/files/include/linux/mtd/mtk_bmt.h deleted file mode 100644 index cbb6d04d8..000000000 --- a/feeds/mediatek-sdk/mediatek/files/include/linux/mtd/mtk_bmt.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __MTK_BMT_H -#define __MTK_BMT_H - -#ifdef CONFIG_MTD_NAND_MTK_BMT -int mtk_bmt_attach(struct mtd_info *mtd); -void mtk_bmt_detach(struct mtd_info *mtd); -#else -static inline int mtk_bmt_attach(struct mtd_info *mtd) -{ - return 0; -} - -static inline void mtk_bmt_detach(struct mtd_info *mtd) -{ -} -#endif - -#endif diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/include/nmbm/nmbm-os.h b/feeds/mediatek-sdk/mediatek/files/include/nmbm/nmbm-os.h similarity index 100% rename from feeds/mediatek-sdk/mediatek/files-5.4/include/nmbm/nmbm-os.h rename to feeds/mediatek-sdk/mediatek/files/include/nmbm/nmbm-os.h diff --git a/feeds/mediatek-sdk/mediatek/files-5.4/include/nmbm/nmbm.h b/feeds/mediatek-sdk/mediatek/files/include/nmbm/nmbm.h similarity index 100% rename from feeds/mediatek-sdk/mediatek/files-5.4/include/nmbm/nmbm.h rename to feeds/mediatek-sdk/mediatek/files/include/nmbm/nmbm.h diff --git a/feeds/mediatek-sdk/mediatek/mt7981-edgecore-eap111.dts b/feeds/mediatek-sdk/mediatek/mt7981-edgecore-eap111.dts new file mode 100755 index 000000000..60cf5ec58 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/mt7981-edgecore-eap111.dts @@ -0,0 +1,378 @@ +/dts-v1/; +#include "mt7981.dtsi" +/ { + model = "EdgeCore EAP111"; + compatible = "edgecore,eap111"; + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11002000"; + }; + + aliases { + led-boot = &led_green; + led-failsafe = &led_green; + led-running = &led_green; + led-upgrade = &led_green; + serial0 = &uart0; + }; + + memory { + // fpga ddr2: 128MB*2 + reg = <0 0x40000000 0 0x20000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_green: led@0 { + label = "green:power"; + gpios = <&pio 9 GPIO_ACTIVE_HIGH>; + }; + + led_orange: led@1 { + label = "orange:wan"; + gpios = <&pio 34 GPIO_ACTIVE_HIGH>; + }; + + led_blue: led@2 { + label = "blue:wlan5g"; + gpios = <&pio 35 GPIO_ACTIVE_HIGH>; + }; + }; + + nmbm_spim_nand { + compatible = "generic,nmbm"; + + #address-cells = <1>; + #size-cells = <1>; + + lower-mtd-device = <&spi_nand>; + forced-create; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + }; + + partition@580000 { + label = "rootfs1"; + reg = <0x580000 0x4000000>; + compatible = "linux,ubi"; + }; + + partition@4580000 { + label = "rootfs2"; + reg = <0x4580000 0x4000000>; + compatible = "linux,ubi"; + }; + }; + }; + + sound_wm8960 { + compatible = "mediatek,mt7986-wm8960-sound"; + audio-routing = "Headphone", "HP_L", + "Headphone", "HP_R", + "LINPUT1", "AMIC", + "RINPUT1", "AMIC"; + + status = "disabled"; + + platform { + sound-dai = <&afe>; + }; + + codec { + sound-dai = <&wm8960>; + }; + }; + + sound_si3218x { + compatible = "mediatek,mt7986-si3218x-sound"; + status = "disabled"; + + platform { + sound-dai = <&afe>; + }; + + codec { + sound-dai = <&proslic_spi>; + }; + }; +}; + +&afe { + pinctrl-names = "default"; + pinctrl-0 = <&pcm_pins>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "disabled"; + + wm8960: wm8960@1a { + compatible = "wlf,wm8960"; + reg = <0x1a>; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "sgmii"; + phy-handle = <&phy1>; // add phy handler + mtd-mac-address = <&factory 0x24>; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&phy0>; + mtd-mac-address = <&factory 0x2a>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@0 { + compatible = "ethernet-phy-id03a2.9461"; + reg = <0>; + phy-mode = "gmii"; + nvmem-cells = <&phy_calibration>; + nvmem-cell-names = "phy-cal-data"; + }; + + phy1: ethernet-phy@1 { + compatible = "ethernet-phy-id03a2.9471"; + reg = <24>; // set phy address to 0x18 + reset-gpios = <&pio 39 1>; + reset-assert-us = <600>; + reset-deassert-us = <20000>; + phy-mode = "sgmii"; + }; + + }; +}; + +&hnat { + mtketh-wan = "eth1"; + mtketh-lan = "lan"; + mtketh-max-gmac = <2>; + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic_pins>; + status = "okay"; + + proslic_spi: proslic_spi@0 { + compatible = "silabs,proslic_spi"; + reg = <0>; + spi-max-frequency = <10000000>; + spi-cpha = <1>; + spi-cpol = <1>; + channel_count = <1>; + debug_level = <4>; /* 1 = TRC, 2 = DBG, 4 = ERR */ + reset_gpio = <&pio 15 0>; + ig,enable-spi = <1>; /* 1: Enable, 0: Disable */ + }; +}; + +&wbsys { + mediatek,mtd-eeprom = <&factory 0x0000>; + status = "okay"; + pinctrl-names = "dbdc"; + pinctrl-0 = <&wf_dbdc_pins>; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_pins>; + status = "okay"; + + slb9670: slb9670@0 { + compatible = "infineon,slb9670"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <2>; + spi-cal-data = /bits/ 8 <0x00 0x1b>; + spi-max-frequency = <40000000>; + }; +}; + +&pio { + + i2c_pins: i2c-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_0"; + }; + }; + + pcm_pins: pcm-pins-g0 { + mux { + function = "pcm"; + groups = "pcm"; + }; + }; + + pwm0_pin: pwm0-pin-g0 { + mux { + function = "pwm"; + groups = "pwm0_0"; + }; + }; + + pwm1_pin: pwm1-pin-g0 { + mux { + function = "pwm"; + groups = "pwm1_0"; + }; + }; + + pwm2_pin: pwm2-pin { + mux { + function = "pwm"; + groups = "pwm2"; + }; + }; + + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + + spic_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1_1"; + }; + }; + + spi2_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2"; + }; + }; + + uart1_pins: uart1-pins-g1 { + mux { + function = "uart"; + groups = "uart1_1"; + }; + }; + + uart2_pins: uart2-pins-g1 { + mux { + function = "uart"; + groups = "uart2_1"; + }; + }; + + wf_dbdc_pins: wf_dbdc-pins { + mux { + function = "eth"; + groups = "wf0_mode1"; + }; + conf { + pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4", + "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6", + "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10", + "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ", + "WF_CBA_RESETB", "WF_DIG_RESETB"; + drive-strength = ; + }; + }; +}; + +&xhci { + mediatek,u3p-dis-msk = <0x0>; + phys = <&u2port0 PHY_TYPE_USB2>, + <&u3port0 PHY_TYPE_USB3>; + status = "okay"; +}; diff --git a/feeds/mediatek-sdk/mediatek/mt7981/config-5.4 b/feeds/mediatek-sdk/mediatek/mt7981/config-5.4 index c88d0584b..c3920ebf7 100644 --- a/feeds/mediatek-sdk/mediatek/mt7981/config-5.4 +++ b/feeds/mediatek-sdk/mediatek/mt7981/config-5.4 @@ -1,8 +1,9 @@ CONFIG_64BIT=y CONFIG_AHCI_MTK=y -# CONFIG_AIROHA_AN8801_PHY is not set CONFIG_AIROHA_EN8801SC_PHY=y # CONFIG_AIROHA_EN8811H_PHY is not set +# CONFIG_AIROHA_AN8801_PHY is not set +CONFIG_AN8855_GSW=y CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_ARCH_KEEP_MEMBLOCK=y @@ -59,12 +60,9 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_SD=y CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y CONFIG_BLK_PM=y CONFIG_BLK_SCSI_REQUEST=y CONFIG_BLOCK_COMPAT=y -# CONFIG_BPF_KPROBE_OVERRIDE is not set -CONFIG_BRIDGE_NETFILTER=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_BT=y @@ -124,9 +122,7 @@ CONFIG_CRC16=y CONFIG_CRYPTO_ACOMP2=y CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y -# CONFIG_CRYPTO_CAVP_TEST is not set CONFIG_CRYPTO_CMAC=y -# CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG is not set CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_DRBG=y CONFIG_CRYPTO_DRBG_HMAC=y @@ -150,12 +146,10 @@ CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_RNG_DEFAULT=y CONFIG_CRYPTO_SHA256=y -# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set CONFIG_DCACHE_WORD_ACCESS=y CONFIG_DEBUG_MISC=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -CONFIG_DEV_COREDUMP=y CONFIG_DMADEVICES=y CONFIG_DMATEST=y CONFIG_DMA_DIRECT_REMAP=y @@ -183,7 +177,6 @@ CONFIG_FIX_EARLYCON_MEM=y # CONFIG_FLATMEM_MANUAL is not set CONFIG_FRAME_POINTER=y CONFIG_FUJITSU_ERRATUM_010001=y -# CONFIG_FUNCTION_ERROR_INJECTION is not set CONFIG_FW_LOADER_PAGED_BUF=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_ARCH_TOPOLOGY=y @@ -224,7 +217,6 @@ CONFIG_HARDIRQS_SW_RESEND=y CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT_MAP=y -# CONFIG_HIST_TRIGGERS is not set CONFIG_HOLES_IN_ZONE=y CONFIG_HOTPLUG_CPU=y CONFIG_HWMON=y @@ -243,7 +235,6 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_INITRAMFS_SOURCE="" -# CONFIG_INIT_STACK_ALL is not set CONFIG_IO_URING=y CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_IPTABLES=m @@ -294,10 +285,8 @@ CONFIG_MTD_RAW_NAND=y CONFIG_MTD_SPI_NAND=y # CONFIG_MTD_SPI_NAND_W25N01KV is not set CONFIG_MTD_SPI_NOR=y -# CONFIG_MTD_SPLIT_BCM63XX_FW is not set CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MTD_SPLIT_FIT_FW=y -# CONFIG_MTD_SPLIT_H3C_VFS is not set CONFIG_MTD_UBI=y CONFIG_MTD_UBI_BEB_LIMIT=20 CONFIG_MTD_UBI_BLOCK=y @@ -319,20 +308,19 @@ CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NETFILTER=y -CONFIG_NETFILTER_ADVANCED=y -CONFIG_NETFILTER_FAMILY_BRIDGE=y CONFIG_NETFILTER_XTABLES=m CONFIG_NETFILTER_XT_NAT=m CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m CONFIG_NET_DEVLINK=y CONFIG_NET_DSA=y +CONFIG_NET_DSA_AN8855=y CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_TAG_ARHT=y CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y CONFIG_NET_SWITCHDEV=y CONFIG_NET_VENDOR_MEDIATEK=y -# CONFIG_NF_FLOW_TABLE_NETLINK is not set CONFIG_NLS=y CONFIG_NMBM=y # CONFIG_NMBM_LOG_LEVEL_DEBUG is not set @@ -398,8 +386,8 @@ CONFIG_POWER_RESET_SYSCON=y CONFIG_POWER_SUPPLY=y CONFIG_PRINTK_TIME=y CONFIG_PWM=y -# CONFIG_PWM_GPIO is not set CONFIG_PWM_MEDIATEK=y +# CONFIG_PWM_GPIO is not set # CONFIG_PWM_MTK_DISP is not set CONFIG_PWM_SYSFS=y CONFIG_QUEUED_RWLOCKS=y @@ -416,12 +404,10 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MT6380=y # CONFIG_REGULATOR_RT5190A is not set -CONFIG_RELAY=y -CONFIG_REMOTEPROC=y CONFIG_RESET_CONTROLLER=y CONFIG_RESET_TI_SYSCON=y CONFIG_RFS_ACCEL=y -CONFIG_RICHTEK_RTQ6056=y +# CONFIG_RICHTEK_RTQ6056 is not set CONFIG_RODATA_FULL_DEFAULT_ENABLED=y CONFIG_RPS=y CONFIG_RTC_CLASS=y @@ -442,7 +428,6 @@ CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SGL_ALLOC=y CONFIG_SG_POOL=y -CONFIG_SKB_EXTENSIONS=y CONFIG_SMP=y CONFIG_SPARSEMEM=y CONFIG_SPARSEMEM_EXTREME=y @@ -485,7 +470,6 @@ CONFIG_UBIFS_FS=y CONFIG_UBIFS_FS_ADVANCED_COMPR=y CONFIG_UBIFS_FS_LZO=y CONFIG_UBIFS_FS_ZLIB=y -CONFIG_UBIFS_FS_ZSTD=y # CONFIG_UCLAMP_TASK is not set # CONFIG_UNMAP_KERNEL_AT_EL0 is not set CONFIG_USB=y @@ -501,12 +485,7 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_MTK=y CONFIG_USB_XHCI_MTK_DEBUGFS=y # CONFIG_USB_XHCI_PLATFORM is not set -CONFIG_VIRTIO=y -# CONFIG_VIRTIO_BLK is not set -# CONFIG_VIRTIO_CONSOLE is not set -# CONFIG_VIRTIO_NET is not set CONFIG_VMAP_STACK=y -CONFIG_WANT_DEV_COREDUMP=y CONFIG_WATCHDOG_CORE=y CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV=y @@ -518,4 +497,25 @@ CONFIG_XPS=y CONFIG_ZLIB_DEFLATE=y CONFIG_ZLIB_INFLATE=y CONFIG_ZONE_DMA32=y +# CONFIG_BPF_KPROBE_OVERRIDE is not set +# CONFIG_HIST_TRIGGERS is not set +# CONFIG_FUNCTION_ERROR_INJECTION is not set +CONFIG_RICHTEK_RTQ6056=y CONFIG_ZTS8032=y +# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set +# CONFIG_CRYPTO_CAVP_TEST is not set +# CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y +CONFIG_NETFILTER_FAMILY_BRIDGE=y +CONFIG_SKB_EXTENSIONS=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +CONFIG_RELAY=y +CONFIG_BLK_MQ_VIRTIO=y +CONFIG_DEV_COREDUMP=y +CONFIG_REMOTEPROC=y +CONFIG_VIRTIO=y +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_VIRTIO_CONSOLE=n +CONFIG_VIRTIO_NET=n +CONFIG_VIRTIO_BLK=n diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch index d40cbfb85..fb959ce4e 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch @@ -81,7 +81,7 @@ }; cpus { -@@ -40,23 +39,36 @@ +@@ -39,23 +39,36 @@ gpio-keys { compatible = "gpio-keys"; @@ -99,9 +99,9 @@ linux,code = ; - gpios = <&pio 102 0>; + gpios = <&pio 102 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ + }; + }; + + leds { + compatible = "gpio-leds"; + @@ -113,10 +113,10 @@ + red { + label = "bpi-r64:pio:red"; + gpios = <&pio 88 GPIO_ACTIVE_HIGH>; - }; - }; - - memory { ++ }; ++ }; ++ + memory@40000000 { - reg = <0 0x40000000 0 0x20000000>; + reg = <0 0x40000000 0 0x40000000>; }; diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch index df4f9f9f0..d3434eb33 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch @@ -477,7 +477,7 @@ Index: linux-5.4.260/drivers/mtd/nand/spi/macronix.c + SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), - SPINAND_INFO("MX35LF4GE4AD", 0x37, -- NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), +- NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1), + SPINAND_INFO("MX35LF2G24AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), diff --git a/feeds/mediatek-sdk/mediatek/hack-5.4/999-2540-cmdline-boot-parameters.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2540-cmdline-boot-parameters.patch similarity index 95% rename from feeds/mediatek-sdk/mediatek/hack-5.4/999-2540-cmdline-boot-parameters.patch rename to feeds/mediatek-sdk/mediatek/patches-5.4/999-2540-cmdline-boot-parameters.patch index eadc28872..a160814e6 100644 --- a/feeds/mediatek-sdk/mediatek/hack-5.4/999-2540-cmdline-boot-parameters.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2540-cmdline-boot-parameters.patch @@ -27,7 +27,7 @@ new file mode 100644 index 000000000..3dfe828bc --- /dev/null +++ b/kernel/boot_param.c -@@ -0,0 +1,44 @@ +@@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* +* Copyright (C) 2022 MediaTek Inc. All rights reserved. @@ -40,9 +40,12 @@ index 000000000..3dfe828bc + +#define BOOT_PARAM_STR_MAX_LEN 256 + -+static bool dual_boot; ++bool dual_boot; +module_param(dual_boot, bool, 0444); + ++static bool reset_boot_count; ++module_param(reset_boot_count, bool, 0444); ++ +static bool no_split_rootfs_data; +module_param(no_split_rootfs_data, bool, 0444); + diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch index 350e7d3ec..48b94cdce 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch @@ -22,19 +22,6 @@ index cd5fca8aa..2dfc0dac7 100644 return; #endif #ifdef CONFIG_BLOCK -diff --git a/kernel/boot_param.c b/kernel/boot_param.c -index 3dfe828bc..cc0b2b8b0 100644 ---- a/kernel/boot_param.c -+++ b/kernel/boot_param.c -@@ -10,7 +10,7 @@ - - #define BOOT_PARAM_STR_MAX_LEN 256 - --static bool dual_boot; -+bool dual_boot; - module_param(dual_boot, bool, 0444); - - static bool no_split_rootfs_data; -- 2.34.1 diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2601-pcie-add-multi-MSI-support.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2601-pcie-add-multi-MSI-support.patch index 80ce1456c..1707d206e 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2601-pcie-add-multi-MSI-support.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2601-pcie-add-multi-MSI-support.patch @@ -54,23 +54,3 @@ index db3672917..44a046005 100644 .chip = &mtk_msi_irq_chip, }; -@@ -627,14 +627,14 @@ static void mtk_pcie_intr_handler(struct irq_desc *desc) - if (status & MSI_STATUS){ - unsigned long imsi_status; - -+ /* Clear MSI interrupt status */ -+ writel(MSI_STATUS, port->base + PCIE_INT_STATUS); - while ((imsi_status = readl(port->base + PCIE_IMSI_STATUS))) { - for_each_set_bit(bit, &imsi_status, MTK_MSI_IRQS_NUM) { - virq = irq_find_mapping(port->inner_domain, bit); - generic_handle_irq(virq); - } - } -- /* Clear MSI interrupt status */ -- writel(MSI_STATUS, port->base + PCIE_INT_STATUS); - } - } - --- -2.34.1 - diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_dsa_add_an8855.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_dsa_add_an8855.patch new file mode 100644 index 000000000..d089c964a --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_dsa_add_an8855.patch @@ -0,0 +1,25 @@ +Index: linux-5.4.238/drivers/net/dsa/Kconfig +=================================================================== +--- linux-5.4.238.orig/drivers/net/dsa/Kconfig 2023-12-26 15:31:49.427259000 +0800 ++++ linux-5.4.238/drivers/net/dsa/Kconfig 2023-12-26 15:46:52.655226000 +0800 +@@ -48,6 +48,8 @@ + This enables support for the Marvell 88E6060 ethernet switch + chip. + ++source "drivers/net/dsa/airoha/an8855/Kconfig" ++ + source "drivers/net/dsa/microchip/Kconfig" + + source "drivers/net/dsa/mv88e6xxx/Kconfig" +Index: linux-5.4.238/drivers/net/dsa/Makefile +=================================================================== +--- linux-5.4.238.orig/drivers/net/dsa/Makefile 2023-12-26 15:32:08.081306000 +0800 ++++ linux-5.4.238/drivers/net/dsa/Makefile 2023-12-26 15:47:59.858217000 +0800 +@@ -18,6 +18,7 @@ + obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX) += vitesse-vsc73xx-core.o + obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM) += vitesse-vsc73xx-platform.o + obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX_SPI) += vitesse-vsc73xx-spi.o ++obj-y += airoha/an8855/ + obj-y += b53/ + obj-y += microchip/ + obj-y += mv88e6xxx/ diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_ethernet_mediatek_hnat.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_ethernet_mediatek_hnat.patch new file mode 100644 index 000000000..34855a522 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_ethernet_mediatek_hnat.patch @@ -0,0 +1,13 @@ +Index: linux-5.4.238/drivers/net/ethernet/mediatek/mtk_hnat/Makefile +=================================================================== +--- linux-5.4.238.orig/drivers/net/ethernet/mediatek/mtk_hnat/Makefile 2023-09-05 21:55:25.000000000 +0800 ++++ linux-5.4.238/drivers/net/ethernet/mediatek/mtk_hnat/Makefile 2023-12-18 11:26:54.110684000 +0800 +@@ -2,4 +2,8 @@ + + obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtkhnat.o + mtkhnat-objs := hnat.o hnat_nf_hook.o hnat_debugfs.o hnat_mcast.o ++ifeq ($(CONFIG_NET_DSA_AN8855), y) ++mtkhnat-y += hnat_stag.o ++else + mtkhnat-$(CONFIG_NET_DSA_MT7530) += hnat_stag.o ++endif diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_phy_add_an8855_gsw.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_phy_add_an8855_gsw.patch new file mode 100644 index 000000000..58220b361 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-drivers_net_phy_add_an8855_gsw.patch @@ -0,0 +1,24 @@ +Index: linux-5.4.238/drivers/net/phy/Kconfig +=================================================================== +--- linux-5.4.238.orig/drivers/net/phy/Kconfig 2023-12-19 12:20:34.714805000 +0800 ++++ linux-5.4.238/drivers/net/phy/Kconfig 2023-12-25 10:11:11.328554000 +0800 +@@ -337,6 +337,8 @@ + + source "drivers/net/phy/mtk/mt753x/Kconfig" + ++source "drivers/net/phy/airoha/an8855/Kconfig" ++ + comment "MII PHY device drivers" + + config SFP +Index: linux-5.4.238/drivers/net/phy/Makefile +=================================================================== +--- linux-5.4.238.orig/drivers/net/phy/Makefile 2023-12-19 12:20:34.718809000 +0800 ++++ linux-5.4.238/drivers/net/phy/Makefile 2023-12-25 10:13:11.891535000 +0800 +@@ -121,5 +121,6 @@ + obj-$(CONFIG_VITESSE_PHY) += vitesse.o + obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o + obj-$(CONFIG_MT753X_GSW) += mtk/mt753x/ ++obj-$(CONFIG_AN8855_GSW) += airoha/an8855/ + obj-$(CONFIG_RTL8367S_GSW) += rtk/ + diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-net_dsa_add_tag_arht.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-net_dsa_add_tag_arht.patch new file mode 100644 index 000000000..ca36a0ce1 --- /dev/null +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2739-net_dsa_add_tag_arht.patch @@ -0,0 +1,46 @@ +Index: linux-5.4.238/net/dsa/Makefile +=================================================================== +--- linux-5.4.238.orig/net/dsa/Makefile 2023-12-09 09:43:04.335694000 +0800 ++++ linux-5.4.238/net/dsa/Makefile 2023-12-09 10:24:27.672514000 +0800 +@@ -16,3 +16,4 @@ + obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o + obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o + obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o ++obj-$(CONFIG_NET_DSA_TAG_AIROHA) += tag_arht.o +Index: linux-5.4.238/net/dsa/Kconfig +=================================================================== +--- linux-5.4.238.orig/net/dsa/Kconfig 2023-12-09 09:43:04.332694000 +0800 ++++ linux-5.4.238/net/dsa/Kconfig 2023-12-09 10:26:13.596504000 +0800 +@@ -74,6 +74,12 @@ + Say Y or M if you want to enable support for tagging frames for + Mediatek switches. + ++config NET_DSA_TAG_AIROHA ++ tristate "Tag driver for Airoha switches" ++ help ++ Say Y or M if you want to enable support for tagging frames for ++ Airoha switches. ++ + config NET_DSA_TAG_KSZ + tristate "Tag driver for Microchip 8795/9477/9893 families of switches" + help +Index: linux-5.4.238/include/net/dsa.h +=================================================================== +--- linux-5.4.238.orig/include/net/dsa.h 2023-12-09 09:43:17.940694000 +0800 ++++ linux-5.4.238/include/net/dsa.h 2023-12-09 10:30:06.432504000 +0800 +@@ -43,6 +43,7 @@ + #define DSA_TAG_PROTO_SJA1105_VALUE 13 + #define DSA_TAG_PROTO_KSZ8795_VALUE 14 + #define DSA_TAG_PROTO_RTL4_A_VALUE 17 ++#define DSA_TAG_PROTO_ARHT_VALUE 28 + + enum dsa_tag_protocol { + DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, +@@ -61,6 +62,7 @@ + DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE, + DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE, + DSA_TAG_PROTO_RTL4_A = DSA_TAG_PROTO_RTL4_A_VALUE, ++ DSA_TAG_PROTO_ARHT = DSA_TAG_PROTO_ARHT_VALUE, + }; + + struct packet_type; diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch deleted file mode 100644 index 86d3edb28..000000000 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 4136e3567f6904259babbe5ae5c0d0bf06413f57 Mon Sep 17 00:00:00 2001 -From: Bo-Cun Chen -Date: Wed, 25 Oct 2023 09:21:06 +0800 -Subject: [PATCH] 999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K - ---- - drivers/net/ethernet/mediatek/mtk_eth_dbg.c | 2 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 74 ++++++++++--------- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +- - .../ethernet/mediatek/mtk_hnat/hnat_debugfs.c | 2 +- - .../ethernet/mediatek/mtk_hnat/hnat_nf_hook.c | 23 ++++++ - 5 files changed, 69 insertions(+), 37 deletions(-) - -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c -index e50e1ac..7c137e5 100755 ---- a/drivers/net/ethernet/mediatek/mtk_eth_dbg.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c -@@ -882,7 +882,7 @@ int hwtx_ring_read(struct seq_file *seq, void *v) - struct mtk_tx_dma_v2 *hwtx_ring; - int i = 0; - -- for (i = 0; i < MTK_DMA_SIZE; i++) { -+ for (i = 0; i < MTK_DMA_FQ_SIZE; i++) { - dma_addr_t addr = eth->phy_scratch_ring + - i * (dma_addr_t)eth->soc->txrx.txd_size; - -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 1226dd6..fe9c1de 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1557,10 +1557,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) - { - const struct mtk_soc_data *soc = eth->soc; - dma_addr_t phy_ring_tail; -- int cnt = MTK_DMA_SIZE; -+ int cnt = MTK_DMA_FQ_SIZE; - dma_addr_t dma_addr; - u64 addr64 = 0; -- int i; -+ int i, j, len; - - if (!eth->soc->has_sram) { - eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, -@@ -1577,40 +1577,44 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) - if (unlikely(!eth->scratch_ring)) - return -ENOMEM; - -- eth->scratch_head = kcalloc(cnt, MTK_QDMA_PAGE_SIZE, GFP_KERNEL); -- if (unlikely(!eth->scratch_head)) -- return -ENOMEM; -- -- dma_addr = dma_map_single(eth->dma_dev, -- eth->scratch_head, cnt * MTK_QDMA_PAGE_SIZE, -- DMA_FROM_DEVICE); -- if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) -- return -ENOMEM; -- - phy_ring_tail = eth->phy_scratch_ring + - (dma_addr_t)soc->txrx.txd_size * (cnt - 1); - -- for (i = 0; i < cnt; i++) { -- struct mtk_tx_dma_v2 *txd; -+ for (j = 0; j < DIV_ROUND_UP(MTK_DMA_FQ_SIZE, MTK_DMA_FQ_LENGTH); j++) { -+ len = min_t(int, cnt - j * MTK_DMA_FQ_LENGTH, MTK_DMA_FQ_LENGTH); - -- txd = eth->scratch_ring + i * soc->txrx.txd_size; -- txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; -- if (i < cnt - 1) -- txd->txd2 = eth->phy_scratch_ring + -- (i + 1) * soc->txrx.txd_size; -+ eth->scratch_head[j] = kcalloc(len, MTK_QDMA_PAGE_SIZE, GFP_KERNEL); -+ if (unlikely(!eth->scratch_head[j])) -+ return -ENOMEM; - -- addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ? -- TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0; -+ dma_addr = dma_map_single(eth->dma_dev, -+ eth->scratch_head[j], len * MTK_QDMA_PAGE_SIZE, -+ DMA_FROM_DEVICE); -+ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) -+ return -ENOMEM; - -- txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64; -- txd->txd4 = 0; -+ for (i = 0; i < len; i++) { -+ struct mtk_tx_dma_v2 *txd; - -- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) || -- MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { -- txd->txd5 = 0; -- txd->txd6 = 0; -- txd->txd7 = 0; -- txd->txd8 = 0; -+ txd = eth->scratch_ring + (j * MTK_DMA_FQ_LENGTH + i) * soc->txrx.txd_size; -+ txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; -+ if (j * MTK_DMA_FQ_LENGTH + i < cnt) -+ txd->txd2 = eth->phy_scratch_ring + -+ (j * MTK_DMA_FQ_LENGTH + i + 1) * soc->txrx.txd_size; -+ -+ addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ? -+ TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0; -+ -+ txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64; -+ txd->txd4 = 0; -+ -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) || -+ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { -+ txd->txd5 = 0; -+ txd->txd6 = 0; -+ txd->txd7 = 0; -+ txd->txd8 = 0; -+ } - } - } - -@@ -2541,9 +2545,9 @@ static int mtk_tx_alloc(struct mtk_eth *eth) - ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz, - &ring->phys, GFP_KERNEL); - else { -- ring->dma = eth->sram_base + MTK_DMA_SIZE * sz; -+ ring->dma = eth->sram_base + MTK_DMA_FQ_SIZE * sz; - ring->phys = eth->phy_scratch_ring + -- MTK_DMA_SIZE * (dma_addr_t)sz; -+ MTK_DMA_FQ_SIZE * (dma_addr_t)sz; - } - - if (!ring->dma) -@@ -3349,9 +3353,11 @@ static void mtk_dma_free(struct mtk_eth *eth) - mtk_rx_clean(eth, ð->rx_ring[MTK_RSS_RING(i)], 1); - } - -- if (eth->scratch_head) { -- kfree(eth->scratch_head); -- eth->scratch_head = NULL; -+ for (i = 0; i < DIV_ROUND_UP(MTK_DMA_FQ_SIZE, MTK_DMA_FQ_LENGTH); i++) { -+ if (eth->scratch_head[i]) { -+ kfree(eth->scratch_head[i]); -+ eth->scratch_head[i] = NULL; -+ } - } - } - -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -index fe8bdee..cd2de23 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -20,6 +20,9 @@ - #define MTK_MAX_RX_LENGTH 1536 - #define MTK_MIN_TX_LENGTH 60 - #define MTK_DMA_SIZE 2048 -+#define MTK_DMA_FQ_SIZE 4096 -+#define MTK_DMA_FQ_HEAD 32 -+#define MTK_DMA_FQ_LENGTH 2048 - #define MTK_NAPI_WEIGHT 256 - - #if defined(CONFIG_MEDIATEK_NETSYS_V3) -@@ -1837,7 +1840,7 @@ struct mtk_eth { - void *scratch_ring; - struct mtk_reset_event reset_event; - dma_addr_t phy_scratch_ring; -- void *scratch_head; -+ void *scratch_head[MTK_DMA_FQ_HEAD]; - struct clk *clks[MTK_CLK_MAX]; - - struct mii_bus *mii_bus; -diff --git a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c -index fc7d216..b97fd6a 100644 ---- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c -+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c -@@ -2784,7 +2784,7 @@ static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffe - qos_toggle = 1; - } else if (buf[0] == '2') { - pr_info("Per-port-per-queue mode is going to be enabled!\n"); -- pr_info("PPPQ use qid 0~5 (scheduler 0).\n"); -+ pr_info("PPPQ use qid 0~11 (scheduler 0).\n"); - qos_toggle = 2; - qos_dl_toggle = 1; - qos_ul_toggle = 1; -diff --git a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c -index 85c38e0..6a373f8 100644 ---- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c -+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c -@@ -1219,6 +1219,7 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb, - int udp = 0; - u32 qid = 0; - u32 port_id = 0; -+ u32 payload_len = 0; - int mape = 0; - - ct = nf_ct_get(skb, &ctinfo); -@@ -1748,6 +1749,28 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb, - else - qid = 0; - -+ if (IS_PPPQ_MODE && IS_PPPQ_PATH(dev, skb)) { -+ if (ntohs(eth->h_proto) == ETH_P_IP) { -+ iph = ip_hdr(skb); -+ if (iph->protocol == IPPROTO_TCP) { -+ skb_set_transport_header(skb, sizeof(struct iphdr)); -+ payload_len = be16_to_cpu(iph->tot_len) - skb_transport_offset(skb) - tcp_hdrlen(skb); -+ /* Dispatch ACK packets to high priority queue */ -+ if (payload_len == 0) -+ qid += 6; -+ } -+ } else if (ntohs(eth->h_proto) == ETH_P_IPV6) { -+ ip6h = ipv6_hdr(skb); -+ if (ip6h->nexthdr == NEXTHDR_TCP) { -+ skb_set_transport_header(skb, sizeof(struct ipv6hdr)); -+ payload_len = be16_to_cpu(ip6h->payload_len) - tcp_hdrlen(skb); -+ /* Dispatch ACK packets to high priority queue */ -+ if (payload_len == 0) -+ qid += 6; -+ } -+ } -+ } -+ - if (IS_IPV4_GRP(foe)) { - entry.ipv4_hnapt.iblk2.dp = gmac; - entry.ipv4_hnapt.iblk2.port_mg = --- -2.18.0 - diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3000-ovs-add-multicast-to-unicast-support.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3000-ovs-add-multicast-to-unicast-support.patch index dc060ea66..afd633ac8 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3000-ovs-add-multicast-to-unicast-support.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3000-ovs-add-multicast-to-unicast-support.patch @@ -1,4 +1,4 @@ -From 4d7eabd37042f541f085cca6265bd22ae3f05e6e Mon Sep 17 00:00:00 2001 +From 2d5090dc6072979167593c8fee026341774efb53 Mon Sep 17 00:00:00 2001 From: mtk22468 Date: Mon, 18 Sep 2023 10:50:36 +0800 Subject: [PATCH] ovs add multicast to unicast support @@ -6,13 +6,13 @@ Subject: [PATCH] ovs add multicast to unicast support --- net/openvswitch/actions.c | 30 ++++ net/openvswitch/datapath.c | 290 +++++++++++++++++++++++++++++++++++++ - net/openvswitch/datapath.h | 32 ++++ + net/openvswitch/datapath.h | 40 +++++ net/openvswitch/vport.c | 8 + net/openvswitch/vport.h | 26 ++++ - 5 files changed, 386 insertions(+) + 5 files changed, 394 insertions(+) diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c -index 9e8a5c4..e953e62 100644 +index 9e8a5c4..82cd46e 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -919,6 +919,10 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, @@ -30,7 +30,7 @@ index 9e8a5c4..e953e62 100644 if (likely(!mru || (skb->len <= mru + vport->dev->hard_header_len))) { -+ if (is_multicast_addr(skb) && !is_igmp_mld(skb)) { ++ if (is_multicast_addr(skb) && !is_igmp_mld(skb) && !is_icmpv6_ndp_rs_ra(skb)) { + mdb = vport->mdb; + spin_lock_bh(&mdb->tbl_lock); + list_for_each_entry(table, &mdb->list_head, mdb_node) { @@ -60,7 +60,7 @@ index 9e8a5c4..e953e62 100644 } else if (mru <= vport->dev->mtu) { struct net *net = read_pnet(&dp->net); diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c -index 4c537e7..e6787cc 100644 +index 4c537e7..0c8d344 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -11,6 +11,9 @@ @@ -349,7 +349,7 @@ index 4c537e7..e6787cc 100644 OVS_CB(packet)->input_vport = input_vport; sf_acts = rcu_dereference(flow->sf_acts); -+ if (is_multicast_addr(packet)) ++ if (is_multicast_addr(packet) && !is_icmpv6_ndp_rs_ra(packet)) + ovs_multicast_rcv(packet, input_vport); + local_bh_disable(); @@ -389,10 +389,10 @@ index 4c537e7..e6787cc 100644 ovs_dp_detach_port(vport); diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h -index 81e85dd..6830d3b 100644 +index 81e85dd..50596bc 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h -@@ -215,6 +215,38 @@ static inline struct datapath *get_dp(struct net *net, int dp_ifindex) +@@ -215,6 +215,46 @@ static inline struct datapath *get_dp(struct net *net, int dp_ifindex) return dp; } @@ -427,6 +427,14 @@ index 81e85dd..6830d3b 100644 + + return err; +} ++ ++static inline bool is_icmpv6_ndp_rs_ra(struct sk_buff *skb) ++{ ++ if (!skb) ++ return 0; ++ ++ return ((icmp6_hdr(skb)->icmp6_type == NDISC_ROUTER_SOLICITATION) && (icmp6_hdr(skb)->icmp6_type == NDISC_ROUTER_ADVERTISEMENT)); ++} + extern struct notifier_block ovs_dp_device_notifier; extern struct genl_family dp_vport_genl_family; diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch index 37666e65a..9f22f379e 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch @@ -1,51 +1,50 @@ -From 3a07dcf1a402223c3d96eed88f9dcb8eac0a9362 Mon Sep 17 00:00:00 2001 -From: Sujuan Chen -Date: Mon, 18 Sep 2023 10:58:32 +0800 +From 07a3ac0ae724c4df67316e01b03432d8ee9f4229 Mon Sep 17 00:00:00 2001 +From: Bo-Cun Chen +Date: Mon, 18 Mar 2024 17:56:01 +0800 Subject: [PATCH 04/24] ethernet update ppe from netsys1 to netsys2 --- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 ++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 19 ++++--- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 ++- drivers/net/ethernet/mediatek/mtk_ppe.c | 29 +++++++++-- drivers/net/ethernet/mediatek/mtk_ppe.h | 51 +++++++++++++++++++ .../net/ethernet/mediatek/mtk_ppe_offload.c | 8 +++ drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 10 ++++ - 6 files changed, 113 insertions(+), 6 deletions(-) + 6 files changed, 112 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 8d15399..45dc85f 100644 +index ffaa515..9262227 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2447,16 +2447,27 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, +@@ -2447,16 +2447,20 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, skb_checksum_none_assert(skb); skb->protocol = eth_type_trans(skb, netdev); -- hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY; -+#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) -+ hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2; -+#else -+ hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY; -+#endif - if (hash != MTK_RXD4_FOE_ENTRY) { - hash = jhash_1word(hash, 0); - skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); - } - +#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) ++ hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2; + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5); -+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -+ mtk_ppe_check_skb(eth->ppe, skb, -+ trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2); ++ if (hash != MTK_RXD5_FOE_ENTRY_V2) ++ skb_set_hash(skb, jhash_1word(hash, 0), PKT_HASH_TYPE_L4); +#else + hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY; +- if (hash != MTK_RXD4_FOE_ENTRY) { +- hash = jhash_1word(hash, 0); +- skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); +- } +- reason = FIELD_GET(MTK_RXD4_PPE_CPU_REASON, trxd.rxd4); - if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) - mtk_ppe_check_skb(eth->ppe, skb, - trxd.rxd4 & MTK_RXD4_FOE_ENTRY); ++ if (hash != MTK_RXD4_FOE_ENTRY) ++ skb_set_hash(skb, jhash_1word(hash, 0), PKT_HASH_TYPE_L4); +#endif ++ + if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) +- mtk_ppe_check_skb(eth->ppe, skb, +- trxd.rxd4 & MTK_RXD4_FOE_ENTRY); ++ mtk_ppe_check_skb(eth->ppe, skb, hash); if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) { -@@ -5953,6 +5964,7 @@ static const struct mtk_soc_data mt7986_data = { +@@ -5957,6 +5961,7 @@ static const struct mtk_soc_data mt7986_data = { .required_clks = MT7986_CLKS_BITMAP, .required_pctl = false, .has_sram = false, @@ -54,7 +53,7 @@ index 8d15399..45dc85f 100644 .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -index 00cfe3b..69eb112 100644 +index 41daeb2..910baaf 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -137,7 +137,7 @@ @@ -66,7 +65,7 @@ index 00cfe3b..69eb112 100644 #define MTK_GDMA_DROP_ALL 0x7777 /* GDM Egress Control Register */ -@@ -674,6 +674,11 @@ +@@ -680,6 +680,11 @@ #define MTK_RXD4_SRC_PORT GENMASK(21, 19) #define MTK_RXD4_ALG GENMASK(31, 22) diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch index 458379d6d..5ff363b9c 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch @@ -1,18 +1,18 @@ -From d35e908b342bce34e01c29a07328a4a245d5d79d Mon Sep 17 00:00:00 2001 +From 01556d88ad11f0d096d2816b2a69999994e1740f Mon Sep 17 00:00:00 2001 From: Bo-Cun Chen -Date: Tue, 26 Dec 2023 16:31:34 +0800 +Date: Mon, 18 Mar 2024 16:26:28 +0800 Subject: [PATCH 05/24] flow-offload-add-mkhnat-dual-ppe-new-v2 --- arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 1 + - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 58 ++++++++++++++----- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 14 ++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 50 ++++++++++++++----- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 14 ++++-- drivers/net/ethernet/mediatek/mtk_ppe.c | 5 +- drivers/net/ethernet/mediatek/mtk_ppe.h | 7 ++- - .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 27 ++++++--- - .../net/ethernet/mediatek/mtk_ppe_offload.c | 48 +++++++++++---- + .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 27 +++++++--- + .../net/ethernet/mediatek/mtk_ppe_offload.c | 48 ++++++++++++++---- include/linux/netdevice.h | 4 ++ - 8 files changed, 124 insertions(+), 40 deletions(-) + 8 files changed, 119 insertions(+), 37 deletions(-) mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_ppe_offload.c diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi @@ -28,31 +28,19 @@ index 3a4f279..d70151b 100644 #address-cells = <1>; #size-cells = <0>; diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 45dc85f..07209f0 100644 +index 2fb67e0..7eeddb3 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2459,14 +2459,16 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, - - #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) - reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5); -- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -- mtk_ppe_check_skb(eth->ppe, skb, -+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) { -+ mtk_ppe_check_skb(eth->ppe[0], skb, - trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2); -+ } - #else - reason = FIELD_GET(MTK_RXD4_PPE_CPU_REASON, trxd.rxd4); -- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) -- mtk_ppe_check_skb(eth->ppe, skb, -+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) { -+ mtk_ppe_check_skb(eth->ppe[0], skb, - trxd.rxd4 & MTK_RXD4_FOE_ENTRY); -+ } +@@ -2464,7 +2464,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, #endif + if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) +- mtk_ppe_check_skb(eth->ppe, skb, hash); ++ mtk_ppe_check_skb(eth->ppe[0], skb, hash); + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { -@@ -4111,8 +4113,12 @@ static int mtk_open(struct net_device *dev) + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) { +@@ -4112,8 +4112,12 @@ static int mtk_open(struct net_device *dev) regmap_write(eth->sgmii->pcs[id].regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); @@ -67,7 +55,7 @@ index 45dc85f..07209f0 100644 mtk_gdm_config(eth, mac->id, gdm_config); -@@ -4201,8 +4207,10 @@ static int mtk_stop(struct net_device *dev) +@@ -4202,8 +4206,10 @@ static int mtk_stop(struct net_device *dev) mtk_dma_free(eth); @@ -80,7 +68,7 @@ index 45dc85f..07209f0 100644 return 0; } -@@ -5761,15 +5769,35 @@ static int mtk_probe(struct platform_device *pdev) +@@ -5762,15 +5768,35 @@ static int mtk_probe(struct platform_device *pdev) } if (eth->soc->offload_version) { @@ -124,7 +112,7 @@ index 45dc85f..07209f0 100644 for (i = 0; i < MTK_MAX_DEVS; i++) { diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -index 69eb112..a00583f 100644 +index 910baaf..3995608 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -137,7 +137,12 @@ @@ -141,7 +129,7 @@ index 69eb112..a00583f 100644 #define MTK_GDMA_DROP_ALL 0x7777 /* GDM Egress Control Register */ -@@ -1932,7 +1937,8 @@ struct mtk_eth { +@@ -1936,7 +1941,8 @@ struct mtk_eth { spinlock_t syscfg0_lock; struct timer_list mtk_dma_monitor_timer; @@ -151,7 +139,7 @@ index 69eb112..a00583f 100644 struct rhashtable flow_table; }; -@@ -2015,9 +2021,11 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r); +@@ -2019,9 +2025,11 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r); int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range); void mtk_usxgmii_link_poll(struct work_struct *work); diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch index 4110b83c7..ba80883f7 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch @@ -1,6 +1,6 @@ -From 0247c9d63f56bbe34f4205f986957b5036a9a4d8 Mon Sep 17 00:00:00 2001 -From: Bc-bocun Chen -Date: Mon, 18 Sep 2023 11:11:03 +0800 +From 51573e91708521bdc47a9d6f771f2cbde11e5ed7 Mon Sep 17 00:00:00 2001 +From: "chak-kei.lam" +Date: Tue, 9 Apr 2024 15:05:24 +0800 Subject: [PATCH 12/24] flow-offload-add-mtkhnat-qdma-qos --- @@ -10,10 +10,10 @@ Subject: [PATCH 12/24] flow-offload-add-mtkhnat-qdma-qos drivers/net/ethernet/mediatek/mtk_ppe.c | 48 +- drivers/net/ethernet/mediatek/mtk_ppe.h | 4 + .../net/ethernet/mediatek/mtk_ppe_offload.c | 28 +- - .../net/ethernet/mediatek/mtk_qdma_debugfs.c | 439 ++++++++++++++++++ + .../net/ethernet/mediatek/mtk_qdma_debugfs.c | 448 ++++++++++++++++++ include/net/flow_offload.h | 1 + net/netfilter/nf_flow_table_offload.c | 4 +- - 9 files changed, 581 insertions(+), 5 deletions(-) + 9 files changed, 590 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile @@ -30,10 +30,10 @@ index fdbb90f..c7d2296 100644 ifdef CONFIG_DEBUG_FS mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 9cd306d..1660fd9 100644 +index 60672c6..8e3a276 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -5813,6 +5813,8 @@ static int mtk_probe(struct platform_device *pdev) +@@ -5838,6 +5838,8 @@ static int mtk_probe(struct platform_device *pdev) } mtk_ppe_debugfs_init(eth); @@ -42,7 +42,7 @@ index 9cd306d..1660fd9 100644 } for (i = 0; i < MTK_MAX_DEVS; i++) { -@@ -5925,6 +5927,7 @@ static const struct mtk_soc_data mt2701_data = { +@@ -5953,6 +5955,7 @@ static const struct mtk_soc_data mt2701_data = { .rx_dma_l4_valid = RX_DMA_L4_VALID, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -50,7 +50,7 @@ index 9cd306d..1660fd9 100644 }, }; -@@ -5945,6 +5948,7 @@ static const struct mtk_soc_data mt7621_data = { +@@ -5976,6 +5979,7 @@ static const struct mtk_soc_data mt7621_data = { .rxd_size = sizeof(struct mtk_rx_dma), .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -58,7 +58,7 @@ index 9cd306d..1660fd9 100644 }, }; -@@ -5966,6 +5970,7 @@ static const struct mtk_soc_data mt7622_data = { +@@ -6000,6 +6004,7 @@ static const struct mtk_soc_data mt7622_data = { .rx_dma_l4_valid = RX_DMA_L4_VALID, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -66,7 +66,7 @@ index 9cd306d..1660fd9 100644 }, }; -@@ -5986,6 +5991,7 @@ static const struct mtk_soc_data mt7623_data = { +@@ -6023,6 +6028,7 @@ static const struct mtk_soc_data mt7623_data = { .rx_dma_l4_valid = RX_DMA_L4_VALID, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -74,7 +74,7 @@ index 9cd306d..1660fd9 100644 }, }; -@@ -6026,6 +6032,7 @@ static const struct mtk_soc_data mt7986_data = { +@@ -6069,6 +6075,7 @@ static const struct mtk_soc_data mt7986_data = { .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2, @@ -82,7 +82,7 @@ index 9cd306d..1660fd9 100644 }, }; -@@ -6047,6 +6054,7 @@ static const struct mtk_soc_data mt7981_data = { +@@ -6093,6 +6100,7 @@ static const struct mtk_soc_data mt7981_data = { .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2, @@ -90,7 +90,7 @@ index 9cd306d..1660fd9 100644 }, }; -@@ -6065,6 +6073,7 @@ static const struct mtk_soc_data mt7988_data = { +@@ -6117,6 +6125,7 @@ static const struct mtk_soc_data mt7988_data = { .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2, @@ -98,7 +98,7 @@ index 9cd306d..1660fd9 100644 }, }; -@@ -6083,6 +6092,7 @@ static const struct mtk_soc_data rt5350_data = { +@@ -6138,6 +6147,7 @@ static const struct mtk_soc_data rt5350_data = { .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = MTK_TX_DMA_BUF_SHIFT, @@ -107,10 +107,10 @@ index 9cd306d..1660fd9 100644 }; diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -index 5f90765..02ca0b2 100644 +index 52e4b85..7b3230e 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -487,6 +487,9 @@ +@@ -495,6 +495,9 @@ #define FC_THRES_DROP_EN (7 << 16) #define FC_THRES_MIN 0x4444 @@ -120,7 +120,7 @@ index 5f90765..02ca0b2 100644 /* QDMA Interrupt Status Register */ #define MTK_QDMA_INT_STATUS (QDMA_BASE + 0x218) #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3) -@@ -530,6 +533,11 @@ +@@ -538,6 +541,11 @@ /* QDMA Interrupt Mask Register */ #define MTK_QDMA_HRED2 (QDMA_BASE + 0x244) @@ -132,7 +132,7 @@ index 5f90765..02ca0b2 100644 /* QDMA TX Forward CPU Pointer Register */ #define MTK_QTX_CTX_PTR (QDMA_BASE +0x300) -@@ -557,6 +565,14 @@ +@@ -565,6 +573,14 @@ /* QDMA FQ Free Page Buffer Length Register */ #define MTK_QDMA_FQ_BLEN (QDMA_BASE +0x32c) @@ -147,7 +147,7 @@ index 5f90765..02ca0b2 100644 /* WDMA Registers */ #define MTK_WDMA_CTX_PTR(x) (WDMA_BASE(x) + 0x8) #define MTK_WDMA_DTX_PTR(x) (WDMA_BASE(x) + 0xC) -@@ -1743,6 +1759,7 @@ struct mtk_soc_data { +@@ -1753,6 +1769,7 @@ struct mtk_soc_data { u32 rx_dma_l4_valid; u32 dma_max_len; u32 dma_len_offset; @@ -155,7 +155,7 @@ index 5f90765..02ca0b2 100644 } txrx; }; -@@ -1936,6 +1953,7 @@ struct mtk_eth { +@@ -1946,6 +1963,7 @@ struct mtk_eth { spinlock_t syscfg0_lock; struct timer_list mtk_dma_monitor_timer; @@ -163,7 +163,7 @@ index 5f90765..02ca0b2 100644 u8 ppe_num; struct mtk_ppe *ppe[MTK_MAX_PPE_NUM]; struct rhashtable flow_table; -@@ -1994,6 +2012,36 @@ extern const struct of_device_id of_mtk_match[]; +@@ -2004,6 +2022,36 @@ extern const struct of_device_id of_mtk_match[]; extern u32 mtk_hwlro_stats_ebl; extern u32 dbg_show_level; @@ -200,7 +200,7 @@ index 5f90765..02ca0b2 100644 /* read the hardware status register */ void mtk_stats_update_mac(struct mtk_mac *mac); -@@ -2027,4 +2075,6 @@ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev); +@@ -2037,4 +2085,6 @@ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev); u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index); int mtk_ppe_debugfs_init(struct mtk_eth *eth); @@ -208,10 +208,10 @@ index 5f90765..02ca0b2 100644 +int mtk_qdma_debugfs_init(struct mtk_eth *eth); #endif /* MTK_ETH_H */ diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c -index 94e03b2..8388f65 100755 +index 7b92fff..f5dbfe9 100755 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -128,7 +128,7 @@ static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable) +@@ -139,7 +139,7 @@ static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable) enable * MTK_PPE_CACHE_CTL_EN); } @@ -220,7 +220,7 @@ index 94e03b2..8388f65 100755 { u32 hv1, hv2, hv3; u32 hash; -@@ -420,12 +420,58 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, +@@ -431,12 +431,58 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, return 0; } @@ -280,10 +280,10 @@ index 94e03b2..8388f65 100755 mtk_flow_entry_match(struct mtk_flow_entry *entry, struct mtk_foe_entry *data) { diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h -index 86288b0..5ab864f 100644 +index bc48bd9..5529d64 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.h +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h -@@ -403,9 +403,13 @@ int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid); +@@ -429,9 +429,13 @@ int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid); int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid); int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, int bss, int wcid); @@ -298,7 +298,7 @@ index 86288b0..5ab864f 100644 #endif diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -index b80f72d..3bc50a4 100755 +index f9cd2f9..f0c63da 100755 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c @@ -9,6 +9,8 @@ @@ -329,7 +329,7 @@ index b80f72d..3bc50a4 100755 if (dev == eth->netdev[0]) pse_port = PSE_GDM1_PORT; else if (dev == eth->netdev[1]) -@@ -217,6 +222,23 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe, +@@ -219,6 +224,23 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe, return -EOPNOTSUPP; out: @@ -353,7 +353,7 @@ index b80f72d..3bc50a4 100755 mtk_foe_entry_set_pse_port(foe, pse_port); return 0; -@@ -447,7 +469,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f) +@@ -449,7 +471,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f) if (data.pppoe.num == 1) mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid); @@ -366,10 +366,10 @@ index b80f72d..3bc50a4 100755 return err; diff --git a/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c b/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c new file mode 100644 -index 0000000..d76b3c5 +index 0000000..c7af3eb --- /dev/null +++ b/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c -@@ -0,0 +1,439 @@ +@@ -0,0 +1,448 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2022 MediaTek Inc. @@ -390,12 +390,21 @@ index 0000000..d76b3c5 + u32 val; + + if (enable) { -+ val = MTK_QTX_SCH_MIN_RATE_EN | MTK_QTX_SCH_MAX_RATE_EN; -+ val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | -+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 25) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) | -+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 4); ++ if (id < MAX_PPPQ_PORT_NUM) { ++ val = MTK_QTX_SCH_MIN_RATE_EN | MTK_QTX_SCH_MAX_RATE_EN; ++ val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | ++ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 25) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 4); ++ } else { ++ val = MTK_QTX_SCH_MIN_RATE_EN; ++ val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | ++ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 3) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 0) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 0) | ++ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 4); ++ } + + writel(val, eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE)); + } else { @@ -428,7 +437,7 @@ index 0000000..d76b3c5 +{ + u32 id, val; + -+ for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) { ++ for (id = 0; id < 2 * MAX_PPPQ_PORT_NUM; id++) { + mtk_qdma_qos_shaper_ebl(eth, id, 1); + + writel(FIELD_PREP(MTK_QTX_CFG_HW_RESV_CNT_OFFSET, 4) | @@ -465,7 +474,7 @@ index 0000000..d76b3c5 + eth->qos_toggle = 1; + } else if (buf[0] == '2') { + pr_info("Per-port-per-queue mode is going to be enabled !\n"); -+ pr_info("PPPQ use qid 0~5 (scheduler 0).\n"); ++ pr_info("PPPQ use qid 0~11 (scheduler 0).\n"); + eth->qos_toggle = 2; + mtk_qdma_qos_pppq_enable(eth); + } diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch index c44e49433..b6c0d41bf 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch @@ -1,44 +1,31 @@ -From a326344938c515068241eb66580f57255258d9c6 Mon Sep 17 00:00:00 2001 +From aaac91720ca1fd7679896286eac2b014e7150fca Mon Sep 17 00:00:00 2001 From: Bo-Cun Chen -Date: Tue, 21 Nov 2023 16:42:01 +0800 +Date: Mon, 18 Mar 2024 16:35:07 +0800 Subject: [PATCH 15/24] ethernet-update-ppe-from-netsys2-to-netsys3 --- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 ++++--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +++- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 ++-- drivers/net/ethernet/mediatek/mtk_ppe.c | 35 ++++++++++++++--- drivers/net/ethernet/mediatek/mtk_ppe.h | 38 ++++++++++++++++--- .../net/ethernet/mediatek/mtk_ppe_offload.c | 6 ++- drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 7 ++++ - 6 files changed, 85 insertions(+), 22 deletions(-) + 6 files changed, 82 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 1660fd9..a3ed175 100644 +index 952bf51..f477ff3 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2447,17 +2447,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, +@@ -2447,7 +2447,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, skb_checksum_none_assert(skb); skb->protocol = eth_type_trans(skb, netdev); --#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) -- hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2; -+#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3) -+ hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2; - #else -- hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY; -+ hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY; - #endif - if (hash != MTK_RXD4_FOE_ENTRY) { - hash = jhash_1word(hash, 0); - skb_set_hash(skb, hash, PKT_HASH_TYPE_L4); - } - -#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) +#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3) + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2; reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5); - if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) { - mtk_ppe_check_skb(eth->ppe[0], skb, -@@ -5799,7 +5799,8 @@ static int mtk_probe(struct platform_device *pdev) + if (hash != MTK_RXD5_FOE_ENTRY_V2) { +@@ -5798,7 +5798,8 @@ static int mtk_probe(struct platform_device *pdev) for (i = 0; i < eth->ppe_num; i++) { eth->ppe[i] = mtk_ppe_init(eth, @@ -48,7 +35,7 @@ index 1660fd9..a3ed175 100644 2, eth->soc->hash_way, i, eth->soc->has_accounting); if (!eth->ppe[i]) { -@@ -6066,6 +6067,9 @@ static const struct mtk_soc_data mt7988_data = { +@@ -6065,6 +6066,9 @@ static const struct mtk_soc_data mt7988_data = { .required_clks = MT7988_CLKS_BITMAP, .required_pctl = false, .has_sram = true, @@ -59,7 +46,7 @@ index 1660fd9..a3ed175 100644 .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -index 02ca0b2..f9dda59 100644 +index 58547af..9c46ac1 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -137,9 +137,10 @@ @@ -74,7 +61,7 @@ index 02ca0b2..f9dda59 100644 #else #define MTK_GDMA_TO_PPE0 0x4444 #endif -@@ -2014,14 +2015,14 @@ extern u32 dbg_show_level; +@@ -2018,14 +2019,14 @@ extern u32 dbg_show_level; static inline void mtk_set_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe, u32 val) { diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch index ee8eb418a..3a5aa2557 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3019-mtk-wed-add-wed3-support.patch @@ -1,4 +1,4 @@ -From 01c157492967f2c2f969ccf8aefe93519cb662d6 Mon Sep 17 00:00:00 2001 +From b6e8f376899070b8109c3413b15e572f8f03dc06 Mon Sep 17 00:00:00 2001 From: Sujuan Chen Date: Mon, 18 Sep 2023 13:21:15 +0800 Subject: [PATCH] mtk:wed:add wed3 support @@ -392,7 +392,7 @@ index 95174b7..2d432f2 100644 return err; diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c -index 68eedd3..878f1bb 100644 +index a7d2166..ab561f7 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c @@ -23,9 +23,45 @@ @@ -614,7 +614,7 @@ index 68eedd3..878f1bb 100644 + } + + /* eagle E1 PCIE1 tx ring 22 flow control issue */ -+ if (dev->wlan.id == 0x7991) ++ if (dev->wlan.id == 0x7991 || dev->wlan.id == 0x7992) + wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING); + + wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN); @@ -1683,11 +1683,11 @@ index 68eedd3..878f1bb 100644 + MTK_WED_WDMA_RX_PREF_DDONE2_EN); + wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN); -+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, -+ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST); wed_set(dev, MTK_WED_WPDMA_GLO_CFG, - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | - MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); ++ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, + MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK | + MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK | + MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4); diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch index 0d0ac4ec0..d3747af3a 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch @@ -1,21 +1,21 @@ -From a0aa9757876b525b24a16bd3cb48b5dac02a8945 Mon Sep 17 00:00:00 2001 +From f83c601c7b525c0adedcf1f5e8041acd350c7e2d Mon Sep 17 00:00:00 2001 From: Sujuan Chen Date: Mon, 18 Sep 2023 13:23:56 +0800 -Subject: [PATCH 21/24] mtk: wed: add dma mask limitation and GFP_DMA32 for - board >= 4GB dram +Subject: [PATCH] mtk: wed: add dma mask limitation and GFP_DMA32 for board >= + 4GB dram --- - drivers/net/ethernet/mediatek/mtk_wed.c | 8 ++++++-- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 4 ++-- - drivers/net/ethernet/mediatek/mtk_wed_wo.c | 4 ++-- - drivers/net/ethernet/mediatek/mtk_wed_wo.h | 1 + - 4 files changed, 11 insertions(+), 6 deletions(-) + drivers/net/ethernet/mediatek/mtk_wed.c | 16 +++++++++++----- + drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 4 ++-- + drivers/net/ethernet/mediatek/mtk_wed_wo.c | 4 ++-- + drivers/net/ethernet/mediatek/mtk_wed_wo.h | 1 + + 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c -index 7f14d43..b928ff6 100644 +index 5eeb3ed..094bc94 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -638,7 +638,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) +@@ -625,7 +625,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) void *buf; int s; @@ -24,7 +24,34 @@ index 7f14d43..b928ff6 100644 if (!page) return -ENOMEM; -@@ -762,7 +762,7 @@ mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev) +@@ -646,10 +646,11 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + + for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) { + struct mtk_wdma_desc *desc = desc_ptr; ++ u32 ctrl; + + desc->buf0 = cpu_to_le32(buf_phys); + if (!mtk_wed_is_v3_or_greater(dev->hw)) { +- u32 txd_size, ctrl; ++ u32 txd_size; + + txd_size = dev->wlan.init_buf(buf, buf_phys, + token++); +@@ -663,11 +664,11 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG0 | + FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2, + MTK_WED_BUF_SIZE - txd_size); +- desc->ctrl = cpu_to_le32(ctrl); + desc->info = 0; + } else { +- desc->ctrl = cpu_to_le32(token << 16); ++ ctrl = token << 16 | TX_DMA_SDP1(buf_phys); + } ++ desc->ctrl = cpu_to_le32(ctrl); + + desc_ptr += desc_size; + buf += MTK_WED_BUF_SIZE; +@@ -749,7 +750,7 @@ mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev) void *buf; int s; @@ -33,7 +60,15 @@ index 7f14d43..b928ff6 100644 if (!page) return -ENOMEM; -@@ -2464,6 +2464,10 @@ mtk_wed_attach(struct mtk_wed_device *dev) +@@ -769,6 +770,7 @@ mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev) + buf_phys = page_phys; + for (s = 0; s < MTK_WED_RX_PAGE_BUF_PER_PAGE; s++) { + desc->buf0 = cpu_to_le32(buf_phys); ++ desc->token = cpu_to_le32(RX_DMA_SDP1(buf_phys)); + desc++; + buf += MTK_WED_PAGE_BUF_SIZE; + buf_phys += MTK_WED_PAGE_BUF_SIZE; +@@ -2457,6 +2459,10 @@ mtk_wed_attach(struct mtk_wed_device *dev) dev->version = hw->version; dev->hw->pci_base = mtk_wed_get_pci_base(dev); diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch index 15d51b95e..c96eaa8ef 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch @@ -1,21 +1,21 @@ -From d73ee12c93d4146b3585fc5d93271b1fbafcd3c4 Mon Sep 17 00:00:00 2001 +From e917fdd9042787edd43e4070c3480baf0dfb8d33 Mon Sep 17 00:00:00 2001 From: Bo-Cun Chen -Date: Tue, 26 Dec 2023 16:46:16 +0800 +Date: Mon, 18 Mar 2024 16:57:13 +0800 Subject: [PATCH 22/24] 999-3022-mediatek-ethernet-add-multiple-ppe-allocatiion.patch --- arch/arm64/boot/dts/mediatek/mt7988.dtsi | 1 + - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 19 +++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++++++++--- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +++ - .../net/ethernet/mediatek/mtk_ppe_offload.c | 10 ++++++++++ - 4 files changed, 31 insertions(+), 2 deletions(-) + .../net/ethernet/mediatek/mtk_ppe_offload.c | 10 +++++++++ + 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi -index 3368240..ff1619d 100644 +index 4a1a446..57b27f8 100644 --- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi -@@ -945,6 +945,7 @@ +@@ -942,6 +942,7 @@ mediatek,infracfg = <&topmisc>; mediatek,toprgu = <&watchdog>; mediatek,hwver = <&hwver>; @@ -24,7 +24,7 @@ index 3368240..ff1619d 100644 #address-cells = <1>; #size-cells = <0>; diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index a3ed175..a761d95 100644 +index 291afdc..c0f4ade 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -2349,6 +2349,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, @@ -35,17 +35,20 @@ index a3ed175..a761d95 100644 if (unlikely(!ring)) goto rx_done; -@@ -2460,7 +2461,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, - #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3) - reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5); - if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) { -- mtk_ppe_check_skb(eth->ppe[0], skb, -+ i = eth->mac[mac]->ppe_idx; -+ mtk_ppe_check_skb(eth->ppe[i], skb, - trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2); +@@ -2463,8 +2464,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, } - #else -@@ -4114,7 +4116,19 @@ static int mtk_open(struct net_device *dev) + #endif + +- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) +- mtk_ppe_check_skb(eth->ppe[0], skb, hash); ++ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) { ++ i = eth->mac[mac]->ppe_idx; ++ mtk_ppe_check_skb(eth->ppe[i], skb, hash); ++ } + + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) { +@@ -4113,7 +4116,19 @@ static int mtk_open(struct net_device *dev) SGMSYS_QPHY_PWR_STATE_CTRL, 0); if (eth->soc->offload_version) { @@ -66,7 +69,7 @@ index a3ed175..a761d95 100644 for (i = 0; i < eth->ppe_num; i++) mtk_ppe_start(eth->ppe[i]); -@@ -5130,6 +5144,7 @@ static const struct net_device_ops mtk_netdev_ops = { +@@ -5129,6 +5144,7 @@ static const struct net_device_ops mtk_netdev_ops = { .ndo_poll_controller = mtk_poll_controller, #endif .ndo_setup_tc = mtk_eth_setup_tc, @@ -75,10 +78,10 @@ index a3ed175..a761d95 100644 static void mux_poll(struct work_struct *work) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -index 88d2f46..711a8e9 100644 +index 8454361..d958aec 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1973,6 +1973,7 @@ struct mtk_mac { +@@ -1978,6 +1978,7 @@ struct mtk_mac { phy_interface_t interface; unsigned int mode; unsigned int type; @@ -86,7 +89,7 @@ index 88d2f46..711a8e9 100644 int speed; struct device_node *of_node; struct phylink *phylink; -@@ -2074,6 +2075,8 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, +@@ -2079,6 +2080,8 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data); int mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f, struct mtk_eth *eth); @@ -96,10 +99,10 @@ index 88d2f46..711a8e9 100644 u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index); diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -index 2d432f2..7f432be 100644 +index 402f1e3..3bfbec8 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -694,6 +694,16 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, +@@ -828,6 +828,16 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, } } diff --git a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch index 92591a5c2..d0ad23e77 100644 --- a/feeds/mediatek-sdk/mediatek/patches-5.4/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch +++ b/feeds/mediatek-sdk/mediatek/patches-5.4/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch @@ -9,22 +9,26 @@ Subject: [PATCH 23/24] 1 file changed, 27 insertions(+) diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c -index ae0acd5..84d9763 100644 +index ae0acd5..547b5a0 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -451,6 +451,28 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid) +@@ -451,6 +451,31 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid) return 0; } -+#if defined(CONFIG_MEDIATEK_NETSYS_V3) +void mtk_foe_entry_adjust_qid(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) +{ + struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(&entry->data); + u32 *ib2 = mtk_foe_entry_ib2(&entry->data); + u8 qid; + ++#if defined(CONFIG_MEDIATEK_NETSYS_V3) + if (l2->tport_id != 1) + return; ++#else ++ if (!(*ib2 & MTK_FOE_IB2_PSE_QOS)) ++ return; ++#endif + + qid = FIELD_GET(MTK_FOE_IB2_QID, *ib2); + /* To enhance performance in the unbalanced PHY rate test, @@ -36,23 +40,19 @@ index ae0acd5..84d9763 100644 + *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID, qid); + } +} -+#endif + int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp) { u32 *ib2 = mtk_foe_entry_ib2(entry); -@@ -790,6 +812,11 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) +@@ -790,6 +815,9 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) continue; } -+#if defined(CONFIG_MEDIATEK_NETSYS_V3) + if (skb && skb->len < 100) + mtk_foe_entry_adjust_qid(ppe, entry); -+#endif + entry->hash = hash; __mtk_foe_entry_commit(ppe, &entry->data, hash); found = true; -- 2.18.0 - diff --git a/feeds/mediatek-sdk/mt76/Makefile b/feeds/mediatek-sdk/mt76/Makefile index 369fb4b1b..24fdd5178 100644 --- a/feeds/mediatek-sdk/mt76/Makefile +++ b/feeds/mediatek-sdk/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2024-02-03 -PKG_SOURCE_VERSION:=6124ea9135ed512671933f5520c46842906c78bc -PKG_MIRROR_HASH:=acc326d7b15c9c72b494ed601300be329553f896e65c7f045e6a09327304c34a +PKG_SOURCE_DATE:=2024-04-03 +PKG_SOURCE_VERSION:=1e336a8582dce2ef32ddd440d423e9afef961e71 +PKG_MIRROR_HASH:=276613540603dc6ece9d2474ae1899b6aaa6ca93bd27824056c9689c725f5890 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 @@ -247,7 +247,7 @@ endef define KernelPackage/mt7981-firmware $(KernelPackage/mt76-default) -# DEPENDS:=+@TARGET_mediatek_mt7981 + DEPENDS:=+@TARGET_mediatek_mt7981 TITLE:=MediaTek MT7981 firmware endef @@ -616,8 +616,8 @@ define KernelPackage/mt7986-firmware/install $(PKG_BUILD_DIR)/firmware/mt7986_wm.bin \ $(PKG_BUILD_DIR)/firmware/mt7986_rom_patch_mt7975.bin \ $(PKG_BUILD_DIR)/firmware/mt7986_rom_patch.bin \ - $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7975_dual.bin \ - $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7976_dual.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7975_dual.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7976_dual.bin \ $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7975.bin \ $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7976.bin \ $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7976_dbdc.bin \ @@ -626,7 +626,7 @@ ifdef CONFIG_NET_MEDIATEK_SOC_WED cp \ $(PKG_BUILD_DIR)/firmware/mt7986_wo_0.bin \ $(PKG_BUILD_DIR)/firmware/mt7986_wo_1.bin \ - $(1)/lib/firmware/mediatek + $(1)/lib/firmware/mediatek endif endef @@ -644,9 +644,9 @@ define KernelPackage/mt7996e/install $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm_tm_233.bin \ $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_rom_patch_233.bin \ $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_2i5i6i.bin \ $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_233.bin \ $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_dual_404.bin \ - $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_tm.bin \ $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wa.bin \ $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm.bin \ $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm_tm.bin \ diff --git a/feeds/mediatek-sdk/mt76/Makefile.orig b/feeds/mediatek-sdk/mt76/mt76/Makefile similarity index 83% rename from feeds/mediatek-sdk/mt76/Makefile.orig rename to feeds/mediatek-sdk/mt76/mt76/Makefile index 4f0fb5f69..24fdd5178 100644 --- a/feeds/mediatek-sdk/mt76/Makefile.orig +++ b/feeds/mediatek-sdk/mt76/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2024-02-03 -PKG_SOURCE_VERSION:=6124ea9135ed512671933f5520c46842906c78bc -PKG_MIRROR_HASH:=acc326d7b15c9c72b494ed601300be329553f896e65c7f045e6a09327304c34a +PKG_SOURCE_DATE:=2024-04-03 +PKG_SOURCE_VERSION:=1e336a8582dce2ef32ddd440d423e9afef961e71 +PKG_MIRROR_HASH:=276613540603dc6ece9d2474ae1899b6aaa6ca93bd27824056c9689c725f5890 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 @@ -233,7 +233,7 @@ endef define KernelPackage/mt7915e $(KernelPackage/mt76-default) - TITLE:=MediaTek MT7915e wireless driver + TITLE:=MediaTek MT7915e/MT7986/MT7916 wireless driver DEPENDS+=@PCI_SUPPORT +kmod-mt76-connac +kmod-hwmon-core +kmod-thermal +@DRIVER_11AX_SUPPORT +@KERNEL_RELAY FILES:= $(PKG_BUILD_DIR)/mt7915/mt7915e.ko AUTOLOAD:=$(call AutoProbe,mt7915e) @@ -247,13 +247,13 @@ endef define KernelPackage/mt7981-firmware $(KernelPackage/mt76-default) - DEPENDS:=@TARGET_mediatek_filogic + DEPENDS:=+@TARGET_mediatek_mt7981 TITLE:=MediaTek MT7981 firmware endef define KernelPackage/mt7986-firmware $(KernelPackage/mt76-default) - DEPENDS:=@TARGET_mediatek_filogic + DEPENDS:=+@TARGET_mediatek_mt7986 TITLE:=MediaTek MT7986 firmware endef @@ -317,8 +317,8 @@ endef define KernelPackage/mt7996e $(KernelPackage/mt76-default) - TITLE:=MediaTek MT7996E wireless driver - DEPENDS+=@PCI_SUPPORT +kmod-mt76-connac +kmod-hwmon-core + TITLE:=MediaTek MT7996/MT7995/MT7919 wireless driver + DEPENDS+=@PCI_SUPPORT +kmod-mt76-core +kmod-mt76-connac +kmod-hwmon-core +kmod-thermal +@DRIVER_11AX_SUPPORT +@DRIVER_11BE_SUPPORT FILES:= $(PKG_BUILD_DIR)/mt7996/mt7996e.ko AUTOLOAD:=$(call AutoProbe,mt7996e) endef @@ -376,6 +376,11 @@ ifdef CONFIG_PACKAGE_MAC80211_MESH NOSTDINC_FLAGS += -DCONFIG_MAC80211_MESH endif +ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS + NOSTDINC_FLAGS += -DCONFIG_MAC80211_DEBUGFS + PKG_MAKE_FLAGS += CONFIG_MAC80211_DEBUGFS=y +endif + ifdef CONFIG_PACKAGE_CFG80211_TESTMODE NOSTDINC_FLAGS += -DCONFIG_NL80211_TESTMODE PKG_MAKE_FLAGS += CONFIG_NL80211_TESTMODE=y @@ -438,7 +443,11 @@ ifdef CONFIG_PACKAGE_kmod-mt7663u endif ifdef CONFIG_PACKAGE_kmod-mt7915e PKG_MAKE_FLAGS += CONFIG_MT7915E=m - ifdef CONFIG_TARGET_mediatek_filogic + ifdef CONFIG_TARGET_mediatek_mt7986 + PKG_MAKE_FLAGS += CONFIG_MT798X_WMAC=y + NOSTDINC_FLAGS += -DCONFIG_MT798X_WMAC + endif + ifdef CONFIG_TARGET_mediatek_mt7981 PKG_MAKE_FLAGS += CONFIG_MT798X_WMAC=y NOSTDINC_FLAGS += -DCONFIG_MT798X_WMAC endif @@ -475,7 +484,8 @@ ifdef CONFIG_PACKAGE_kmod-mt7925e endif define Build/Compile - +$(KERNEL_MAKE) $(PKG_JOBS) \ + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ $(PKG_MAKE_FLAGS) \ M="$(PKG_BUILD_DIR)" \ NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ @@ -568,6 +578,8 @@ define KernelPackage/mt7915-firmware/install $(PKG_BUILD_DIR)/firmware/mt7915_wa.bin \ $(PKG_BUILD_DIR)/firmware/mt7915_wm.bin \ $(PKG_BUILD_DIR)/firmware/mt7915_rom_patch.bin \ + $(PKG_BUILD_DIR)/firmware/mt7915_eeprom.bin \ + $(PKG_BUILD_DIR)/firmware/mt7915_eeprom_dbdc.bin \ $(1)/lib/firmware/mediatek endef @@ -577,6 +589,7 @@ define KernelPackage/mt7916-firmware/install $(PKG_BUILD_DIR)/firmware/mt7916_wa.bin \ $(PKG_BUILD_DIR)/firmware/mt7916_wm.bin \ $(PKG_BUILD_DIR)/firmware/mt7916_rom_patch.bin \ + $(PKG_BUILD_DIR)/firmware/mt7916_eeprom.bin \ $(1)/lib/firmware/mediatek endef @@ -586,7 +599,13 @@ define KernelPackage/mt7981-firmware/install $(PKG_BUILD_DIR)/firmware/mt7981_wa.bin \ $(PKG_BUILD_DIR)/firmware/mt7981_wm.bin \ $(PKG_BUILD_DIR)/firmware/mt7981_rom_patch.bin \ + $(PKG_BUILD_DIR)/firmware/mt7981_eeprom_mt7976_dbdc.bin \ $(1)/lib/firmware/mediatek +ifdef CONFIG_NET_MEDIATEK_SOC_WED + cp \ + $(PKG_BUILD_DIR)/firmware/mt7981_wo.bin \ + $(1)/lib/firmware/mediatek +endif endef define KernelPackage/mt7986-firmware/install @@ -597,9 +616,62 @@ define KernelPackage/mt7986-firmware/install $(PKG_BUILD_DIR)/firmware/mt7986_wm.bin \ $(PKG_BUILD_DIR)/firmware/mt7986_rom_patch_mt7975.bin \ $(PKG_BUILD_DIR)/firmware/mt7986_rom_patch.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7975_dual.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7976_dual.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7975.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7976.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7976_dbdc.bin \ $(1)/lib/firmware/mediatek +ifdef CONFIG_NET_MEDIATEK_SOC_WED + cp \ + $(PKG_BUILD_DIR)/firmware/mt7986_wo_0.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_wo_1.bin \ + $(1)/lib/firmware/mediatek +endif endef +ifdef CONFIG_PACKAGE_kmod-mt7996e +define KernelPackage/mt7996e/install + $(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7996 + cp \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wa.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm_tm.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_rom_patch.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_dsp.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wa_233.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm_233.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm_tm_233.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_rom_patch_233.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_2i5i6i.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_233.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_dual_404.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wa.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm_tm.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_rom_patch.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_dsp.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_2i5i.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_2i5e.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_2e5e.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wa_23.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm_23.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm_tm_23.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_rom_patch_23.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_dsp_23.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_23_2i5i.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_23_2e5e.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wa_24.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm_24.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm_tm_24.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_rom_patch_24.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_dsp_24.bin \ + $(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_24_2i5i.bin \ + $(1)/lib/firmware/mediatek/mt7996 +endef +endif + define KernelPackage/mt7921-firmware/install $(INSTALL_DIR) $(1)/lib/firmware/mediatek cp \ diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0001-wifi-mt76-fix-incorrect-HE-TX-GI-report.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0001-wifi-mt76-fix-incorrect-HE-TX-GI-report.patch new file mode 100644 index 000000000..1c9624e72 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0001-wifi-mt76-fix-incorrect-HE-TX-GI-report.patch @@ -0,0 +1,501 @@ +From e9f5961a07a895d18b6158a94d74633c07eab50f Mon Sep 17 00:00:00 2001 +From: Evelyn Tsai +Date: Thu, 18 May 2023 18:11:37 +0800 +Subject: [PATCH 01/14] wifi: mt76: fix incorrect HE TX GI report + +Change GI reporting source from static capability to rate-tuning module. + +Signed-off-by: Benjamin Lin +--- + mt76.h | 4 ++ + mt7915/init.c | 4 ++ + mt7915/mac.c | 64 ++++++++++++------- + mt7915/main.c | 7 +++ + mt7915/mcu.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/mcu.h | 58 +++++++++++++++++ + mt7915/mt7915.h | 6 ++ + 7 files changed, 282 insertions(+), 22 deletions(-) + +diff --git a/mt76.h b/mt76.h +index 2cbea73..92acba9 100644 +--- a/mt76.h ++++ b/mt76.h +@@ -282,12 +282,16 @@ struct mt76_queue_ops { + void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q); + }; + ++#define MT_PHY_TYPE_LEGACY GENMASK(2, 0) ++#define MT_PHY_TYPE_EXT GENMASK(7, 3) ++ + enum mt76_phy_type { + MT_PHY_TYPE_CCK, + MT_PHY_TYPE_OFDM, + MT_PHY_TYPE_HT, + MT_PHY_TYPE_HT_GF, + MT_PHY_TYPE_VHT, ++ MT_PHY_TYPE_HE_REMAP, + MT_PHY_TYPE_HE_SU = 8, + MT_PHY_TYPE_HE_EXT_SU, + MT_PHY_TYPE_HE_TB, +diff --git a/mt7915/init.c b/mt7915/init.c +index eee1879..edf83c4 100644 +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -673,6 +673,8 @@ mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy) + struct mt76_phy *mphy = phy->mt76; + int ret; + ++ INIT_LIST_HEAD(&phy->stats_list); ++ spin_lock_init(&phy->stats_lock); + INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work); + + mt7915_eeprom_parse_hw_cap(dev, phy); +@@ -1206,6 +1208,8 @@ int mt7915_register_device(struct mt7915_dev *dev) + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; ++ INIT_LIST_HEAD(&dev->phy.stats_list); ++ spin_lock_init(&dev->phy.stats_lock); + INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work); + INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work); + INIT_LIST_HEAD(&dev->sta_rc_list); +diff --git a/mt7915/mac.c b/mt7915/mac.c +index 8008ce3..b915201 100644 +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -180,15 +180,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) + rx_cur); + } + +- /* +- * We don't support reading GI info from txs packets. +- * For accurate tx status reporting and AQL improvement, +- * we need to make sure that flags match so polling GI +- * from per-sta counters directly. +- */ + rate = &msta->wcid.rate; +- addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 7); +- val = mt76_rr(dev, addr); + + switch (rate->bw) { + case RATE_INFO_BW_160: +@@ -205,18 +197,6 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) + break; + } + +- if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { +- u8 offs = 24 + 2 * bw; +- +- rate->he_gi = (val & (0x3 << offs)) >> offs; +- } else if (rate->flags & +- (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) { +- if (val & BIT(12 + bw)) +- rate->flags |= RATE_INFO_FLAGS_SHORT_GI; +- else +- rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI; +- } +- + /* get signal strength of resp frames (CTS/BA/ACK) */ + addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 30); + val = mt76_rr(dev, addr); +@@ -918,6 +898,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) + info = le32_to_cpu(*cur_info); + if (info & MT_TX_FREE_PAIR) { + struct mt7915_sta *msta; ++ struct mt7915_phy *phy; + u16 idx; + + idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); +@@ -927,11 +908,18 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) + continue; + + msta = container_of(wcid, struct mt7915_sta, wcid); +- spin_lock_bh(&mdev->sta_poll_lock); ++ phy = msta->vif->phy; ++ spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &mdev->sta_poll_list); +- spin_unlock_bh(&mdev->sta_poll_lock); ++ spin_unlock_bh(&dev->mt76.sta_poll_lock); ++ ++ spin_lock_bh(&phy->stats_lock); ++ if (list_empty(&msta->stats_list)) ++ list_add_tail(&msta->stats_list, &phy->stats_list); ++ spin_unlock_bh(&phy->stats_lock); ++ + continue; + } + +@@ -1010,6 +998,7 @@ mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len) + static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) + { + struct mt7915_sta *msta = NULL; ++ struct mt7915_phy *phy; + struct mt76_wcid *wcid; + __le32 *txs_data = data; + u16 wcidx; +@@ -1045,6 +1034,11 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + ++ phy = msta->vif->phy; ++ spin_lock_bh(&phy->stats_lock); ++ if (list_empty(&msta->stats_list)) ++ list_add_tail(&msta->stats_list, &phy->stats_list); ++ spin_unlock_bh(&phy->stats_lock); + out: + rcu_read_unlock(); + } +@@ -1952,6 +1946,27 @@ static void mt7915_mac_severe_check(struct mt7915_phy *phy) + phy->trb_ts = trb; + } + ++static void mt7915_mac_sta_stats_work(struct mt7915_phy *phy) ++{ ++ struct mt7915_sta *sta; ++ LIST_HEAD(list); ++ ++ spin_lock_bh(&phy->stats_lock); ++ list_splice_init(&phy->stats_list, &list); ++ ++ while (!list_empty(&list)) { ++ sta = list_first_entry(&list, struct mt7915_sta, stats_list); ++ list_del_init(&sta->stats_list); ++ spin_unlock_bh(&phy->stats_lock); ++ ++ mt7915_mcu_get_tx_rate(phy, sta->wcid.idx); ++ ++ spin_lock_bh(&phy->stats_lock); ++ } ++ ++ spin_unlock_bh(&phy->stats_lock); ++} ++ + void mt7915_mac_sta_rc_work(struct work_struct *work) + { + struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work); +@@ -2010,6 +2025,11 @@ void mt7915_mac_work(struct work_struct *work) + mt7915_mcu_muru_debug_get(phy); + } + ++ if (++phy->stats_work_count == 10) { ++ phy->stats_work_count = 0; ++ mt7915_mac_sta_stats_work(phy); ++ } ++ + mutex_unlock(&mphy->dev->mutex); + + mt76_tx_status_check(mphy->dev, false); +diff --git a/mt7915/main.c b/mt7915/main.c +index b16a633..e61041d 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -752,6 +752,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + + INIT_LIST_HEAD(&msta->rc_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); ++ INIT_LIST_HEAD(&msta->stats_list); + msta->vif = mvif; + msta->wcid.sta = 1; + msta->wcid.idx = idx; +@@ -779,6 +780,7 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + { + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; ++ struct mt7915_phy *phy = msta->vif->phy; + int i; + + mt7915_mcu_add_sta(dev, vif, sta, false); +@@ -795,6 +797,11 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + if (!list_empty(&msta->rc_list)) + list_del_init(&msta->rc_list); + spin_unlock_bh(&mdev->sta_poll_lock); ++ ++ spin_lock_bh(&phy->stats_lock); ++ if (!list_empty(&msta->stats_list)) ++ list_del_init(&msta->stats_list); ++ spin_unlock_bh(&phy->stats_lock); + } + + static void mt7915_tx(struct ieee80211_hw *hw, +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index fe54a2f..7df2162 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -3793,6 +3793,167 @@ out: + return ret; + } + ++static int ++mt7915_mcu_parse_tx_gi(struct mt76_dev *dev, u8 mode, u8 gi, u8 bw, ++ struct rate_info *rate) ++{ ++ /* Legacy drivers only use 3 bits for PHY mode. For backward ++ * compatibility, HE and newer PHY mode indices are remapped ++ * to the extended bits. ++ */ ++ if (u8_get_bits(mode, MT_PHY_TYPE_LEGACY) == MT_PHY_TYPE_HE_REMAP) ++ mode = u8_get_bits(mode, MT_PHY_TYPE_EXT); ++ ++ switch (mode) { ++ case MT_PHY_TYPE_CCK: ++ case MT_PHY_TYPE_OFDM: ++ break; ++ case MT_PHY_TYPE_HT: ++ case MT_PHY_TYPE_HT_GF: ++ case MT_PHY_TYPE_VHT: ++ if (gi) ++ rate->flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case MT_PHY_TYPE_HE_SU: ++ case MT_PHY_TYPE_HE_EXT_SU: ++ case MT_PHY_TYPE_HE_TB: ++ case MT_PHY_TYPE_HE_MU: ++ if (!is_mt7915(dev)) { ++ switch (bw) { ++ case MCU_PHY_BW_20: ++ gi = u8_get_bits(gi, HE_GI_BW_20); ++ break; ++ case MCU_PHY_BW_40: ++ gi = u8_get_bits(gi, HE_GI_BW_40); ++ break; ++ case MCU_PHY_BW_80: ++ gi = u8_get_bits(gi, HE_GI_BW_80); ++ break; ++ case MCU_PHY_BW_160: ++ gi = u8_get_bits(gi, HE_GI_BW_160); ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ if (gi > NL80211_RATE_INFO_HE_GI_3_2) ++ return -EINVAL; ++ ++ rate->he_gi = gi; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++int mt7915_mcu_get_tx_rate_v1(struct mt7915_phy *phy, u16 wcidx) ++{ ++ struct mt7915_mcu_ra_info_v1 *rate; ++ struct mt7915_dev *dev = phy->dev; ++ struct mt76_phy *mphy = phy->mt76; ++ struct mt76_wcid *wcid; ++ struct sk_buff *skb; ++ int ret; ++ ++ struct { ++ __le32 category; ++ u8 wcidx_lo; ++ u8 band; ++ u8 wcidx_hi; ++ u8 rsv[5]; ++ } req = { ++ .category = cpu_to_le32(MCU_GET_TX_RATE), ++ .wcidx_lo = to_wcid_lo(wcidx), ++ .band = mphy->band_idx, ++ .wcidx_hi = to_wcid_hi(wcidx) ++ }; ++ ++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(GET_TX_STAT), ++ &req, sizeof(req), true, &skb); ++ if (ret) ++ return ret; ++ ++ rate = (struct mt7915_mcu_ra_info_v1 *)skb->data; ++ if ((rate->wcidx_hi << 8 | rate->wcidx_lo) != wcidx) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ rcu_read_lock(); ++ wcid = rcu_dereference(dev->mt76.wcid[wcidx]); ++ if (!wcid) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ ret = mt7915_mcu_parse_tx_gi(mphy->dev, rate->mode, rate->gi, ++ rate->bw, &wcid->rate); ++unlock: ++ rcu_read_unlock(); ++out: ++ dev_kfree_skb(skb); ++ ++ return ret; ++} ++ ++int mt7915_mcu_get_tx_rate_v2(struct mt7915_phy *phy, u16 wcidx) ++{ ++ struct mt7915_mcu_ra_info_v2 *rate; ++ struct mt7915_dev *dev = phy->dev; ++ struct mt76_phy *mphy = phy->mt76; ++ struct mt76_wcid *wcid; ++ struct sk_buff *skb; ++ int ret; ++ ++ struct { ++ u8 category; ++ u8 band; ++ __le16 wcidx; ++ } req = { ++ .category = MCU_GET_TX_RATE, ++ .band = mphy->band_idx, ++ .wcidx = cpu_to_le16(wcidx) ++ }; ++ ++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(GET_TX_STAT), ++ &req, sizeof(req), true, &skb); ++ if (ret) ++ return ret; ++ ++ rate = (struct mt7915_mcu_ra_info_v2 *)skb->data; ++ if (le16_to_cpu(rate->wcidx) != wcidx) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ rcu_read_lock(); ++ wcid = rcu_dereference(dev->mt76.wcid[wcidx]); ++ if (!wcid) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ ret = mt7915_mcu_parse_tx_gi(mphy->dev, rate->mode, rate->gi, ++ rate->bw, &wcid->rate); ++unlock: ++ rcu_read_unlock(); ++out: ++ dev_kfree_skb(skb); ++ ++ return ret; ++} ++ ++int mt7915_mcu_get_tx_rate(struct mt7915_phy *phy, u16 wcidx) ++{ ++ if (is_mt7915(&phy->dev->mt76)) ++ return mt7915_mcu_get_tx_rate_v1(phy, wcidx); ++ else ++ return mt7915_mcu_get_tx_rate_v2(phy, wcidx); ++} ++ + int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct cfg80211_he_bss_color *he_bss_color) + { +diff --git a/mt7915/mcu.h b/mt7915/mcu.h +index b41ac4a..8f36546 100644 +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -152,6 +152,61 @@ struct mt7915_mcu_eeprom_info { + u8 data[16]; + } __packed; + ++enum { ++ MCU_PHY_BW_20 = 0, ++ MCU_PHY_BW_40, ++ MCU_PHY_BW_80, ++ MCU_PHY_BW_160, ++ MCU_PHY_BW_10, ++ MCU_PHY_BW_5, ++ MCU_PHY_BW_8080, ++ MCU_PHY_BW_320, ++ MCU_PHY_BW_NUM ++}; ++ ++#define HE_GI_BW_20 GENMASK(1, 0) ++#define HE_GI_BW_40 GENMASK(3, 2) ++#define HE_GI_BW_80 GENMASK(5, 4) ++#define HE_GI_BW_160 GENMASK(7, 6) ++ ++struct mt7915_mcu_ra_info_v1 { ++ u8 wcidx_lo; ++ u8 band; ++ u8 wcidx_hi; ++ u8 rsv1[46]; ++ ++ u8 mode; ++ u8 flags; ++ u8 stbc; ++ u8 gi; ++ u8 bw; ++ u8 ldpc; ++ u8 mcs; ++ u8 nss; ++ u8 ltf; ++ ++ u8 rsv2[8]; ++}; ++ ++struct mt7915_mcu_ra_info_v2 { ++ u8 category; ++ u8 rsv1; ++ __le16 num; ++ __le16 wcidx; ++ ++ u8 mode; ++ u8 flags; ++ u8 stbc; ++ u8 gi; ++ u8 bw; ++ u8 ldpc; ++ u8 mcs; ++ u8 nss; ++ u8 ltf; ++ ++ u8 rsv2; ++}; ++ + struct mt7915_mcu_phy_rx_info { + u8 category; + u8 rate; +@@ -527,4 +582,7 @@ mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower) + return txpower; + } + ++enum { ++ MCU_GET_TX_RATE = 4 ++}; + #endif +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index a30d08e..aee30c7 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -137,6 +137,7 @@ struct mt7915_sta { + struct mt7915_vif *vif; + + struct list_head rc_list; ++ struct list_head stats_list; + u32 airtime_ac[8]; + + int ack_signal; +@@ -224,6 +225,10 @@ struct mt7915_phy { + struct mt76_mib_stats mib; + struct mt76_channel_state state_ts; + ++ u8 stats_work_count; ++ struct list_head stats_list; ++ spinlock_t stats_lock; ++ + #ifdef CONFIG_NL80211_TESTMODE + struct { + u32 *reg_backup; +@@ -499,6 +504,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch); + int mt7915_mcu_get_temperature(struct mt7915_phy *phy); + int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state); + int mt7915_mcu_set_thermal_protect(struct mt7915_phy *phy); ++int mt7915_mcu_get_tx_rate(struct mt7915_phy *phy, u16 wcidx); + int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct rate_info *rate); + int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0002-wifi-mt76-mt7915-add-pc-stack-dump-for-WM-s-coredump.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0002-wifi-mt76-mt7915-add-pc-stack-dump-for-WM-s-coredump.patch new file mode 100644 index 000000000..651281ca2 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0002-wifi-mt76-mt7915-add-pc-stack-dump-for-WM-s-coredump.patch @@ -0,0 +1,641 @@ +From c7b5350668962272203b878cfc1ae2754c807d56 Mon Sep 17 00:00:00 2001 +From: Bo Jiao +Date: Mon, 22 May 2023 13:49:37 +0800 +Subject: [PATCH 02/14] wifi: mt76: mt7915: add pc stack dump for WM's + coredump. + +Signed-off-by: Bo Jiao +--- + mt76.h | 11 +++ + mt76_connac_mcu.c | 9 +++ + mt7915/coredump.c | 169 +++++++++++++++++++++++++++++++--------------- + mt7915/coredump.h | 34 +++++++--- + mt7915/mac.c | 33 ++++++--- + mt7915/mt7915.h | 2 +- + mt7915/regs.h | 20 ++++++ + 7 files changed, 207 insertions(+), 71 deletions(-) + +diff --git a/mt76.h b/mt76.h +index 92acba9..ee14425 100644 +--- a/mt76.h ++++ b/mt76.h +@@ -32,6 +32,8 @@ + + #define MT76_TOKEN_FREE_THR 64 + ++#define MT76_BUILD_TIME_LEN 24 ++ + #define MT_QFLAG_WED_RING GENMASK(1, 0) + #define MT_QFLAG_WED_TYPE GENMASK(4, 2) + #define MT_QFLAG_WED BIT(5) +@@ -66,6 +68,12 @@ enum mt76_bus_type { + MT76_BUS_SDIO, + }; + ++enum mt76_ram_type { ++ MT76_RAM_TYPE_WM, ++ MT76_RAM_TYPE_WA, ++ __MT76_RAM_TYPE_MAX, ++}; ++ + enum mt76_wed_type { + MT76_WED_Q_TX, + MT76_WED_Q_TXFREE, +@@ -838,6 +846,9 @@ struct mt76_dev { + struct device *dma_dev; + + struct mt76_mcu mcu; ++ struct mt76_connac2_patch_hdr *patch_hdr; ++ struct mt76_connac2_fw_trailer *wm_hdr; ++ struct mt76_connac2_fw_trailer *wa_hdr; + + struct net_device napi_dev; + struct net_device tx_napi_dev; +diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c +index b35acf8..1ea9798 100644 +--- a/mt76_connac_mcu.c ++++ b/mt76_connac_mcu.c +@@ -2941,6 +2941,9 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm, + goto out; + } + ++ dev->wm_hdr = devm_kzalloc(dev->dev, sizeof(*hdr), GFP_KERNEL); ++ memcpy(dev->wm_hdr, hdr, sizeof(*hdr)); ++ + snprintf(dev->hw->wiphy->fw_version, + sizeof(dev->hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); +@@ -2970,6 +2973,9 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm, + goto out; + } + ++ dev->wa_hdr = devm_kzalloc(dev->dev, sizeof(*hdr), GFP_KERNEL); ++ memcpy(dev->wa_hdr, hdr, sizeof(*hdr)); ++ + snprintf(dev->hw->wiphy->fw_version, + sizeof(dev->hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); +@@ -3040,6 +3046,9 @@ int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name) + dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n", + be32_to_cpu(hdr->hw_sw_ver), hdr->build_date); + ++ dev->patch_hdr = devm_kzalloc(dev->dev, sizeof(*hdr), GFP_KERNEL); ++ memcpy(dev->patch_hdr, hdr, sizeof(*hdr)); ++ + for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) { + struct mt76_connac2_patch_sec *sec; + u32 len, addr, mode; +diff --git a/mt7915/coredump.c b/mt7915/coredump.c +index 5daf225..298c1ca 100644 +--- a/mt7915/coredump.c ++++ b/mt7915/coredump.c +@@ -7,7 +7,7 @@ + #include + #include "coredump.h" + +-static bool coredump_memdump; ++static bool coredump_memdump = true; + module_param(coredump_memdump, bool, 0644); + MODULE_PARM_DESC(coredump_memdump, "Optional ability to dump firmware memory"); + +@@ -86,8 +86,11 @@ static const struct mt7915_mem_region mt798x_mem_regions[] = { + }; + + const struct mt7915_mem_region* +-mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num) ++mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u8 type, u32 *num) + { ++ if (type == MT76_RAM_TYPE_WA) ++ return NULL; ++ + switch (mt76_chip(&dev->mt76)) { + case 0x7915: + *num = ARRAY_SIZE(mt7915_mem_regions); +@@ -104,14 +107,14 @@ mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num) + } + } + +-static int mt7915_coredump_get_mem_size(struct mt7915_dev *dev) ++static int mt7915_coredump_get_mem_size(struct mt7915_dev *dev, u8 type) + { + const struct mt7915_mem_region *mem_region; + size_t size = 0; + u32 num; + int i; + +- mem_region = mt7915_coredump_get_mem_layout(dev, &num); ++ mem_region = mt7915_coredump_get_mem_layout(dev, type, &num); + if (!mem_region) + return 0; + +@@ -128,9 +131,9 @@ static int mt7915_coredump_get_mem_size(struct mt7915_dev *dev) + return size; + } + +-struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev) ++struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev, u8 type) + { +- struct mt7915_crash_data *crash_data = dev->coredump.crash_data; ++ struct mt7915_crash_data *crash_data = dev->coredump.crash_data[type]; + + lockdep_assert_held(&dev->dump_mutex); + +@@ -141,12 +144,15 @@ struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev) + } + + static void +-mt7915_coredump_fw_state(struct mt7915_dev *dev, struct mt7915_coredump *dump, ++mt7915_coredump_fw_state(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump, + bool *exception) + { +- u32 state, count, type; ++ u32 state, count, category; ++ ++ if (type == MT76_RAM_TYPE_WA) ++ return; + +- type = (u32)mt76_get_field(dev, MT_FW_EXCEPT_TYPE, GENMASK(7, 0)); ++ category = (u32)mt76_get_field(dev, MT_FW_EXCEPT_TYPE, GENMASK(7, 0)); + state = (u32)mt76_get_field(dev, MT_FW_ASSERT_STAT, GENMASK(7, 0)); + count = is_mt7915(&dev->mt76) ? + (u32)mt76_get_field(dev, MT_FW_EXCEPT_COUNT, GENMASK(15, 8)) : +@@ -155,7 +161,7 @@ mt7915_coredump_fw_state(struct mt7915_dev *dev, struct mt7915_coredump *dump, + /* normal mode: driver can manually trigger assert for detail info */ + if (!count) + strscpy(dump->fw_state, "normal", sizeof(dump->fw_state)); +- else if (state > 1 && (count == 1) && type == 5) ++ else if (state > 1 && (count == 1) && category == 5) + strscpy(dump->fw_state, "assert", sizeof(dump->fw_state)); + else if ((state > 1 && count == 1) || count > 1) + strscpy(dump->fw_state, "exception", sizeof(dump->fw_state)); +@@ -164,11 +170,14 @@ mt7915_coredump_fw_state(struct mt7915_dev *dev, struct mt7915_coredump *dump, + } + + static void +-mt7915_coredump_fw_trace(struct mt7915_dev *dev, struct mt7915_coredump *dump, ++mt7915_coredump_fw_trace(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump, + bool exception) + { + u32 n, irq, sch, base = MT_FW_EINT_INFO; + ++ if (type == MT76_RAM_TYPE_WA) ++ return; ++ + /* trap or run? */ + dump->last_msg_id = mt76_rr(dev, MT_FW_LAST_MSG_ID); + +@@ -221,31 +230,61 @@ mt7915_coredump_fw_trace(struct mt7915_dev *dev, struct mt7915_coredump *dump, + } + + static void +-mt7915_coredump_fw_stack(struct mt7915_dev *dev, struct mt7915_coredump *dump, ++mt7915_coredump_fw_stack(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump, + bool exception) + { +- u32 oldest, i, idx; ++ u32 reg, i; ++ ++ if (type == MT76_RAM_TYPE_WA) ++ return; ++ ++ /* read current PC */ ++ mt76_rmw_field(dev, MT_CONN_DBG_CTL_LOG_SEL, ++ MT_CONN_DBG_CTL_PC_LOG_SEL, 0x22); ++ for (i = 0; i < 10; i++) { ++ dump->pc_cur[i] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG); ++ usleep_range(100, 500); ++ } + + /* stop call stack record */ +- if (!exception) +- mt76_clear(dev, 0x89050200, BIT(0)); ++ if (!exception) { ++ mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0)); ++ mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0)); ++ } + +- oldest = (u32)mt76_get_field(dev, 0x89050200, GENMASK(20, 16)) + 2; +- for (i = 0; i < 16; i++) { +- idx = ((oldest + 2 * i + 1) % 32); +- dump->call_stack[i] = mt76_rr(dev, 0x89050204 + idx * 4); ++ /* read PC log */ ++ dump->pc_dbg_ctrl = mt76_rr(dev, MT_MCU_WM_EXCP_PC_CTRL); ++ dump->pc_cur_idx = FIELD_GET(MT_MCU_WM_EXCP_PC_CTRL_IDX_STATUS, ++ dump->pc_dbg_ctrl); ++ for (i = 0; i < 32; i++) { ++ reg = MT_MCU_WM_EXCP_PC_LOG + i * 4; ++ dump->pc_stack[i] = mt76_rr(dev, reg); ++ } ++ ++ /* read LR log */ ++ dump->lr_dbg_ctrl = mt76_rr(dev, MT_MCU_WM_EXCP_LR_CTRL); ++ dump->lr_cur_idx = FIELD_GET(MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS, ++ dump->lr_dbg_ctrl); ++ for (i = 0; i < 32; i++) { ++ reg = MT_MCU_WM_EXCP_LR_LOG + i * 4; ++ dump->lr_stack[i] = mt76_rr(dev, reg); + } + + /* start call stack record */ +- if (!exception) +- mt76_set(dev, 0x89050200, BIT(0)); ++ if (!exception) { ++ mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0)); ++ mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0)); ++ } + } + + static void +-mt7915_coredump_fw_task(struct mt7915_dev *dev, struct mt7915_coredump *dump) ++mt7915_coredump_fw_task(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump) + { + u32 offs = is_mt7915(&dev->mt76) ? 0xe0 : 0x170; + ++ if (type == MT76_RAM_TYPE_WA) ++ return; ++ + strscpy(dump->task_qid, "(task queue id) read, write", + sizeof(dump->task_qid)); + +@@ -266,10 +305,13 @@ mt7915_coredump_fw_task(struct mt7915_dev *dev, struct mt7915_coredump *dump) + } + + static void +-mt7915_coredump_fw_context(struct mt7915_dev *dev, struct mt7915_coredump *dump) ++mt7915_coredump_fw_context(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump) + { + u32 count, idx, id; + ++ if (type == MT76_RAM_TYPE_WA) ++ return; ++ + count = mt76_rr(dev, MT_FW_CIRQ_COUNT); + + /* current context */ +@@ -299,9 +341,10 @@ mt7915_coredump_fw_context(struct mt7915_dev *dev, struct mt7915_coredump *dump) + } + } + +-static struct mt7915_coredump *mt7915_coredump_build(struct mt7915_dev *dev) ++static struct mt7915_coredump *mt7915_coredump_build(struct mt7915_dev *dev, u8 type) + { +- struct mt7915_crash_data *crash_data = dev->coredump.crash_data; ++ struct mt76_dev *mdev = &dev->mt76; ++ struct mt7915_crash_data *crash_data = dev->coredump.crash_data[type]; + struct mt7915_coredump *dump; + struct mt7915_coredump_mem *dump_mem; + size_t len, sofar = 0, hdr_len = sizeof(*dump); +@@ -326,23 +369,34 @@ static struct mt7915_coredump *mt7915_coredump_build(struct mt7915_dev *dev) + + dump = (struct mt7915_coredump *)(buf); + dump->len = len; ++ dump->hdr_len = hdr_len; + + /* plain text */ + strscpy(dump->magic, "mt76-crash-dump", sizeof(dump->magic)); + strscpy(dump->kernel, init_utsname()->release, sizeof(dump->kernel)); +- strscpy(dump->fw_ver, dev->mt76.hw->wiphy->fw_version, ++ strscpy(dump->fw_ver, mdev->hw->wiphy->fw_version, + sizeof(dump->fw_ver)); ++ strscpy(dump->fw_type, ((type == MT76_RAM_TYPE_WA) ? "WA" : "WM"), ++ sizeof(dump->fw_type)); ++ strscpy(dump->fw_patch_date, mdev->patch_hdr->build_date, ++ sizeof(dump->fw_patch_date)); ++ strscpy(dump->fw_ram_date[MT76_RAM_TYPE_WM], ++ mdev->wm_hdr->build_date, ++ sizeof(mdev->wm_hdr->build_date)); ++ strscpy(dump->fw_ram_date[MT76_RAM_TYPE_WA], ++ mdev->wa_hdr->build_date, ++ sizeof(mdev->wa_hdr->build_date)); + + guid_copy(&dump->guid, &crash_data->guid); + dump->tv_sec = crash_data->timestamp.tv_sec; + dump->tv_nsec = crash_data->timestamp.tv_nsec; + dump->device_id = mt76_chip(&dev->mt76); + +- mt7915_coredump_fw_state(dev, dump, &exception); +- mt7915_coredump_fw_trace(dev, dump, exception); +- mt7915_coredump_fw_task(dev, dump); +- mt7915_coredump_fw_context(dev, dump); +- mt7915_coredump_fw_stack(dev, dump, exception); ++ mt7915_coredump_fw_state(dev, type, dump, &exception); ++ mt7915_coredump_fw_trace(dev, type, dump, exception); ++ mt7915_coredump_fw_task(dev, type, dump); ++ mt7915_coredump_fw_context(dev, type, dump); ++ mt7915_coredump_fw_stack(dev, type, dump, exception); + + /* gather memory content */ + dump_mem = (struct mt7915_coredump_mem *)(buf + sofar); +@@ -356,17 +410,19 @@ static struct mt7915_coredump *mt7915_coredump_build(struct mt7915_dev *dev) + return dump; + } + +-int mt7915_coredump_submit(struct mt7915_dev *dev) ++int mt7915_coredump_submit(struct mt7915_dev *dev, u8 type) + { + struct mt7915_coredump *dump; + +- dump = mt7915_coredump_build(dev); ++ dump = mt7915_coredump_build(dev, type); + if (!dump) { + dev_warn(dev->mt76.dev, "no crash dump data found\n"); + return -ENODATA; + } + + dev_coredumpv(dev->mt76.dev, dump, dump->len, GFP_KERNEL); ++ dev_info(dev->mt76.dev, "%s coredump completed\n", ++ wiphy_name(dev->mt76.hw->wiphy)); + + return 0; + } +@@ -374,23 +430,26 @@ int mt7915_coredump_submit(struct mt7915_dev *dev) + int mt7915_coredump_register(struct mt7915_dev *dev) + { + struct mt7915_crash_data *crash_data; ++ int i; + +- crash_data = vzalloc(sizeof(*dev->coredump.crash_data)); +- if (!crash_data) +- return -ENOMEM; ++ for (i = 0; i < __MT76_RAM_TYPE_MAX; i++) { ++ crash_data = vzalloc(sizeof(*dev->coredump.crash_data[i])); ++ if (!crash_data) ++ return -ENOMEM; + +- dev->coredump.crash_data = crash_data; ++ dev->coredump.crash_data[i] = crash_data; + +- if (coredump_memdump) { +- crash_data->memdump_buf_len = mt7915_coredump_get_mem_size(dev); +- if (!crash_data->memdump_buf_len) +- /* no memory content */ +- return 0; ++ if (coredump_memdump) { ++ crash_data->memdump_buf_len = mt7915_coredump_get_mem_size(dev, i); ++ if (!crash_data->memdump_buf_len) ++ /* no memory content */ ++ return 0; + +- crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len); +- if (!crash_data->memdump_buf) { +- vfree(crash_data); +- return -ENOMEM; ++ crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len); ++ if (!crash_data->memdump_buf) { ++ vfree(crash_data); ++ return -ENOMEM; ++ } + } + } + +@@ -399,13 +458,17 @@ int mt7915_coredump_register(struct mt7915_dev *dev) + + void mt7915_coredump_unregister(struct mt7915_dev *dev) + { +- if (dev->coredump.crash_data->memdump_buf) { +- vfree(dev->coredump.crash_data->memdump_buf); +- dev->coredump.crash_data->memdump_buf = NULL; +- dev->coredump.crash_data->memdump_buf_len = 0; +- } ++ int i; + +- vfree(dev->coredump.crash_data); +- dev->coredump.crash_data = NULL; ++ for (i = 0; i < __MT76_RAM_TYPE_MAX; i++) { ++ if (dev->coredump.crash_data[i]->memdump_buf) { ++ vfree(dev->coredump.crash_data[i]->memdump_buf); ++ dev->coredump.crash_data[i]->memdump_buf = NULL; ++ dev->coredump.crash_data[i]->memdump_buf_len = 0; ++ } ++ ++ vfree(dev->coredump.crash_data[i]); ++ dev->coredump.crash_data[i] = NULL; ++ } + } + +diff --git a/mt7915/coredump.h b/mt7915/coredump.h +index 709f8e9..809ccbd 100644 +--- a/mt7915/coredump.h ++++ b/mt7915/coredump.h +@@ -4,6 +4,7 @@ + #ifndef _COREDUMP_H_ + #define _COREDUMP_H_ + ++#include "../mt76_connac_mcu.h" + #include "mt7915.h" + + struct trace { +@@ -15,6 +16,7 @@ struct mt7915_coredump { + char magic[16]; + + u32 len; ++ u32 hdr_len; + + guid_t guid; + +@@ -26,12 +28,28 @@ struct mt7915_coredump { + char kernel[64]; + /* firmware version */ + char fw_ver[ETHTOOL_FWVERS_LEN]; ++ char fw_patch_date[MT76_BUILD_TIME_LEN]; ++ char fw_ram_date[__MT76_RAM_TYPE_MAX][MT76_BUILD_TIME_LEN]; + + u32 device_id; + ++ /* fw type */ ++ char fw_type[8]; + /* exception state */ + char fw_state[12]; + ++ /* program counters */ ++ u32 pc_dbg_ctrl; ++ u32 pc_cur_idx; ++ u32 pc_cur[10]; ++ /* PC registers */ ++ u32 pc_stack[32]; ++ ++ u32 lr_dbg_ctrl; ++ u32 lr_cur_idx; ++ /* LR registers */ ++ u32 lr_stack[32]; ++ + u32 last_msg_id; + u32 eint_info_idx; + u32 irq_info_idx; +@@ -70,9 +88,6 @@ struct mt7915_coredump { + u32 handler; + } context; + +- /* link registers calltrace */ +- u32 call_stack[16]; +- + /* memory content */ + u8 data[]; + } __packed; +@@ -83,6 +98,7 @@ struct mt7915_coredump_mem { + } __packed; + + struct mt7915_mem_hdr { ++ char name[64]; + u32 start; + u32 len; + u8 data[]; +@@ -98,26 +114,26 @@ struct mt7915_mem_region { + #ifdef CONFIG_DEV_COREDUMP + + const struct mt7915_mem_region * +-mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num); +-struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev); +-int mt7915_coredump_submit(struct mt7915_dev *dev); ++mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u8 type, u32 *num); ++struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev, u8 type); ++int mt7915_coredump_submit(struct mt7915_dev *dev, u8 type); + int mt7915_coredump_register(struct mt7915_dev *dev); + void mt7915_coredump_unregister(struct mt7915_dev *dev); + + #else /* CONFIG_DEV_COREDUMP */ + + static inline const struct mt7915_mem_region * +-mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num) ++mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u8 type, u32 *num) + { + return NULL; + } + +-static inline int mt7915_coredump_submit(struct mt7915_dev *dev) ++static inline int mt7915_coredump_submit(struct mt7915_dev *dev, u8 type) + { + return 0; + } + +-static inline struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev) ++static inline struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev, u8 type) + { + return NULL; + } +diff --git a/mt7915/mac.c b/mt7915/mac.c +index b915201..0f6b806 100644 +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1597,28 +1597,31 @@ void mt7915_mac_reset_work(struct work_struct *work) + } + + /* firmware coredump */ +-void mt7915_mac_dump_work(struct work_struct *work) ++static void mt7915_mac_fw_coredump(struct mt7915_dev *dev, u8 type) + { + const struct mt7915_mem_region *mem_region; + struct mt7915_crash_data *crash_data; +- struct mt7915_dev *dev; + struct mt7915_mem_hdr *hdr; + size_t buf_len; + int i; + u32 num; + u8 *buf; + +- dev = container_of(work, struct mt7915_dev, dump_work); ++ if (type != MT76_RAM_TYPE_WM) { ++ dev_warn(dev->mt76.dev, "%s currently only supports WM coredump!\n", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ return; ++ } + + mutex_lock(&dev->dump_mutex); + +- crash_data = mt7915_coredump_new(dev); ++ crash_data = mt7915_coredump_new(dev, type); + if (!crash_data) { + mutex_unlock(&dev->dump_mutex); +- goto skip_coredump; ++ return; + } + +- mem_region = mt7915_coredump_get_mem_layout(dev, &num); ++ mem_region = mt7915_coredump_get_mem_layout(dev, type, &num); + if (!mem_region || !crash_data->memdump_buf_len) { + mutex_unlock(&dev->dump_mutex); + goto skip_memdump; +@@ -1628,6 +1631,9 @@ void mt7915_mac_dump_work(struct work_struct *work) + buf_len = crash_data->memdump_buf_len; + + /* dumping memory content... */ ++ dev_info(dev->mt76.dev, "%s start coredump for %s\n", ++ wiphy_name(dev->mt76.hw->wiphy), ++ ((type == MT76_RAM_TYPE_WA) ? "WA" : "WM")); + memset(buf, 0, buf_len); + for (i = 0; i < num; i++) { + if (mem_region->len > buf_len) { +@@ -1645,6 +1651,7 @@ void mt7915_mac_dump_work(struct work_struct *work) + mt7915_memcpy_fromio(dev, buf, mem_region->start, + mem_region->len); + ++ strscpy(hdr->name, mem_region->name, sizeof(mem_region->name)); + hdr->start = mem_region->start; + hdr->len = mem_region->len; + +@@ -1661,8 +1668,18 @@ void mt7915_mac_dump_work(struct work_struct *work) + mutex_unlock(&dev->dump_mutex); + + skip_memdump: +- mt7915_coredump_submit(dev); +-skip_coredump: ++ mt7915_coredump_submit(dev, type); ++} ++ ++void mt7915_mac_dump_work(struct work_struct *work) ++{ ++ struct mt7915_dev *dev; ++ ++ dev = container_of(work, struct mt7915_dev, dump_work); ++ ++ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WM_WDT) ++ mt7915_mac_fw_coredump(dev, MT76_RAM_TYPE_WM); ++ + queue_work(dev->mt76.wq, &dev->reset_work); + } + +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index aee30c7..5cd2b33 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -286,7 +286,7 @@ struct mt7915_dev { + struct mutex dump_mutex; + #ifdef CONFIG_DEV_COREDUMP + struct { +- struct mt7915_crash_data *crash_data; ++ struct mt7915_crash_data *crash_data[__MT76_RAM_TYPE_MAX]; + } coredump; + #endif + +diff --git a/mt7915/regs.h b/mt7915/regs.h +index 89ac8e6..7515b23 100644 +--- a/mt7915/regs.h ++++ b/mt7915/regs.h +@@ -1219,4 +1219,24 @@ enum offs_rev { + #define MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR MT_MCU_WM_CIRQ(0x108) + #define MT_MCU_WM_CIRQ_EINT_SOFT_ADDR MT_MCU_WM_CIRQ(0x118) + ++/* CONN DBG */ ++#define MT_CONN_DBG_CTL_BASE 0x18060000 ++#define MT_CONN_DBG_CTL(ofs) (MT_CONN_DBG_CTL_BASE + (ofs)) ++#define MT_CONN_DBG_CTL_LOG_SEL MT_CONN_DBG_CTL(0x090) ++#define MT_CONN_DBG_CTL_PC_LOG_SEL GENMASK(7, 2) ++#define MT_CONN_DBG_CTL_GPR_LOG_SEL GENMASK(13, 8) ++#define MT_CONN_DBG_CTL_PC_LOG MT_CONN_DBG_CTL(0x204) ++#define MT_CONN_DBG_CTL_GPR_LOG MT_CONN_DBG_CTL(0x204) ++ ++/* CONN MCU EXCP CON */ ++#define MT_MCU_WM_EXCP_BASE 0x89050000 ++ ++#define MT_MCU_WM_EXCP(ofs) (MT_MCU_WM_EXCP_BASE + (ofs)) ++#define MT_MCU_WM_EXCP_PC_CTRL MT_MCU_WM_EXCP(0x100) ++#define MT_MCU_WM_EXCP_PC_CTRL_IDX_STATUS GENMASK(20, 16) ++#define MT_MCU_WM_EXCP_PC_LOG MT_MCU_WM_EXCP(0x104) ++#define MT_MCU_WM_EXCP_LR_CTRL MT_MCU_WM_EXCP(0x200) ++#define MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS GENMASK(20, 16) ++#define MT_MCU_WM_EXCP_LR_LOG MT_MCU_WM_EXCP(0x204) ++ + #endif +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0003-wifi-mt76-mt7915-move-temperature-margin-check-to-mt.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0003-wifi-mt76-mt7915-move-temperature-margin-check-to-mt.patch new file mode 100644 index 000000000..2e4c7d0f8 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0003-wifi-mt76-mt7915-move-temperature-margin-check-to-mt.patch @@ -0,0 +1,56 @@ +From 5201efd8c8527bf4f7f60c8be5d558f847b8c4e4 Mon Sep 17 00:00:00 2001 +From: Howard Hsu +Date: Thu, 13 Jul 2023 15:50:00 +0800 +Subject: [PATCH 03/14] wifi: mt76: mt7915: move temperature margin check to + mt7915_thermal_temp_store() + +Originally, we would reduce the 10-degree margin to the restore +temperature, but the user would not be aware of this when setting it. +Moving the margin reduction to the user setting check allows the user to +clearly understand that there is a 10-degree difference between the +restore and trigger temperature. + +Signed-off-by: Howard Hsu +--- + mt7915/init.c | 7 ++++--- + mt7915/mcu.c | 3 +-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/mt7915/init.c b/mt7915/init.c +index edf83c4..9fe0524 100644 +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -83,12 +83,13 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev, + mutex_lock(&phy->dev->mt76.mutex); + val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 60, 130); + ++ /* add a safety margin ~10 */ + if ((i - 1 == MT7915_CRIT_TEMP_IDX && +- val > phy->throttle_temp[MT7915_MAX_TEMP_IDX]) || ++ val > phy->throttle_temp[MT7915_MAX_TEMP_IDX] - 10) || + (i - 1 == MT7915_MAX_TEMP_IDX && +- val < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) { ++ val - 10 < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) { + dev_err(phy->dev->mt76.dev, +- "temp1_max shall be greater than temp1_crit."); ++ "temp1_max shall be 10 degrees greater than temp1_crit."); + mutex_unlock(&phy->dev->mt76.mutex); + return -EINVAL; + } +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index 7df2162..6e9970c 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -3226,8 +3226,7 @@ int mt7915_mcu_set_thermal_protect(struct mt7915_phy *phy) + + /* set high-temperature trigger threshold */ + req.ctrl.ctrl_id = THERMAL_PROTECT_ENABLE; +- /* add a safety margin ~10 */ +- req.restore_temp = cpu_to_le32(phy->throttle_temp[0] - 10); ++ req.restore_temp = cpu_to_le32(phy->throttle_temp[0]); + req.trigger_temp = cpu_to_le32(phy->throttle_temp[1]); + req.sustain_time = cpu_to_le16(10); + +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0004-wifi-mt76-mt7915-fix-txpower-issues.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0004-wifi-mt76-mt7915-fix-txpower-issues.patch new file mode 100644 index 000000000..06dbcd824 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0004-wifi-mt76-mt7915-fix-txpower-issues.patch @@ -0,0 +1,123 @@ +From 81f7cb7c452f3e3cce7818bfd0547fc57c280dce Mon Sep 17 00:00:00 2001 +From: Evelyn Tsai +Date: Sat, 29 Jul 2023 04:53:47 +0800 +Subject: [PATCH 04/14] wifi: mt76: mt7915: fix txpower issues + +--- + eeprom.c | 2 +- + mt7915/debugfs.c | 48 ++++++++++++++++++++++++++---------------------- + mt7915/main.c | 1 + + 3 files changed, 28 insertions(+), 23 deletions(-) + +diff --git a/eeprom.c b/eeprom.c +index 0bc66cc..ecd09c0 100644 +--- a/eeprom.c ++++ b/eeprom.c +@@ -343,7 +343,7 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, + u32 ru_rates = ARRAY_SIZE(dest->ru[0]); + char band; + size_t len; +- s8 max_power = 0; ++ s8 max_power = -127; + s8 txs_delta; + + if (!mcs_rates) +diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c +index 5780138..894e2cd 100644 +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -951,9 +951,9 @@ mt7915_xmit_queues_show(struct seq_file *file, void *data) + + DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues); + +-#define mt7915_txpower_puts(rate) \ ++#define mt7915_txpower_puts(rate, _len) \ + ({ \ +- len += scnprintf(buf + len, sz - len, "%-16s:", #rate " (TMAC)"); \ ++ len += scnprintf(buf + len, sz - len, "%-*s:", _len, #rate " (TMAC)"); \ + for (i = 0; i < mt7915_sku_group_len[SKU_##rate]; i++, offs++) \ + len += scnprintf(buf + len, sz - len, " %6d", txpwr[offs]); \ + len += scnprintf(buf + len, sz - len, "\n"); \ +@@ -995,43 +995,47 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, + len += scnprintf(buf + len, sz - len, + "\nPhy%d Tx power table (channel %d)\n", + phy != &dev->phy, phy->mt76->chandef.chan->hw_value); +- len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s\n", ++ len += scnprintf(buf + len, sz - len, "%-23s %6s %6s %6s %6s\n", + " ", "1m", "2m", "5m", "11m"); +- mt7915_txpower_puts(CCK); ++ mt7915_txpower_puts(CCK, 23); + + len += scnprintf(buf + len, sz - len, +- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", ++ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m", + "54m"); +- mt7915_txpower_puts(OFDM); ++ mt7915_txpower_puts(OFDM, 23); + + len += scnprintf(buf + len, sz - len, +- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", ++ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", + "mcs5", "mcs6", "mcs7"); +- mt7915_txpower_puts(HT_BW20); ++ mt7915_txpower_puts(HT_BW20, 23); + + len += scnprintf(buf + len, sz - len, +- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", ++ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", + "mcs6", "mcs7", "mcs32"); +- mt7915_txpower_puts(HT_BW40); ++ mt7915_txpower_puts(HT_BW40, 23); + + len += scnprintf(buf + len, sz - len, +- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", ++ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", + "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11"); +- mt7915_txpower_puts(VHT_BW20); +- mt7915_txpower_puts(VHT_BW40); +- mt7915_txpower_puts(VHT_BW80); +- mt7915_txpower_puts(VHT_BW160); +- mt7915_txpower_puts(HE_RU26); +- mt7915_txpower_puts(HE_RU52); +- mt7915_txpower_puts(HE_RU106); +- mt7915_txpower_puts(HE_RU242); +- mt7915_txpower_puts(HE_RU484); +- mt7915_txpower_puts(HE_RU996); +- mt7915_txpower_puts(HE_RU2x996); ++ mt7915_txpower_puts(VHT_BW20, 23); ++ mt7915_txpower_puts(VHT_BW40, 23); ++ mt7915_txpower_puts(VHT_BW80, 23); ++ mt7915_txpower_puts(VHT_BW160, 23); ++ mt7915_txpower_puts(HE_RU26, 23); ++ mt7915_txpower_puts(HE_RU52, 23); ++ mt7915_txpower_puts(HE_RU106, 23); ++ len += scnprintf(buf + len, sz - len, "BW20/"); ++ mt7915_txpower_puts(HE_RU242, 18); ++ len += scnprintf(buf + len, sz - len, "BW40/"); ++ mt7915_txpower_puts(HE_RU484, 18); ++ len += scnprintf(buf + len, sz - len, "BW80/"); ++ mt7915_txpower_puts(HE_RU996, 18); ++ len += scnprintf(buf + len, sz - len, "BW160/"); ++ mt7915_txpower_puts(HE_RU2x996, 17); + + reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(band) : + MT_WF_PHY_TPC_CTRL_STAT_MT7916(band); +diff --git a/mt7915/main.c b/mt7915/main.c +index e61041d..1903db4 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -1080,6 +1080,7 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) + mt76_set_stream_caps(phy->mt76, true); + mt7915_set_stream_vht_txbf_caps(phy); + mt7915_set_stream_he_caps(phy); ++ mt7915_mcu_set_txpower_sku(phy); + + mutex_unlock(&dev->mt76.mutex); + +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0005-wifi-mt76-mt7915-Fixed-null-pointer-dereference-issu.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0005-wifi-mt76-mt7915-Fixed-null-pointer-dereference-issu.patch new file mode 100644 index 000000000..a30ec46ff --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0005-wifi-mt76-mt7915-Fixed-null-pointer-dereference-issu.patch @@ -0,0 +1,42 @@ +From d4b6226c74988932d9df8f1a6b5afbcea7effc38 Mon Sep 17 00:00:00 2001 +From: MeiChia Chiu +Date: Thu, 26 Oct 2023 21:11:05 +0800 +Subject: [PATCH 05/14] wifi: mt76: mt7915: Fixed null pointer dereference + issue + +Without this patch, when the station is still in Authentication stage and +sends a "Notify bandwidth change action frame" to AP at the same time, +there will be a race condition that causes a crash to occur because the AP +access "msta->vif" that has not been fully initialized. + +Signed-off-by: Bo Jiao +Signed-off-by: Money Wang +Signed-off-by: MeiChia Chiu +--- + mt7915/main.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/mt7915/main.c b/mt7915/main.c +index 1903db4..61a1dbb 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -1170,9 +1170,16 @@ static void mt7915_sta_rc_update(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u32 changed) + { ++ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = phy->dev; + ++ if (!msta->vif) { ++ dev_warn(dev->mt76.dev, "Un-initialized STA %pM wcid %d in rc_work\n", ++ sta->addr, msta->wcid.idx); ++ return; ++ } ++ + mt7915_sta_rc_work(&changed, sta); + ieee80211_queue_work(hw, &dev->rc_work); + } +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0006-wifi-mt76-ACS-channel-time-too-long-on-duty-channel.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0006-wifi-mt76-ACS-channel-time-too-long-on-duty-channel.patch new file mode 100644 index 000000000..114ee03bb --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0006-wifi-mt76-ACS-channel-time-too-long-on-duty-channel.patch @@ -0,0 +1,51 @@ +From dbc2448c773d6c2e8a36513a0c855ff0775f5ec4 Mon Sep 17 00:00:00 2001 +From: Evelyn Tsai +Date: Sat, 18 Nov 2023 07:36:45 +0800 +Subject: [PATCH 06/14] wifi: mt76: ACS channel time too long on duty channel + +Issue: +There's a chance that the channel time for duty channel is zero in ACS +scan. + +Root cause: +The chan_stat may be reset when restore to duty channel. +Mac80211 will notify to hostapd when scan done and then restore to duty +channel. +And mt76 will clear scan flag after restore done. +If hostapd get the chan_stat before channel_restore, will get the +correct channel time; +If hostapd get the chan_stat after channel_restore, will get zero +channel time; + +Solution: +When channel switch, will check the mac80211 scan state but not the mt76 scan flag. +Mac80211 scan state will be set in scanning, and will be reset after +scan done and before restore to duty channel. +--- + mac80211.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/mac80211.c b/mac80211.c +index e7b763b..bc20f60 100644 +--- a/mac80211.c ++++ b/mac80211.c +@@ -927,6 +927,7 @@ void mt76_set_channel(struct mt76_phy *phy) + struct cfg80211_chan_def *chandef = &hw->conf.chandef; + bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; + int timeout = HZ / 5; ++ unsigned long was_scanning = ieee80211_get_scanning(hw); + + wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); + mt76_update_survey(phy); +@@ -941,7 +942,7 @@ void mt76_set_channel(struct mt76_phy *phy) + if (!offchannel) + phy->main_chan = chandef->chan; + +- if (chandef->chan != phy->main_chan) ++ if (chandef->chan != phy->main_chan || was_scanning) + memset(phy->chan_state, 0, sizeof(*phy->chan_state)); + } + EXPORT_SYMBOL_GPL(mt76_set_channel); +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0007-wifi-mt76-mt7915-add-post-channel-switch-for-DFS-cha.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0007-wifi-mt76-mt7915-add-post-channel-switch-for-DFS-cha.patch new file mode 100644 index 000000000..1151befcf --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0007-wifi-mt76-mt7915-add-post-channel-switch-for-DFS-cha.patch @@ -0,0 +1,54 @@ +From 72e729e50f4b162db845e988275b91db2d558ef1 Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Thu, 16 Nov 2023 14:41:54 +0800 +Subject: [PATCH 07/14] wifi: mt76: mt7915: add post channel switch for DFS + channel switching + +Signed-off-by: StanleyYP Wang +--- + mt7915/main.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/mt7915/main.c b/mt7915/main.c +index 61a1dbb..71e0d55 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -736,6 +736,27 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw, + mutex_unlock(&dev->mt76.mutex); + } + ++static int ++mt7915_post_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++{ ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct cfg80211_chan_def *chandef = &phy->mt76->chandef; ++ int ret; ++ ++ ret = cfg80211_chandef_dfs_required(hw->wiphy, chandef, NL80211_IFTYPE_AP); ++ if (ret <= 0) ++ goto out; ++ ++ ieee80211_stop_queues(hw); ++ ret = mt7915_set_channel(phy); ++ if (ret) ++ goto out; ++ ieee80211_wake_queues(hw); ++ ++out: ++ return ret; ++} ++ + int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +@@ -1701,6 +1722,7 @@ const struct ieee80211_ops mt7915_ops = { + .get_txpower = mt76_get_txpower, + .set_sar_specs = mt7915_set_sar_specs, + .channel_switch_beacon = mt7915_channel_switch_beacon, ++ .post_channel_switch = mt7915_post_channel_switch, + .get_stats = mt7915_get_stats, + .get_et_sset_count = mt7915_get_et_sset_count, + .get_et_stats = mt7915_get_et_stats, +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0008-wifi-mt76-mt7915-add-support-for-realtime-Rx-rate-up.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0008-wifi-mt76-mt7915-add-support-for-realtime-Rx-rate-up.patch new file mode 100644 index 000000000..c17f0f461 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0008-wifi-mt76-mt7915-add-support-for-realtime-Rx-rate-up.patch @@ -0,0 +1,53 @@ +From 0e87f52e13e654b144c12e3aad968fbc3da5ac1b Mon Sep 17 00:00:00 2001 +From: "Henry.Yen" +Date: Mon, 8 Jan 2024 17:19:01 +0800 +Subject: [PATCH 08/14] wifi: mt76: mt7915: add support for realtime Rx rate + updates + +Add support for realtime Rx rate updates. + +Currently, Rx rate is updated according to packet-triggered RxV +parsing flow, i.e., mt76_connac2_mac_fill_rx_rate(). However, whenever +the session enters hardware acceleration, driver layer won't have +any clue about what the current Rx rate is. So we make use of MCU +CMD to obtain Rx rate instead. + +Signed-off-by: Henry.Yen +--- + mt76_connac.h | 6 ++++++ + mt7915/main.c | 2 +- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/mt76_connac.h b/mt76_connac.h +index 91987bd..4871857 100644 +--- a/mt76_connac.h ++++ b/mt76_connac.h +@@ -260,6 +260,12 @@ static inline bool is_connac_v1(struct mt76_dev *dev) + return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev); + } + ++static inline bool is_connac_v2(struct mt76_dev *dev) ++{ ++ return is_mt7915(dev) || is_mt7916(dev) || ++ is_mt7981(dev) || is_mt7986(dev); ++} ++ + static inline bool is_mt76_fw_txp(struct mt76_dev *dev) + { + switch (mt76_chip(dev)) { +diff --git a/mt7915/main.c b/mt7915/main.c +index 71e0d55..5d31f5a 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -1118,7 +1118,7 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, + struct rate_info *txrate = &msta->wcid.rate; + struct rate_info rxrate = {}; + +- if (is_mt7915(&phy->dev->mt76) && ++ if (is_connac_v2(&phy->dev->mt76) && + !mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) { + sinfo->rxrate = rxrate; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0009-wifi-mt76-mt7915-remove-redundant-argument-in-add_be.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0009-wifi-mt76-mt7915-remove-redundant-argument-in-add_be.patch new file mode 100644 index 000000000..2d608c693 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0009-wifi-mt76-mt7915-remove-redundant-argument-in-add_be.patch @@ -0,0 +1,82 @@ +From 995dd81673e89e6b387d256e26a0cf07e2ccb0e5 Mon Sep 17 00:00:00 2001 +From: MeiChia Chiu +Date: Wed, 24 Jan 2024 15:04:33 +0800 +Subject: [PATCH 09/14] wifi: mt76: mt7915: remove redundant argument in + add_beacon function + +Remove redundant argument "changed". + +Signed-off-by: MeiChia Chiu +--- + mt7915/mac.c | 3 +-- + mt7915/main.c | 4 ++-- + mt7915/mcu.c | 3 +-- + mt7915/mt7915.h | 2 +- + 4 files changed, 5 insertions(+), 7 deletions(-) + +diff --git a/mt7915/mac.c b/mt7915/mac.c +index 0f6b806..ada3a7f 100644 +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1285,8 +1285,7 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: +- mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon, +- BSS_CHANGED_BEACON_ENABLED); ++ mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); + break; + default: + break; +diff --git a/mt7915/main.c b/mt7915/main.c +index 5d31f5a..9eeca39 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -659,7 +659,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, + + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) +- mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); ++ mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); + + if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)) +@@ -732,7 +732,7 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw, + struct mt7915_dev *dev = mt7915_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); +- mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON); ++ mt7915_mcu_add_beacon(hw, vif, true); + mutex_unlock(&dev->mt76.mutex); + } + +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index 6e9970c..84ffe07 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -1970,8 +1970,7 @@ mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, + MCU_EXT_CMD(BSS_INFO_UPDATE), true); + } + +-int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- int en, u32 changed) ++int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en) + { + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 5cd2b33..e1801d5 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -461,7 +461,7 @@ int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vi + int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, + u32 changed); + int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- int enable, u32 changed); ++ int enable); + int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_he_obss_pd *he_obss_pd); + int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0010-wifi-mt76-mt7915-add-support-for-WMM-PBC-configurati.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0010-wifi-mt76-mt7915-add-support-for-WMM-PBC-configurati.patch new file mode 100644 index 000000000..b4c617944 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0010-wifi-mt76-mt7915-add-support-for-WMM-PBC-configurati.patch @@ -0,0 +1,243 @@ +From 9c7177584089b98089142568514af4b23e0d4e72 Mon Sep 17 00:00:00 2001 +From: Benjamin Lin +Date: Mon, 29 Jan 2024 11:28:41 +0800 +Subject: [PATCH 10/14] wifi: mt76: mt7915: add support for WMM PBC + configuration + +--- + mt76_connac_mcu.h | 2 ++ + mt7915/init.c | 2 ++ + mt7915/mac.c | 14 ++++++++ + mt7915/mcu.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/mcu.h | 15 ++++++++ + mt7915/mt7915.h | 4 +++ + 6 files changed, 127 insertions(+) + +diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h +index 67be14d..1dd8244 100644 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1025,6 +1025,7 @@ enum { + MCU_EXT_EVENT_ASSERT_DUMP = 0x23, + MCU_EXT_EVENT_RDD_REPORT = 0x3a, + MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, ++ MCU_EXT_EVENT_BSS_ACQ_PKT_CNT = 0x52, + MCU_EXT_EVENT_WA_TX_STAT = 0x74, + MCU_EXT_EVENT_BCC_NOTIFY = 0x75, + MCU_EXT_EVENT_MURU_CTRL = 0x9f, +@@ -1220,6 +1221,7 @@ enum { + MCU_EXT_CMD_TXDPD_CAL = 0x60, + MCU_EXT_CMD_CAL_CACHE = 0x67, + MCU_EXT_CMD_RED_ENABLE = 0x68, ++ MCU_EXT_CMD_PKT_BUDGET_CTRL = 0x6c, + MCU_EXT_CMD_CP_SUPPORT = 0x75, + MCU_EXT_CMD_SET_RADAR_TH = 0x7c, + MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, +diff --git a/mt7915/init.c b/mt7915/init.c +index 9fe0524..f81a2f2 100644 +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -1221,6 +1221,8 @@ int mt7915_register_device(struct mt7915_dev *dev) + INIT_WORK(&dev->dump_work, mt7915_mac_dump_work); + mutex_init(&dev->dump_mutex); + ++ INIT_WORK(&dev->wmm_pbc_work, mt7915_mcu_wmm_pbc_work); ++ + dev->dbdc_support = mt7915_band_config(dev); + + phy2 = mt7915_alloc_ext_phy(dev); +diff --git a/mt7915/mac.c b/mt7915/mac.c +index ada3a7f..e167e7b 100644 +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -2032,6 +2032,8 @@ void mt7915_mac_work(struct work_struct *work) + + mt76_update_survey(mphy); + if (++mphy->mac_work_count == 5) { ++ int i; ++ + mphy->mac_work_count = 0; + + mt7915_mac_update_stats(phy); +@@ -2039,6 +2041,18 @@ void mt7915_mac_work(struct work_struct *work) + + if (phy->dev->muru_debug) + mt7915_mcu_muru_debug_get(phy); ++ ++ /* Update DEV-wise information only in ++ * the MAC work of the first band running. ++ */ ++ for (i = MT_BAND0; i <= mphy->band_idx; ++i) { ++ if (i == mphy->band_idx) { ++ if (mt7915_mcu_wa_cmd(phy->dev, MCU_WA_PARAM_CMD(QUERY), MCU_WA_PARAM_BSS_ACQ_PKT_CNT, ++ BSS_ACQ_PKT_CNT_BSS_BITMAP_ALL | BSS_ACQ_PKT_CNT_READ_CLR, 0)) ++ dev_err(mphy->dev->dev, "Failed to query per-AC-queue packet counts.\n"); ++ } else if (test_bit(MT76_STATE_RUNNING, &mphy->dev->phys[i]->state)) ++ break; ++ } + } + + if (++phy->stats_work_count == 10) { +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index 84ffe07..446c512 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -354,6 +354,93 @@ mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb) + mt7915_mcu_cca_finish, mphy->hw); + } + ++void mt7915_mcu_wmm_pbc_work(struct work_struct *work) ++{ ++#define WMM_PBC_QUEUE_NUM 5 ++#define WMM_PBC_BSS_ALL 0xff ++#define WMM_PBC_WLAN_IDX_ALL 0xffff ++#define WMM_PBC_BOUND_DEFAULT 0xffff ++#define WMM_PBC_UP_BOUND_BAND0_VO 950 ++#define WMM_PBC_UP_BOUND_BAND0_VI 950 ++#define WMM_PBC_UP_BOUND_BAND0_BE 750 ++#define WMM_PBC_UP_BOUND_BAND0_BK 450 ++#define WMM_PBC_UP_BOUND_BAND1_VO 1900 ++#define WMM_PBC_UP_BOUND_BAND1_VI 1900 ++#define WMM_PBC_UP_BOUND_BAND1_BE 1500 ++#define WMM_PBC_UP_BOUND_BAND1_BK 900 ++#define WMM_PBC_UP_BOUND_MGMT 32 ++ struct mt7915_dev *dev = container_of(work, struct mt7915_dev, wmm_pbc_work); ++ struct { ++ u8 bss_idx; ++ u8 queue_num; ++ __le16 wlan_idx; ++ u8 __rsv[4]; ++ struct { ++ __le16 low; ++ __le16 up; ++ } __packed bound[WMM_PBC_QUEUE_NUM * 2]; ++ } __packed req = { ++ .bss_idx = WMM_PBC_BSS_ALL, ++ .queue_num = WMM_PBC_QUEUE_NUM * 2, ++ .wlan_idx = cpu_to_le16(WMM_PBC_WLAN_IDX_ALL), ++ }; ++ int i; ++ ++#define pbc_acq_up_bound_config(_band, _ac, _bound) \ ++ req.bound[_band * WMM_PBC_QUEUE_NUM + mt76_connac_lmac_mapping(_ac)].up = dev->wmm_pbc_enable \ ++ ? cpu_to_le16(_bound) \ ++ : cpu_to_le16(WMM_PBC_BOUND_DEFAULT) ++ pbc_acq_up_bound_config(MT_BAND0, IEEE80211_AC_VO, WMM_PBC_UP_BOUND_BAND0_VO); ++ pbc_acq_up_bound_config(MT_BAND0, IEEE80211_AC_VI, WMM_PBC_UP_BOUND_BAND0_VI); ++ pbc_acq_up_bound_config(MT_BAND0, IEEE80211_AC_BE, WMM_PBC_UP_BOUND_BAND0_BE); ++ pbc_acq_up_bound_config(MT_BAND0, IEEE80211_AC_BK, WMM_PBC_UP_BOUND_BAND0_BK); ++ req.bound[MT_BAND0 * WMM_PBC_QUEUE_NUM + 4].up = dev->wmm_pbc_enable ++ ? cpu_to_le16(WMM_PBC_UP_BOUND_MGMT) ++ : cpu_to_le16(WMM_PBC_BOUND_DEFAULT); ++ pbc_acq_up_bound_config(MT_BAND1, IEEE80211_AC_VO, WMM_PBC_UP_BOUND_BAND1_VO); ++ pbc_acq_up_bound_config(MT_BAND1, IEEE80211_AC_VI, WMM_PBC_UP_BOUND_BAND1_VI); ++ pbc_acq_up_bound_config(MT_BAND1, IEEE80211_AC_BE, WMM_PBC_UP_BOUND_BAND1_BE); ++ pbc_acq_up_bound_config(MT_BAND1, IEEE80211_AC_BK, WMM_PBC_UP_BOUND_BAND1_BK); ++ req.bound[MT_BAND1 * WMM_PBC_QUEUE_NUM + 4].up = dev->wmm_pbc_enable ++ ? cpu_to_le16(WMM_PBC_UP_BOUND_MGMT) ++ : cpu_to_le16(WMM_PBC_BOUND_DEFAULT); ++ ++ for (i = 0; i < WMM_PBC_QUEUE_NUM * 2; ++i) ++ req.bound[i].low = cpu_to_le16(WMM_PBC_BOUND_DEFAULT); ++ ++ if (mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(PKT_BUDGET_CTRL), ++ &req, sizeof(req), true)) ++ dev_err(dev->mt76.dev, "Failed to configure WMM PBC.\n"); ++} ++ ++static void ++mt7915_mcu_rx_bss_acq_pkt_cnt(struct mt7915_dev *dev, struct sk_buff * skb) ++{ ++ struct mt7915_mcu_bss_acq_pkt_cnt_event *event = (struct mt7915_mcu_bss_acq_pkt_cnt_event *)skb->data; ++ u32 bitmap = le32_to_cpu(event->bss_bitmap); ++ u64 sum[IEEE80211_NUM_ACS] = {0}; ++ u8 ac_cnt = 0; ++ int i, j; ++ ++ for (i = 0; (i < BSS_ACQ_PKT_CNT_BSS_NUM) && (bitmap & (1 << i)); ++i) { ++ for (j = IEEE80211_AC_VO; j < IEEE80211_NUM_ACS; ++j) ++ sum[j] += le32_to_cpu(event->bss[i].cnt[mt76_connac_lmac_mapping(j)]); ++ } ++ ++ for (i = IEEE80211_AC_VO; i < IEEE80211_NUM_ACS; ++i) { ++ if (sum[i] > WMM_PKT_THRESHOLD) ++ ++ac_cnt; ++ } ++ ++ if (ac_cnt > 1 && !dev->wmm_pbc_enable) { ++ dev->wmm_pbc_enable = true; ++ queue_work(dev->mt76.wq, &dev->wmm_pbc_work); ++ } else if (ac_cnt <= 1 && dev->wmm_pbc_enable) { ++ dev->wmm_pbc_enable = false; ++ queue_work(dev->mt76.wq, &dev->wmm_pbc_work); ++ } ++} ++ + static void + mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) + { +@@ -376,6 +463,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) + case MCU_EXT_EVENT_BCC_NOTIFY: + mt7915_mcu_rx_bcc_notify(dev, skb); + break; ++ case MCU_EXT_EVENT_BSS_ACQ_PKT_CNT: ++ mt7915_mcu_rx_bss_acq_pkt_cnt(dev, skb); ++ break; + default: + break; + } +diff --git a/mt7915/mcu.h b/mt7915/mcu.h +index 8f36546..fa0847d 100644 +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -329,10 +329,25 @@ enum { + MCU_WA_PARAM_CMD_DEBUG, + }; + ++#define BSS_ACQ_PKT_CNT_BSS_NUM 24 ++#define BSS_ACQ_PKT_CNT_BSS_BITMAP_ALL 0x00ffffff ++#define BSS_ACQ_PKT_CNT_READ_CLR BIT(31) ++#define WMM_PKT_THRESHOLD 50 ++ ++struct mt7915_mcu_bss_acq_pkt_cnt_event { ++ struct mt76_connac2_mcu_rxd rxd; ++ ++ __le32 bss_bitmap; ++ struct { ++ __le32 cnt[IEEE80211_NUM_ACS]; ++ } __packed bss[BSS_ACQ_PKT_CNT_BSS_NUM]; ++} __packed; ++ + enum { + MCU_WA_PARAM_PDMA_RX = 0x04, + MCU_WA_PARAM_CPU_UTIL = 0x0b, + MCU_WA_PARAM_RED = 0x0e, ++ MCU_WA_PARAM_BSS_ACQ_PKT_CNT = 0x12, + MCU_WA_PARAM_RED_SETTING = 0x40, + }; + +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index e1801d5..89156f3 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -326,6 +326,9 @@ struct mt7915_dev { + struct reset_control *rstc; + void __iomem *dcm; + void __iomem *sku; ++ ++ bool wmm_pbc_enable; ++ struct work_struct wmm_pbc_work; + }; + + enum { +@@ -516,6 +519,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); + int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); + void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb); + void mt7915_mcu_exit(struct mt7915_dev *dev); ++void mt7915_mcu_wmm_pbc_work(struct work_struct *work); + + static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev) + { +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/patches/0012-wifi-mt76-fix-tx-statistics-about-tx-retry-and-tx-fa.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0011-wifi-mt76-fix-tx-statistics-about-tx-retry-and-tx-fa.patch similarity index 82% rename from feeds/mediatek-sdk/mt76/patches/0012-wifi-mt76-fix-tx-statistics-about-tx-retry-and-tx-fa.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/0011-wifi-mt76-fix-tx-statistics-about-tx-retry-and-tx-fa.patch index ba1d990c2..04b333264 100644 --- a/feeds/mediatek-sdk/mt76/patches/0012-wifi-mt76-fix-tx-statistics-about-tx-retry-and-tx-fa.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0011-wifi-mt76-fix-tx-statistics-about-tx-retry-and-tx-fa.patch @@ -1,7 +1,7 @@ -From 44a55f1f2dbe5c2324b24e70772339c490b8e2af Mon Sep 17 00:00:00 2001 +From 3bbf19ff34cd0d7ef3371b49101bbcaf9d068668 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Mon, 29 Jan 2024 11:02:06 +0800 -Subject: [PATCH 12/15] wifi: mt76: fix tx statistics about tx retry and tx +Subject: [PATCH 11/14] wifi: mt76: fix tx statistics about tx retry and tx fail The tx retry and tx failed are reported by PPDU TxS. @@ -13,7 +13,7 @@ Signed-off-by: Peter Chiu 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c -index b841bf62..630c6402 100644 +index b841bf6..630c640 100644 --- a/mt76_connac_mac.c +++ b/mt76_connac_mac.c @@ -716,9 +716,6 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid, @@ -27,10 +27,10 @@ index b841bf62..630c6402 100644 skb = mt76_tx_status_skb_get(dev, wcid, pid, &list); if (skb) { diff --git a/mt7915/mac.c b/mt7915/mac.c -index 762159b4..e819815a 100644 +index e167e7b..a5d0b09 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c -@@ -1014,7 +1014,7 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) +@@ -1021,7 +1021,7 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) msta = container_of(wcid, struct mt7915_sta, wcid); diff --git a/feeds/mediatek-sdk/mt76/patches/0013-wifi-mt76-add-sanity-check-to-prevent-kernel-crash.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0012-wifi-mt76-add-sanity-check-to-prevent-kernel-crash.patch similarity index 84% rename from feeds/mediatek-sdk/mt76/patches/0013-wifi-mt76-add-sanity-check-to-prevent-kernel-crash.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/0012-wifi-mt76-add-sanity-check-to-prevent-kernel-crash.patch index d31e838ed..034e354b5 100644 --- a/feeds/mediatek-sdk/mt76/patches/0013-wifi-mt76-add-sanity-check-to-prevent-kernel-crash.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0012-wifi-mt76-add-sanity-check-to-prevent-kernel-crash.patch @@ -1,7 +1,7 @@ -From 7298f88158863fbad0ec780f4ef64d389dd52b96 Mon Sep 17 00:00:00 2001 +From fa15f886fd427e2de3e09ef5c93743e611483adf Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Mon, 29 Jan 2024 15:33:24 +0800 -Subject: [PATCH 13/15] wifi: mt76: add sanity check to prevent kernel crash +Subject: [PATCH 12/14] wifi: mt76: add sanity check to prevent kernel crash wcid may not be initialized when mac80211 calls mt76.tx and it would lead to kernel crash. @@ -12,7 +12,7 @@ Signed-off-by: Peter Chiu 1 file changed, 8 insertions(+) diff --git a/tx.c b/tx.c -index 1809b032..4596b367 100644 +index 5cf6ede..ab42f69 100644 --- a/tx.c +++ b/tx.c @@ -345,6 +345,14 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, diff --git a/feeds/mediatek-sdk/mt76/patches/0015-wifi-mt76-mt7915-limit-per-band-token-count.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0013-wifi-mt76-mt7915-limit-per-band-token-count.patch similarity index 84% rename from feeds/mediatek-sdk/mt76/patches/0015-wifi-mt76-mt7915-limit-per-band-token-count.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/0013-wifi-mt76-mt7915-limit-per-band-token-count.patch index c9e0b05e6..ee848e6a4 100644 --- a/feeds/mediatek-sdk/mt76/patches/0015-wifi-mt76-mt7915-limit-per-band-token-count.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0013-wifi-mt76-mt7915-limit-per-band-token-count.patch @@ -1,28 +1,18 @@ -From 47ea10a75083acf3af7826124ef0166f2debc5c0 Mon Sep 17 00:00:00 2001 +From ef9b267adeee3803ae8ee3073d2ebcbd3e1c95f9 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Mon, 29 Jan 2024 15:33:24 +0800 -Subject: [PATCH 15/15] wifi: mt76: mt7915: limit per-band token count +Subject: [PATCH] wifi: mt76: mt7915: limit per-band token count Add a threshold for per-band token count to prevent a band from interfering with the other band. Signed-off-by: Peter Chiu ---- - mt76.h | 8 +++++++- - mt7915/init.c | 3 +++ - mt7915/mac.c | 3 ++- - mt7921/pci_mac.c | 2 +- - mt7925/pci_mac.c | 2 +- - mt7996/init.c | 5 +++++ - mt7996/mac.c | 3 ++- - tx.c | 20 ++++++++++++++++++-- - 8 files changed, 39 insertions(+), 7 deletions(-) diff --git a/mt76.h b/mt76.h -index 03116ffe..b1f49973 100644 +index ee14425d..b83456b4 100644 --- a/mt76.h +++ b/mt76.h -@@ -402,6 +402,8 @@ struct mt76_txwi_cache { +@@ -407,6 +407,8 @@ struct mt76_txwi_cache { struct list_head list; dma_addr_t dma_addr; @@ -31,7 +21,7 @@ index 03116ffe..b1f49973 100644 union { struct sk_buff *skb; void *ptr; -@@ -814,6 +816,7 @@ struct mt76_phy { +@@ -819,6 +821,7 @@ struct mt76_phy { bool al; u8 pin; } leds; @@ -39,7 +29,7 @@ index 03116ffe..b1f49973 100644 }; struct mt76_dev { -@@ -867,6 +870,8 @@ struct mt76_dev { +@@ -872,6 +875,8 @@ struct mt76_dev { u16 wed_token_count; u16 token_count; u16 token_size; @@ -48,7 +38,7 @@ index 03116ffe..b1f49973 100644 spinlock_t rx_token_lock; struct idr rx_token; -@@ -1657,7 +1662,8 @@ static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q) +@@ -1662,7 +1667,8 @@ static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q) struct mt76_txwi_cache * mt76_token_release(struct mt76_dev *dev, int token, bool *wake); @@ -58,11 +48,24 @@ index 03116ffe..b1f49973 100644 void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked); struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token); int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr, +diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c +index 630c6402..a92c261d 100644 +--- a/mt76_connac_mac.c ++++ b/mt76_connac_mac.c +@@ -1178,6 +1178,8 @@ void mt76_connac2_tx_token_put(struct mt76_dev *dev) + idr_for_each_entry(&dev->token, txwi, id) { + mt76_connac2_txwi_free(dev, txwi, NULL, NULL); + dev->token_count--; ++ if (dev->num_phy > 1 && dev->phys[txwi->phy_idx]) ++ dev->phys[txwi->phy_idx]->tokens--; + } + spin_unlock_bh(&dev->token_lock); + idr_destroy(&dev->token); diff --git a/mt7915/init.c b/mt7915/init.c -index 2fc1f3ce..6ba98433 100644 +index f81a2f2f..3ec9eab7 100644 --- a/mt7915/init.c +++ b/mt7915/init.c -@@ -1221,6 +1221,8 @@ int mt7915_register_device(struct mt7915_dev *dev) +@@ -1225,6 +1225,8 @@ int mt7915_register_device(struct mt7915_dev *dev) dev->dbdc_support = mt7915_band_config(dev); @@ -71,7 +74,7 @@ index 2fc1f3ce..6ba98433 100644 phy2 = mt7915_alloc_ext_phy(dev); if (IS_ERR(phy2)) return PTR_ERR(phy2); -@@ -1253,6 +1255,7 @@ int mt7915_register_device(struct mt7915_dev *dev) +@@ -1257,6 +1259,7 @@ int mt7915_register_device(struct mt7915_dev *dev) } dev->recovery.hw_init_done = true; @@ -80,7 +83,7 @@ index 2fc1f3ce..6ba98433 100644 ret = mt7915_init_debugfs(&dev->phy); if (ret) diff --git a/mt7915/mac.c b/mt7915/mac.c -index faa5ed36..8e98e5ae 100644 +index a5d0b096..4604a682 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c @@ -738,6 +738,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -101,7 +104,7 @@ index faa5ed36..8e98e5ae 100644 return id; diff --git a/mt7921/pci_mac.c b/mt7921/pci_mac.c -index c866144f..3282507a 100644 +index 031ba9aa..4c69c55c 100644 --- a/mt7921/pci_mac.c +++ b/mt7921/pci_mac.c @@ -27,7 +27,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -157,7 +160,7 @@ index 9aa97e4a..7549a108 100644 if (ret) goto error; diff --git a/mt7996/mac.c b/mt7996/mac.c -index 0384fb05..feb5299d 100644 +index bc7111a7..aa19120b 100644 --- a/mt7996/mac.c +++ b/mt7996/mac.c @@ -922,6 +922,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -178,7 +181,7 @@ index 0384fb05..feb5299d 100644 return id; diff --git a/tx.c b/tx.c -index 4596b367..b602d9d7 100644 +index ab42f69b..0fdf7d83 100644 --- a/tx.c +++ b/tx.c @@ -825,16 +825,30 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked) diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0014-wifi-mt76-mt7915-update-power-on-sequence.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0014-wifi-mt76-mt7915-update-power-on-sequence.patch new file mode 100644 index 000000000..4c2f703b2 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0014-wifi-mt76-mt7915-update-power-on-sequence.patch @@ -0,0 +1,147 @@ +From c3b0d9d6116df31a11d18e42e7227bf516c104f9 Mon Sep 17 00:00:00 2001 +From: Peter Chiu +Date: Thu, 14 Mar 2024 17:55:12 +0800 +Subject: [PATCH 14/14] wifi: mt76: mt7915: update power on sequence + +Update power on sequence to prevent unexpected behavior. + +Signed-off-by: Peter Chiu +--- + mt7915/mt7915.h | 1 + + mt7915/regs.h | 2 ++ + mt7915/soc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 48 insertions(+), 2 deletions(-) + +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 89156f3..74cd8ca 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -329,6 +329,7 @@ struct mt7915_dev { + + bool wmm_pbc_enable; + struct work_struct wmm_pbc_work; ++ u32 adie_type; + }; + + enum { +diff --git a/mt7915/regs.h b/mt7915/regs.h +index 7515b23..3452a7e 100644 +--- a/mt7915/regs.h ++++ b/mt7915/regs.h +@@ -775,6 +775,7 @@ enum offs_rev { + #define MT_TOP_RGU_SYSRAM_PDN (MT_TOP_RGU_BASE + 0x050) + #define MT_TOP_RGU_SYSRAM_SLP (MT_TOP_RGU_BASE + 0x054) + #define MT_TOP_WFSYS_PWR (MT_TOP_RGU_BASE + 0x010) ++#define MT_TOP_BGFYS_PWR (MT_TOP_RGU_BASE + 0x020) + #define MT_TOP_PWR_EN_MASK BIT(7) + #define MT_TOP_PWR_ACK_MASK BIT(6) + #define MT_TOP_PWR_KEY_MASK GENMASK(31, 16) +@@ -886,6 +887,7 @@ enum offs_rev { + #define MT_ADIE_SLP_CTRL(_band, ofs) (MT_ADIE_SLP_CTRL_BASE(_band) + (ofs)) + + #define MT_ADIE_SLP_CTRL_CK0(_band) MT_ADIE_SLP_CTRL(_band, 0x120) ++#define MT_ADIE_SLP_CTRL_CK1(_band) MT_ADIE_SLP_CTRL(_band, 0x124) + + /* ADIE */ + #define MT_ADIE_CHIP_ID 0x02c +diff --git a/mt7915/soc.c b/mt7915/soc.c +index 92d8d71..bb3468a 100644 +--- a/mt7915/soc.c ++++ b/mt7915/soc.c +@@ -260,6 +260,7 @@ static int mt7986_wmac_consys_lockup(struct mt7915_dev *dev, bool enable) + MT_INFRACFG_TX_EN_MASK, + FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable)); + ++ usleep_range(1000, 2000); + return 0; + } + +@@ -844,6 +845,10 @@ static void mt7986_wmac_subsys_setting(struct mt7915_dev *dev) + MT_CONN_INFRA_OSC_STB_TIME_MASK, 0x80706); + + /* prevent subsys from power on/of in a short time interval */ ++ mt76_rmw(dev, MT_TOP_BGFYS_PWR, ++ MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK, ++ (0x42540000)); ++ + mt76_rmw(dev, MT_TOP_WFSYS_PWR, + MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK, + MT_TOP_PWR_KEY); +@@ -914,7 +919,7 @@ static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type) + + read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, +- dev, MT_ADIE_SLP_CTRL_CK0(0)); ++ dev, MT_ADIE_SLP_CTRL_CK0(1)); + } + mt76_wmac_spi_unlock(dev); + +@@ -1154,12 +1159,14 @@ int mt7986_wmac_enable(struct mt7915_dev *dev) + if (ret) + return ret; + ++ dev->adie_type = adie_type; ++ + return mt7986_wmac_sku_update(dev, adie_type); + } + + void mt7986_wmac_disable(struct mt7915_dev *dev) + { +- u32 cur; ++ u32 cur, i; + + mt7986_wmac_top_wfsys_wakeup(dev, true); + +@@ -1178,6 +1185,20 @@ void mt7986_wmac_disable(struct mt7915_dev *dev) + mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_MCU_BPLL_CFG_MASK, 0x2); + mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_WPLL_CFG_MASK, 0x2); + ++ /* Disable adie top clock */ ++ mt76_wmac_spi_lock(dev); ++ for (i = 0; i < 2; i++) { ++ if (is_7975(dev, i, dev->adie_type) || is_7976(dev, i, dev->adie_type)) { ++ mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK1(i), ++ MT_SLP_CTRL_EN_MASK, 0x0); ++ ++ read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), ++ USEC_PER_MSEC, 50 * USEC_PER_MSEC, ++ false, dev, MT_ADIE_SLP_CTRL_CK1(i)); ++ } ++ } ++ mt76_wmac_spi_unlock(dev); ++ + /* Reset EMI */ + mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, + MT_CONN_INFRA_EMI_REQ_MASK, 0x1); +@@ -1189,6 +1210,28 @@ void mt7986_wmac_disable(struct mt7915_dev *dev) + MT_CONN_INFRA_INFRA_REQ_MASK, 0x0); + + mt7986_wmac_top_wfsys_wakeup(dev, false); ++ ++ mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP, ++ MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x1); ++ ++ usleep_range(1000, 1100); ++ ++ mt76_wmac_spi_lock(dev); ++ for (i = 0; i < 2; i++) { ++ if (is_7975(dev, i, dev->adie_type) || is_7976(dev, i, dev->adie_type)) { ++ mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(i), ++ MT_SLP_CTRL_EN_MASK, 0x0); ++ ++ read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), ++ USEC_PER_MSEC, 50 * USEC_PER_MSEC, ++ false, dev, MT_ADIE_SLP_CTRL_CK0(i)); ++ } ++ } ++ mt76_wmac_spi_unlock(dev); ++ ++ mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP, ++ MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x0); ++ + mt7986_wmac_consys_lockup(dev, true); + mt7986_wmac_consys_reset(dev, false); + } +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0015-wifi-mt76-mt7915-add-support-for-IEEE-802.11-fragmen.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0015-wifi-mt76-mt7915-add-support-for-IEEE-802.11-fragmen.patch new file mode 100644 index 000000000..ab924eb94 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0015-wifi-mt76-mt7915-add-support-for-IEEE-802.11-fragmen.patch @@ -0,0 +1,67 @@ +From 7b7d9e3ef08ce5526d43d657cb717b471002b087 Mon Sep 17 00:00:00 2001 +From: Benjamin Lin +Date: Wed, 3 Apr 2024 14:05:59 +0800 +Subject: [PATCH] wifi: mt76: mt7915: add support for IEEE 802.11 fragmentation + +Add fragmentation index into TXD.DW2 to support IEEE 802.11 fragmentation. + +Signed-off-by: Benjamin Lin +--- + mt76_connac2_mac.h | 7 +++++++ + mt76_connac_mac.c | 10 +++++++++- + 2 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/mt76_connac2_mac.h b/mt76_connac2_mac.h +index 5f13211..eb47653 100644 +--- a/mt76_connac2_mac.h ++++ b/mt76_connac2_mac.h +@@ -355,4 +355,11 @@ enum tx_port_idx { + MT_TX_PORT_IDX_MCU + }; + ++enum tx_frag_idx { ++ MT_TX_FRAG_NONE, ++ MT_TX_FRAG_FIRST, ++ MT_TX_FRAG_MID, ++ MT_TX_FRAG_LAST ++}; ++ + #endif /* __MT76_CONNAC2_MAC_H */ +diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c +index 630c640..d7d602a 100644 +--- a/mt76_connac_mac.c ++++ b/mt76_connac_mac.c +@@ -391,6 +391,7 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, + bool multicast = is_multicast_ether_addr(hdr->addr1); + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + __le16 fc = hdr->frame_control; ++ __le16 sc = hdr->seq_ctrl; + u8 fc_type, fc_stype; + u32 val; + +@@ -432,6 +433,13 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, + info->flags & IEEE80211_TX_CTL_USE_MINRATE) + val |= MT_TXD2_FIX_RATE; + ++ if (ieee80211_has_morefrags(fc) && ieee80211_is_first_frag(sc)) ++ val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_FIRST); ++ else if (ieee80211_has_morefrags(fc) && !ieee80211_is_first_frag(sc)) ++ val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_MID); ++ else if (!ieee80211_has_morefrags(fc) && !ieee80211_is_first_frag(sc)) ++ val |= FIELD_PREP(MT_TXD2_FRAG, MT_TX_FRAG_LAST); ++ + txwi[2] |= cpu_to_le32(val); + + if (ieee80211_is_beacon(fc)) { +@@ -440,7 +448,7 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, + } + + if (info->flags & IEEE80211_TX_CTL_INJECTED) { +- u16 seqno = le16_to_cpu(hdr->seq_ctrl); ++ u16 seqno = le16_to_cpu(sc); + + if (ieee80211_is_back_req(hdr->frame_control)) { + struct ieee80211_bar *bar; +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0016-wifi-mt76-mt7915-add-dummy-HW-offload-of-IEEE-802.11.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0016-wifi-mt76-mt7915-add-dummy-HW-offload-of-IEEE-802.11.patch new file mode 100644 index 000000000..b062d4055 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0016-wifi-mt76-mt7915-add-dummy-HW-offload-of-IEEE-802.11.patch @@ -0,0 +1,55 @@ +From 239f1a1bb8eedd9f24dd3abcb801dceac7fe7ffb Mon Sep 17 00:00:00 2001 +From: Benjamin Lin +Date: Wed, 17 Apr 2024 10:47:08 +0800 +Subject: [PATCH] wifi: mt76: mt7915: add dummy HW offload of IEEE 802.11 + fragmentation + +Currently, CONNAC2 series do not support encryption for fragmented Tx frames. +Therefore, add dummy function mt7915_set_frag_threshold() to prevent SW IEEE 802.11 fragmentation. + +Signed-off-by: Benjamin Lin +--- + mt7915/init.c | 1 + + mt7915/main.c | 7 +++++++ + 2 files changed, 8 insertions(+) + +diff --git a/mt7915/init.c b/mt7915/init.c +index 3ec9eab..19a68c5 100644 +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -398,6 +398,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy) + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); + ieee80211_hw_set(hw, WANT_MONITOR_VIF); ++ ieee80211_hw_set(hw, SUPPORTS_TX_FRAG); + + hw->max_tx_fragments = 4; + +diff --git a/mt7915/main.c b/mt7915/main.c +index 9eeca39..5224d83 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -1614,6 +1614,12 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw, + mutex_unlock(&dev->mt76.mutex); + } + ++static int ++mt7915_set_frag_threshold(struct ieee80211_hw *hw, u32 val) ++{ ++ return 0; ++} ++ + static int + mt7915_set_radar_background(struct ieee80211_hw *hw, + struct cfg80211_chan_def *chandef) +@@ -1741,6 +1747,7 @@ const struct ieee80211_ops mt7915_ops = { + .sta_set_decap_offload = mt7915_sta_set_decap_offload, + .add_twt_setup = mt7915_mac_add_twt_setup, + .twt_teardown_request = mt7915_twt_teardown_request, ++ .set_frag_threshold = mt7915_set_frag_threshold, + CFG80211_TESTMODE_CMD(mt76_testmode_cmd) + CFG80211_TESTMODE_DUMP(mt76_testmode_dump) + #ifdef CONFIG_MAC80211_DEBUGFS +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0016-wifi-mt76-mt7915-fix-rx-filter-setting-for-bfee-func.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0016-wifi-mt76-mt7915-fix-rx-filter-setting-for-bfee-func.patch new file mode 100644 index 000000000..f223d89e0 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0016-wifi-mt76-mt7915-fix-rx-filter-setting-for-bfee-func.patch @@ -0,0 +1,32 @@ +From 1a9953c39a08407607e5ef9d2ca4fefa77b5eaea Mon Sep 17 00:00:00 2001 +From: Howard Hsu +Date: Fri, 12 Apr 2024 11:33:08 +0800 +Subject: [PATCH] wifi: mt76: mt7915: fix rx filter setting for bfee + functionality + +Fix rx filter setting to prevent dropping NDPA frames. Without this +commit, bfee functionality may behave abnormally. + +Fixes: e57b7901469f ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets") +Signed-off-by: Howard Hsu +--- + mt7915/main.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/mt7915/main.c b/mt7915/main.c +index 9eeca39..6674c27 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -564,8 +564,7 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw, + + MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | + MT_WF_RFCR_DROP_RTS | +- MT_WF_RFCR_DROP_CTL_RSV | +- MT_WF_RFCR_DROP_NDPA); ++ MT_WF_RFCR_DROP_CTL_RSV); + + *total_flags = flags; + rxfilter = phy->rxfilter; +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0017-wifi-mt76-mt7915-fix-inconsistent-QoS-mapping-betwee.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0017-wifi-mt76-mt7915-fix-inconsistent-QoS-mapping-betwee.patch new file mode 100644 index 000000000..d4d3d2e82 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0017-wifi-mt76-mt7915-fix-inconsistent-QoS-mapping-betwee.patch @@ -0,0 +1,103 @@ +From 9c6e5082d5552ac2cefe5b4857da4b29b0c76685 Mon Sep 17 00:00:00 2001 +From: Benjamin Lin +Date: Thu, 25 Apr 2024 17:17:13 +0800 +Subject: [PATCH] wifi: mt76: mt7915: fix inconsistent QoS mapping between SW + and HW + +The mapping from IP DSCP to IEEE 802.11 user priority may be customized. +Therefore, driver needs to pass the mapping to HW, so that the QoS type of traffic can be mapped in a consistent manner for both SW and HW paths. + +Signed-off-by: Benjamin Lin +--- + mt76_connac_mcu.h | 1 + + mt7915/main.c | 3 +++ + mt7915/mcu.c | 37 +++++++++++++++++++++++++++++++++++++ + mt7915/mt7915.h | 1 + + 4 files changed, 42 insertions(+) + +diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h +index 1dd8244..0936c1c 100644 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1236,6 +1236,7 @@ enum { + MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, + MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, + MCU_EXT_CMD_PHY_STAT_INFO = 0xad, ++ MCU_EXT_CMD_SET_QOS_MAP = 0xb4, + }; + + enum { +diff --git a/mt7915/main.c b/mt7915/main.c +index 5ed84bc..26f9a5a 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -646,6 +646,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, + } + } + ++ if (changed & BSS_CHANGED_QOS) ++ mt7915_mcu_set_qos_map(dev, vif); ++ + /* ensure that enable txcmd_mode after bss_info */ + if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) + mt7915_mcu_set_tx(dev, vif); +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index 446c512..3d7fc6d 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -4212,3 +4212,40 @@ int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set) + + return 0; + } ++ ++int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif) ++{ ++#define IP_DSCP_NUM 64 ++ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; ++ struct { ++ u8 bss_idx; ++ u8 qos_map_enable; ++ u8 __rsv[2]; ++ s8 qos_map[IP_DSCP_NUM]; ++ } __packed req = { ++ .bss_idx = mvif->mt76.idx, ++ .qos_map_enable = false, ++ }; ++ struct cfg80211_qos_map *qos_map; ++ ++ rcu_read_lock(); ++ qos_map = ieee80211_get_qos_map(vif); ++ if (qos_map) { ++ struct cfg80211_dscp_range *dscp_range = qos_map->up; ++ s8 up; ++ ++ req.qos_map_enable = true; ++ for (up = 0; up < IEEE80211_NUM_UPS; ++up) { ++ u8 low = dscp_range[up].low, high = dscp_range[up].high; ++ ++ if (low >= IP_DSCP_NUM || high >= IP_DSCP_NUM || low > high) ++ continue; ++ ++ memset(req.qos_map + low, up, high - low + 1); ++ } ++ } ++ rcu_read_unlock(); ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(SET_QOS_MAP), &req, ++ sizeof(req), true); ++} +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 74cd8ca..66d87d7 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -521,6 +521,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); + void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb); + void mt7915_mcu_exit(struct mt7915_dev *dev); + void mt7915_mcu_wmm_pbc_work(struct work_struct *work); ++int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif); + + static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev) + { +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/0999-wifi-mt76-mt7915-build-pass-for-Linux-Kernel-5.4-fix.patch b/feeds/mediatek-sdk/mt76/mt76/patches/0999-wifi-mt76-mt7915-build-pass-for-Linux-Kernel-5.4-fix.patch new file mode 100644 index 000000000..60b0e2da9 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/0999-wifi-mt76-mt7915-build-pass-for-Linux-Kernel-5.4-fix.patch @@ -0,0 +1,882 @@ +From 4300f1a6eb91cc3291d73e415ae32cbd120f6bc6 Mon Sep 17 00:00:00 2001 +From: Evelyn Tsai +Date: Sat, 1 Apr 2023 08:18:17 +0800 +Subject: [PATCH 0999/1053] wifi: mt76: mt7915: build pass for Linux Kernel 5.4 + fixes + +--- + debugfs.c | 2 ++ + dma.c | 73 ++++++++++++++++++++++++----------------------- + dma.h | 3 +- + eeprom.c | 8 +++++- + mac80211.c | 56 ------------------------------------ + mcu.c | 1 + + mt76.h | 27 +----------------- + mt7615/mcu.c | 1 + + mt76_connac.h | 2 -- + mt76_connac_mcu.c | 47 +----------------------------- + mt76_connac_mcu.h | 4 --- + mt7915/main.c | 25 +++++++--------- + mt7915/mcu.c | 1 + + usb.c | 43 ++++++++++++++-------------- + wed.c | 62 +++++++++++++++++++++++++--------------- + 15 files changed, 123 insertions(+), 232 deletions(-) + +diff --git a/debugfs.c b/debugfs.c +index c4649ba..1c8328d 100644 +--- a/debugfs.c ++++ b/debugfs.c +@@ -33,8 +33,10 @@ mt76_napi_threaded_set(void *data, u64 val) + if (!mt76_is_mmio(dev)) + return -EOPNOTSUPP; + ++#if 0 /* disable in backport 5.15 */ + if (dev->napi_dev.threaded != val) + return dev_set_threaded(&dev->napi_dev, val); ++#endif + + return 0; + } +diff --git a/dma.c b/dma.c +index f4f88c4..ccdd564 100644 +--- a/dma.c ++++ b/dma.c +@@ -178,7 +178,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev) + local_bh_disable(); + while ((t = __mt76_get_rxwi(dev)) != NULL) { + if (t->ptr) +- mt76_put_page_pool_buf(t->ptr, false); ++ skb_free_frag(t->ptr); + kfree(t); + } + local_bh_enable(); +@@ -450,9 +450,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, + if (!t) + return NULL; + +- dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, +- SKB_WITH_OVERHEAD(q->buf_size), +- page_pool_get_dma_dir(q->page_pool)); ++ dma_unmap_single(dev->dma_dev, t->dma_addr, ++ SKB_WITH_OVERHEAD(q->buf_size), ++ DMA_FROM_DEVICE); + + buf = t->ptr; + t->dma_addr = 0; +@@ -462,9 +462,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, + if (drop) + *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP); + } else { +- dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0], +- SKB_WITH_OVERHEAD(q->buf_size), +- page_pool_get_dma_dir(q->page_pool)); ++ dma_unmap_single(dev->dma_dev, e->dma_addr[0], ++ SKB_WITH_OVERHEAD(q->buf_size), ++ DMA_FROM_DEVICE); + } + + done: +@@ -631,11 +631,11 @@ free_skb: + return ret; + } + +-int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, +- bool allow_direct) ++int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) + { + int len = SKB_WITH_OVERHEAD(q->buf_size); +- int frames = 0; ++ int frames = 0, offset = q->buf_offset; ++ dma_addr_t addr; + + if (!q->ndesc) + return 0; +@@ -643,30 +643,30 @@ int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, + spin_lock_bh(&q->lock); + + while (q->queued < q->ndesc - 1) { +- struct mt76_queue_buf qbuf = {}; +- enum dma_data_direction dir; +- dma_addr_t addr; +- int offset; ++ struct mt76_queue_buf qbuf; + void *buf = NULL; + + if (mt76_queue_is_wed_rro_ind(q)) + goto done; + +- buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); ++ buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC); + if (!buf) + break; + +- addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset; +- dir = page_pool_get_dma_dir(q->page_pool); +- dma_sync_single_for_device(dev->dma_dev, addr, len, dir); ++ addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE); ++ if (unlikely(dma_mapping_error(dev->dma_dev, addr))) { ++ skb_free_frag(buf); ++ break; ++ } + +- qbuf.addr = addr + q->buf_offset; ++ qbuf.addr = addr + offset; + done: +- qbuf.len = len - q->buf_offset; ++ qbuf.len = len - offset; + qbuf.skip_unmap = false; + if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) { +- mt76_put_page_pool_buf(buf, allow_direct); +- break; ++ dma_unmap_single(dev->dma_dev, addr, len, ++ DMA_FROM_DEVICE); ++ skb_free_frag(buf); + } + frames++; + } +@@ -719,10 +719,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, + if (!q->entry) + return -ENOMEM; + +- ret = mt76_create_page_pool(dev, q); +- if (ret) +- return ret; +- + ret = mt76_wed_dma_setup(dev, q, false); + if (ret) + return ret; +@@ -741,6 +737,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, + static void + mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) + { ++ struct page *page; + void *buf; + bool more; + +@@ -756,7 +753,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) + break; + + if (!mt76_queue_is_wed_rro(q)) +- mt76_put_page_pool_buf(buf, false); ++ skb_free_frag(buf); + } while (1); + + spin_lock_bh(&q->lock); +@@ -766,6 +763,13 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) + } + + spin_unlock_bh(&q->lock); ++ ++ if (!q->rx_page.va) ++ return; ++ ++ page = virt_to_page(q->rx_page.va); ++ __page_frag_cache_drain(page, q->rx_page.pagecnt_bias); ++ memset(&q->rx_page, 0, sizeof(q->rx_page)); + } + + static void +@@ -796,7 +800,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) + return; + + mt76_dma_sync_idx(dev, q); +- mt76_dma_rx_fill(dev, q, false); ++ mt76_dma_rx_fill(dev, q); + } + + static void +@@ -813,7 +817,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, + + skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size); + } else { +- mt76_put_page_pool_buf(data, allow_direct); ++ skb_free_frag(data); + } + + if (more) +@@ -883,12 +887,11 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) + !(dev->drv->rx_check(dev, data, len))) + goto free_frag; + +- skb = napi_build_skb(data, q->buf_size); ++ skb = build_skb(data, q->buf_size); + if (!skb) + goto free_frag; + + skb_reserve(skb, q->buf_offset); +- skb_mark_for_recycle(skb); + + *(u32 *)skb->cb = info; + +@@ -904,10 +907,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) + continue; + + free_frag: +- mt76_put_page_pool_buf(data, allow_direct); ++ skb_free_frag(data); + } + +- mt76_dma_rx_fill(dev, q, true); ++ mt76_dma_rx_fill(dev, q); + return done; + } + +@@ -952,7 +955,7 @@ mt76_dma_init(struct mt76_dev *dev, + + mt76_for_each_q_rx(dev, i) { + netif_napi_add(&dev->napi_dev, &dev->napi[i], poll); +- mt76_dma_rx_fill(dev, &dev->q_rx[i], false); ++ mt76_dma_rx_fill(dev, &dev->q_rx[i]); + napi_enable(&dev->napi[i]); + } + +@@ -1007,8 +1010,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev) + + netif_napi_del(&dev->napi[i]); + mt76_dma_rx_cleanup(dev, q); +- +- page_pool_destroy(q->page_pool); + } + + if (mtk_wed_device_active(&dev->mmio.wed)) +diff --git a/dma.h b/dma.h +index 1de5a2b..619dc0f 100644 +--- a/dma.h ++++ b/dma.h +@@ -79,8 +79,7 @@ enum mt76_dma_wed_ind_reason { + int mt76_dma_rx_poll(struct napi_struct *napi, int budget); + void mt76_dma_attach(struct mt76_dev *dev); + void mt76_dma_cleanup(struct mt76_dev *dev); +-int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, +- bool allow_direct); ++int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q); + void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q, + bool reset_idx); + void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q); +diff --git a/eeprom.c b/eeprom.c +index ecd09c0..a267397 100644 +--- a/eeprom.c ++++ b/eeprom.c +@@ -163,9 +163,15 @@ void + mt76_eeprom_override(struct mt76_phy *phy) + { + struct mt76_dev *dev = phy->dev; ++#ifdef CONFIG_OF + struct device_node *np = dev->dev->of_node; ++ const u8 *mac = NULL; + +- of_get_mac_address(np, phy->macaddr); ++ if (np) ++ mac = of_get_mac_address(np); ++ if (!IS_ERR_OR_NULL(mac)) ++ ether_addr_copy(phy->macaddr, mac); ++#endif + + if (!is_valid_ether_addr(phy->macaddr)) { + eth_random_addr(phy->macaddr); +diff --git a/mac80211.c b/mac80211.c +index bc20f60..b30a74e 100644 +--- a/mac80211.c ++++ b/mac80211.c +@@ -577,47 +577,6 @@ void mt76_unregister_phy(struct mt76_phy *phy) + } + EXPORT_SYMBOL_GPL(mt76_unregister_phy); + +-int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q) +-{ +- struct page_pool_params pp_params = { +- .order = 0, +- .flags = PP_FLAG_PAGE_FRAG, +- .nid = NUMA_NO_NODE, +- .dev = dev->dma_dev, +- }; +- int idx = q - dev->q_rx; +- +- switch (idx) { +- case MT_RXQ_MAIN: +- case MT_RXQ_BAND1: +- case MT_RXQ_BAND2: +- pp_params.pool_size = 256; +- break; +- default: +- pp_params.pool_size = 16; +- break; +- } +- +- if (mt76_is_mmio(dev)) { +- /* rely on page_pool for DMA mapping */ +- pp_params.flags |= PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; +- pp_params.dma_dir = DMA_FROM_DEVICE; +- pp_params.max_len = PAGE_SIZE; +- pp_params.offset = 0; +- } +- +- q->page_pool = page_pool_create(&pp_params); +- if (IS_ERR(q->page_pool)) { +- int err = PTR_ERR(q->page_pool); +- +- q->page_pool = NULL; +- return err; +- } +- +- return 0; +-} +-EXPORT_SYMBOL_GPL(mt76_create_page_pool); +- + struct mt76_dev * + mt76_alloc_device(struct device *pdev, unsigned int size, + const struct ieee80211_ops *ops, +@@ -1817,21 +1776,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, + } + EXPORT_SYMBOL_GPL(mt76_ethtool_worker); + +-void mt76_ethtool_page_pool_stats(struct mt76_dev *dev, u64 *data, int *index) +-{ +-#ifdef CONFIG_PAGE_POOL_STATS +- struct page_pool_stats stats = {}; +- int i; +- +- mt76_for_each_q_rx(dev, i) +- page_pool_get_stats(dev->q_rx[i].page_pool, &stats); +- +- page_pool_ethtool_stats_get(data, &stats); +- *index += page_pool_ethtool_stats_get_count(); +-#endif +-} +-EXPORT_SYMBOL_GPL(mt76_ethtool_page_pool_stats); +- + enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy) + { + struct ieee80211_hw *hw = phy->hw; +diff --git a/mcu.c b/mcu.c +index a8cafa3..fa4b054 100644 +--- a/mcu.c ++++ b/mcu.c +@@ -4,6 +4,7 @@ + */ + + #include "mt76.h" ++#include + + struct sk_buff * + __mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, +diff --git a/mt76.h b/mt76.h +index b83456b..a07c7df 100644 +--- a/mt76.h ++++ b/mt76.h +@@ -15,11 +15,6 @@ + #include + #include + #include +-#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0) +-#include +-#else +-#include +-#endif + #include "util.h" + #include "testmode.h" + +@@ -238,7 +233,7 @@ struct mt76_queue { + + dma_addr_t desc_dma; + struct sk_buff *rx_head; +- struct page_pool *page_pool; ++ struct page_frag_cache rx_page; + }; + + struct mt76_mcu_ops { +@@ -1527,7 +1522,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, + return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout); + } + +-void mt76_ethtool_page_pool_stats(struct mt76_dev *dev, u64 *data, int *index); + void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, + struct mt76_sta_stats *stats, bool eht); + int mt76_skb_adjust_pad(struct sk_buff *skb, int pad); +@@ -1673,25 +1667,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked); + struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token); + int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr, + struct mt76_txwi_cache *r, dma_addr_t phys); +-int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q); +-static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct) +-{ +- struct page *page = virt_to_head_page(buf); +- +- page_pool_put_full_page(page->pp, page, allow_direct); +-} +- +-static inline void * +-mt76_get_page_pool_buf(struct mt76_queue *q, u32 *offset, u32 size) +-{ +- struct page *page; +- +- page = page_pool_dev_alloc_frag(q->page_pool, offset, size); +- if (!page) +- return NULL; +- +- return page_address(page) + *offset; +-} + + static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked) + { +diff --git a/mt7615/mcu.c b/mt7615/mcu.c +index ae34d01..c9444c6 100644 +--- a/mt7615/mcu.c ++++ b/mt7615/mcu.c +@@ -10,6 +10,7 @@ + #include "mcu.h" + #include "mac.h" + #include "eeprom.h" ++#include + + static bool prefer_offload_fw = true; + module_param(prefer_offload_fw, bool, 0644); +diff --git a/mt76_connac.h b/mt76_connac.h +index 4871857..8e7068c 100644 +--- a/mt76_connac.h ++++ b/mt76_connac.h +@@ -56,7 +56,6 @@ enum { + CMD_CBW_10MHZ, + CMD_CBW_5MHZ, + CMD_CBW_8080MHZ, +- CMD_CBW_320MHZ, + + CMD_HE_MCS_BW80 = 0, + CMD_HE_MCS_BW160, +@@ -292,7 +291,6 @@ static inline u8 mt76_connac_chan_bw(struct cfg80211_chan_def *chandef) + [NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ, + [NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ, + [NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ, +- [NL80211_CHAN_WIDTH_320] = CMD_CBW_320MHZ, + }; + + if (chandef->width >= ARRAY_SIZE(width_to_bw)) +diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c +index 1ea9798..a8f097d 100644 +--- a/mt76_connac_mcu.c ++++ b/mt76_connac_mcu.c +@@ -4,6 +4,7 @@ + #include + #include "mt76_connac2_mac.h" + #include "mt76_connac_mcu.h" ++#include + + int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option) + { +@@ -1357,40 +1358,6 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, + } + EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode); + +-u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif, +- enum nl80211_band band) +-{ +- const struct ieee80211_sta_eht_cap *eht_cap; +- struct ieee80211_supported_band *sband; +- u8 mode = 0; +- +- if (band == NL80211_BAND_6GHZ) +- mode |= PHY_MODE_AX_6G; +- +- sband = phy->hw->wiphy->bands[band]; +- eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type); +- +- if (!eht_cap || !eht_cap->has_eht || !vif->bss_conf.eht_support) +- return mode; +- +- switch (band) { +- case NL80211_BAND_6GHZ: +- mode |= PHY_MODE_BE_6G; +- break; +- case NL80211_BAND_5GHZ: +- mode |= PHY_MODE_BE_5G; +- break; +- case NL80211_BAND_2GHZ: +- mode |= PHY_MODE_BE_24G; +- break; +- default: +- break; +- } +- +- return mode; +-} +-EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_ext); +- + const struct ieee80211_sta_he_cap * + mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif) + { +@@ -1406,18 +1373,6 @@ mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif) + } + EXPORT_SYMBOL_GPL(mt76_connac_get_he_phy_cap); + +-const struct ieee80211_sta_eht_cap * +-mt76_connac_get_eht_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif) +-{ +- enum nl80211_band band = phy->chandef.chan->band; +- struct ieee80211_supported_band *sband; +- +- sband = phy->hw->wiphy->bands[band]; +- +- return ieee80211_get_eht_iftype_cap(sband, vif->type); +-} +-EXPORT_SYMBOL_GPL(mt76_connac_get_eht_phy_cap); +- + #define DEFAULT_HE_PE_DURATION 4 + #define DEFAULT_HE_DURATION_RTS_THRES 1023 + static void +diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h +index 1dd8244..61ca241 100644 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1984,12 +1984,8 @@ void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val); + + const struct ieee80211_sta_he_cap * + mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif); +-const struct ieee80211_sta_eht_cap * +-mt76_connac_get_eht_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif); + u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif, + enum nl80211_band band, struct ieee80211_sta *sta); +-u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif, +- enum nl80211_band band); + + int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct mt76_connac_sta_key_conf *sta_key_conf, +diff --git a/mt7915/main.c b/mt7915/main.c +index 9eeca39..407da07 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -1438,22 +1438,20 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 sset, u8 *data) + { +- if (sset != ETH_SS_STATS) +- return; ++ if (sset == ETH_SS_STATS) ++ memcpy(data, *mt7915_gstrings_stats, ++ sizeof(mt7915_gstrings_stats)); + +- memcpy(data, mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats)); +- data += sizeof(mt7915_gstrings_stats); +- page_pool_ethtool_stats_get_strings(data); + } + + static + int mt7915_get_et_sset_count(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int sset) + { +- if (sset != ETH_SS_STATS) +- return 0; ++ if (sset == ETH_SS_STATS) ++ return MT7915_SSTATS_LEN; + +- return MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count(); ++ return 0; + } + + static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) +@@ -1481,7 +1479,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, + .idx = mvif->mt76.idx, + }; + /* See mt7915_ampdu_stat_read_phy, etc */ +- int i, ei = 0, stats_size; ++ int i, ei = 0; + + mutex_lock(&dev->mt76.mutex); + +@@ -1593,12 +1591,9 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, + return; + + ei += wi.worker_stat_count; +- +- mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei); +- +- stats_size = MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count(); +- if (ei != stats_size) +- dev_err(dev->mt76.dev, "ei: %d size: %d", ei, stats_size); ++ if (ei != MT7915_SSTATS_LEN) ++ dev_err(dev->mt76.dev, "ei: %d MT7915_SSTATS_LEN: %d", ++ ei, (int)MT7915_SSTATS_LEN); + } + + static void +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index 446c512..8f6bc6e 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -6,6 +6,7 @@ + #include "mcu.h" + #include "mac.h" + #include "eeprom.h" ++#include + + #define fw_name(_dev, name, ...) ({ \ + char *_fw; \ +diff --git a/usb.c b/usb.c +index dc690d1..058f2d1 100644 +--- a/usb.c ++++ b/usb.c +@@ -319,27 +319,29 @@ mt76u_set_endpoints(struct usb_interface *intf, + + static int + mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb, +- int nsgs) ++ int nsgs, gfp_t gfp) + { + int i; + + for (i = 0; i < nsgs; i++) { ++ struct page *page; + void *data; + int offset; + +- data = mt76_get_page_pool_buf(q, &offset, q->buf_size); ++ data = page_frag_alloc(&q->rx_page, q->buf_size, gfp); + if (!data) + break; + +- sg_set_page(&urb->sg[i], virt_to_head_page(data), q->buf_size, +- offset); ++ page = virt_to_head_page(data); ++ offset = data - page_address(page); ++ sg_set_page(&urb->sg[i], page, q->buf_size, offset); + } + + if (i < nsgs) { + int j; + + for (j = nsgs; j < urb->num_sgs; j++) +- mt76_put_page_pool_buf(sg_virt(&urb->sg[j]), false); ++ skb_free_frag(sg_virt(&urb->sg[j])); + urb->num_sgs = i; + } + +@@ -352,16 +354,15 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb, + + static int + mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, +- struct urb *urb, int nsgs) ++ struct urb *urb, int nsgs, gfp_t gfp) + { + enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN]; +- int offset; + + if (qid == MT_RXQ_MAIN && dev->usb.sg_en) +- return mt76u_fill_rx_sg(dev, q, urb, nsgs); ++ return mt76u_fill_rx_sg(dev, q, urb, nsgs, gfp); + + urb->transfer_buffer_length = q->buf_size; +- urb->transfer_buffer = mt76_get_page_pool_buf(q, &offset, q->buf_size); ++ urb->transfer_buffer = page_frag_alloc(&q->rx_page, q->buf_size, gfp); + + return urb->transfer_buffer ? 0 : -ENOMEM; + } +@@ -399,7 +400,7 @@ mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue *q, + if (err) + return err; + +- return mt76u_refill_rx(dev, q, e->urb, sg_size); ++ return mt76u_refill_rx(dev, q, e->urb, sg_size, GFP_KERNEL); + } + + static void mt76u_urb_free(struct urb *urb) +@@ -407,10 +408,10 @@ static void mt76u_urb_free(struct urb *urb) + int i; + + for (i = 0; i < urb->num_sgs; i++) +- mt76_put_page_pool_buf(sg_virt(&urb->sg[i]), false); ++ skb_free_frag(sg_virt(&urb->sg[i])); + + if (urb->transfer_buffer) +- mt76_put_page_pool_buf(urb->transfer_buffer, false); ++ skb_free_frag(urb->transfer_buffer); + + usb_free_urb(urb); + } +@@ -546,8 +547,6 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb, + len -= data_len; + nsgs++; + } +- +- skb_mark_for_recycle(skb); + dev->drv->rx_skb(dev, MT_RXQ_MAIN, skb, NULL); + + return nsgs; +@@ -613,7 +612,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) + + count = mt76u_process_rx_entry(dev, urb, q->buf_size); + if (count > 0) { +- err = mt76u_refill_rx(dev, q, urb, count); ++ err = mt76u_refill_rx(dev, q, urb, count, GFP_ATOMIC); + if (err < 0) + break; + } +@@ -664,10 +663,6 @@ mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) + struct mt76_queue *q = &dev->q_rx[qid]; + int i, err; + +- err = mt76_create_page_pool(dev, q); +- if (err) +- return err; +- + spin_lock_init(&q->lock); + q->entry = devm_kcalloc(dev->dev, + MT_NUM_RX_ENTRIES, sizeof(*q->entry), +@@ -696,6 +691,7 @@ EXPORT_SYMBOL_GPL(mt76u_alloc_mcu_queue); + static void + mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) + { ++ struct page *page; + int i; + + for (i = 0; i < q->ndesc; i++) { +@@ -705,8 +701,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) + mt76u_urb_free(q->entry[i].urb); + q->entry[i].urb = NULL; + } +- page_pool_destroy(q->page_pool); +- q->page_pool = NULL; ++ ++ if (!q->rx_page.va) ++ return; ++ ++ page = virt_to_page(q->rx_page.va); ++ __page_frag_cache_drain(page, q->rx_page.pagecnt_bias); ++ memset(&q->rx_page, 0, sizeof(q->rx_page)); + } + + static void mt76u_free_rx(struct mt76_dev *dev) +diff --git a/wed.c b/wed.c +index f89e453..f7a3f1b 100644 +--- a/wed.c ++++ b/wed.c +@@ -9,8 +9,12 @@ + void mt76_wed_release_rx_buf(struct mtk_wed_device *wed) + { + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); ++ u32 length; + int i; + ++ length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size + ++ sizeof(struct skb_shared_info)); ++ + for (i = 0; i < dev->rx_token_size; i++) { + struct mt76_txwi_cache *t; + +@@ -18,7 +22,9 @@ void mt76_wed_release_rx_buf(struct mtk_wed_device *wed) + if (!t || !t->ptr) + continue; + +- mt76_put_page_pool_buf(t->ptr, false); ++ dma_unmap_single(dev->dma_dev, t->dma_addr, ++ wed->wlan.rx_size, DMA_FROM_DEVICE); ++ __free_pages(virt_to_page(t->ptr), get_order(length)); + t->ptr = NULL; + + mt76_put_rxwi(dev, t); +@@ -33,39 +39,51 @@ u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size) + { + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc; +- struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; +- int i, len = SKB_WITH_OVERHEAD(q->buf_size); +- struct mt76_txwi_cache *t = NULL; ++ u32 length; ++ int i; ++ ++ length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size + ++ sizeof(struct skb_shared_info)); + + for (i = 0; i < size; i++) { +- enum dma_data_direction dir; +- dma_addr_t addr; +- u32 offset; ++ struct mt76_txwi_cache *t = mt76_get_rxwi(dev); ++ dma_addr_t phy_addr; ++ struct page *page; + int token; +- void *buf; ++ void *ptr; + +- t = mt76_get_rxwi(dev); + if (!t) + goto unmap; + +- buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); +- if (!buf) ++ page = __dev_alloc_pages(GFP_KERNEL, get_order(length)); ++ if (!page) { ++ mt76_put_rxwi(dev, t); + goto unmap; ++ } + +- addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset; +- dir = page_pool_get_dma_dir(q->page_pool); +- dma_sync_single_for_device(dev->dma_dev, addr, len, dir); ++ ptr = page_address(page); ++ phy_addr = dma_map_single(dev->dma_dev, ptr, ++ wed->wlan.rx_size, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dev->dev, phy_addr))) { ++ __free_pages(page, get_order(length)); ++ mt76_put_rxwi(dev, t); ++ goto unmap; ++ } + +- desc->buf0 = cpu_to_le32(addr); +- token = mt76_rx_token_consume(dev, buf, t, addr); ++ desc->buf0 = cpu_to_le32(phy_addr); ++ token = mt76_rx_token_consume(dev, ptr, t, phy_addr); + if (token < 0) { +- mt76_put_page_pool_buf(buf, false); ++ dma_unmap_single(dev->dma_dev, phy_addr, ++ wed->wlan.rx_size, DMA_TO_DEVICE); ++ __free_pages(page, get_order(length)); ++ mt76_put_rxwi(dev, t); + goto unmap; + } + + token = FIELD_PREP(MT_DMA_CTL_TOKEN, token); + #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT +- token |= FIELD_PREP(MT_DMA_CTL_SDP0_H, addr >> 32); ++ token |= FIELD_PREP(MT_DMA_CTL_SDP0_H, phy_addr >> 32); + #endif + desc->token |= cpu_to_le32(token); + desc++; +@@ -74,8 +92,6 @@ u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size) + return 0; + + unmap: +- if (t) +- mt76_put_rxwi(dev, t); + mt76_wed_release_rx_buf(wed); + + return -ENOMEM; +@@ -123,7 +139,7 @@ int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) + /* WED txfree queue needs ring to be initialized before setup */ + q->flags = 0; + mt76_dma_queue_reset(dev, q); +- mt76_dma_rx_fill(dev, q, false); ++ mt76_dma_rx_fill(dev, q); + + ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs); + if (!ret) +@@ -144,7 +160,7 @@ int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) + break; + case MT76_WED_RRO_Q_MSDU_PG: + q->flags &= ~MT_QFLAG_WED; +- __mt76_dma_queue_reset(dev, q, false); ++ __mt76_dma_queue_reset(dev, q); + mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs); + q->head = q->ndesc - 1; + q->queued = q->head; +@@ -152,7 +168,7 @@ int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) + case MT76_WED_RRO_Q_IND: + q->flags &= ~MT_QFLAG_WED; + mt76_dma_queue_reset(dev, q); +- mt76_dma_rx_fill(dev, q, false); ++ mt76_dma_rx_fill(dev, q); + mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs); + break; + default: +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1000-wifi-mt76-mt7915-add-mtk-internal-debug-tools-for-mt.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1000-wifi-mt76-mt7915-add-mtk-internal-debug-tools-for-mt.patch new file mode 100644 index 000000000..a03665bb1 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1000-wifi-mt76-mt7915-add-mtk-internal-debug-tools-for-mt.patch @@ -0,0 +1,5880 @@ +From ae5f0852b50290e0aaf2ff9d5dd8f9bd2b97bbb6 Mon Sep 17 00:00:00 2001 +From: Shayne Chen +Date: Wed, 22 Jun 2022 10:39:47 +0800 +Subject: [PATCH] wifi: mt76: mt7915: add mtk internal debug tools for mt76 + +--- + mt76_connac_mcu.h | 6 + + mt7915/Makefile | 2 +- + mt7915/debugfs.c | 89 +- + mt7915/mac.c | 14 + + mt7915/main.c | 5 + + mt7915/mcu.c | 48 +- + mt7915/mcu.h | 4 + + mt7915/mt7915.h | 56 + + mt7915/mt7915_debug.h | 1442 ++++++++++++++++ + mt7915/mtk_debugfs.c | 3750 +++++++++++++++++++++++++++++++++++++++++ + mt7915/mtk_mcu.c | 51 + + mt7915/soc.c | 7 + + tools/fwlog.c | 44 +- + 13 files changed, 5499 insertions(+), 19 deletions(-) + create mode 100644 mt7915/mt7915_debug.h + create mode 100644 mt7915/mtk_debugfs.c + create mode 100644 mt7915/mtk_mcu.c + +diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h +index 99cdd1b..a8690cd 100644 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1195,6 +1195,7 @@ enum { + MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, + MCU_EXT_CMD_FW_LOG_2_HOST = 0x13, + MCU_EXT_CMD_TXBF_ACTION = 0x1e, ++ MCU_EXT_CMD_MEC_CTRL = 0x1f, + MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, + MCU_EXT_CMD_THERMAL_PROT = 0x23, + MCU_EXT_CMD_STA_REC_UPDATE = 0x25, +@@ -1218,6 +1219,11 @@ enum { + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, + MCU_EXT_CMD_RXDCOC_CAL = 0x59, + MCU_EXT_CMD_GET_MIB_INFO = 0x5a, ++#ifdef MTK_DEBUG ++ MCU_EXT_CMD_RED_SHOW_STA = 0x69, ++ MCU_EXT_CMD_RED_TARGET_DELAY = 0x6A, ++ MCU_EXT_CMD_RED_TX_RPT = 0x6B, ++#endif + MCU_EXT_CMD_TXDPD_CAL = 0x60, + MCU_EXT_CMD_CAL_CACHE = 0x67, + MCU_EXT_CMD_RED_ENABLE = 0x68, +diff --git a/mt7915/Makefile b/mt7915/Makefile +index c4dca9c..fd71141 100644 +--- a/mt7915/Makefile ++++ b/mt7915/Makefile +@@ -4,7 +4,7 @@ EXTRA_CFLAGS += -DCONFIG_MT76_LEDS + obj-$(CONFIG_MT7915E) += mt7915e.o + + mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ +- debugfs.o mmio.o ++ debugfs.o mmio.o mtk_debugfs.o mtk_mcu.o + + mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o + mt7915e-$(CONFIG_MT798X_WMAC) += soc.o +diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c +index 894e2cd..2661386 100644 +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -8,6 +8,9 @@ + #include "mac.h" + + #define FW_BIN_LOG_MAGIC 0x44e98caf ++#ifdef MTK_DEBUG ++#define FW_BIN_LOG_MAGIC_V2 0x44d9c99a ++#endif + + /** global debugfs **/ + +@@ -496,6 +499,9 @@ mt7915_fw_debug_wm_set(void *data, u64 val) + int ret; + + dev->fw.debug_wm = val ? MCU_FW_LOG_TO_HOST : 0; ++#ifdef MTK_DEBUG ++ dev->fw.debug_wm = val; ++#endif + + if (dev->fw.debug_bin) + val = 16; +@@ -520,6 +526,9 @@ mt7915_fw_debug_wm_set(void *data, u64 val) + if (ret) + goto out; + } ++#ifdef MTK_DEBUG ++ mt7915_mcu_fw_dbg_ctrl(dev, 68, !!val); ++#endif + + /* WM CPU info record control */ + mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0)); +@@ -528,6 +537,12 @@ mt7915_fw_debug_wm_set(void *data, u64 val) + mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5)); + mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5)); + ++#ifdef MTK_DEBUG ++ if (dev->fw.debug_bin & BIT(3)) ++ /* use bit 7 to indicate v2 magic number */ ++ dev->fw.debug_wm |= BIT(7); ++#endif ++ + out: + if (ret) + dev->fw.debug_wm = 0; +@@ -540,7 +555,11 @@ mt7915_fw_debug_wm_get(void *data, u64 *val) + { + struct mt7915_dev *dev = data; + +- *val = dev->fw.debug_wm; ++#ifdef MTK_DEBUG ++ *val = dev->fw.debug_wm & ~BIT(7); ++#else ++ val = dev->fw.debug_wm; ++#endif + + return 0; + } +@@ -615,16 +634,30 @@ mt7915_fw_debug_bin_set(void *data, u64 val) + }; + struct mt7915_dev *dev = data; + +- if (!dev->relay_fwlog) ++ if (!dev->relay_fwlog && val) { + dev->relay_fwlog = relay_open("fwlog_data", dev->debugfs_dir, + 1500, 512, &relay_cb, NULL); +- if (!dev->relay_fwlog) +- return -ENOMEM; ++ if (!dev->relay_fwlog) ++ return -ENOMEM; ++ } + + dev->fw.debug_bin = val; + + relay_reset(dev->relay_fwlog); + ++#ifdef MTK_DEBUG ++ dev->dbg.dump_mcu_pkt = val & BIT(4) ? true : false; ++ dev->dbg.dump_txd = val & BIT(5) ? true : false; ++ dev->dbg.dump_tx_pkt = val & BIT(6) ? true : false; ++ dev->dbg.dump_rx_pkt = val & BIT(7) ? true : false; ++ dev->dbg.dump_rx_raw = val & BIT(8) ? true : false; ++#endif ++ ++ if (dev->relay_fwlog && !val) { ++ relay_close(dev->relay_fwlog); ++ dev->relay_fwlog = NULL; ++ } ++ + return mt7915_fw_debug_wm_set(dev, dev->fw.debug_wm); + } + +@@ -1254,6 +1287,11 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) + if (!ext_phy) + dev->debugfs_dir = dir; + ++#ifdef MTK_DEBUG ++ debugfs_create_u16("wlan_idx", 0600, dir, &dev->wlan_idx); ++ mt7915_mtk_init_debugfs(phy, dir); ++#endif ++ + return 0; + } + +@@ -1266,6 +1304,12 @@ mt7915_debugfs_write_fwlog(struct mt7915_dev *dev, const void *hdr, int hdrlen, + void *dest; + + spin_lock_irqsave(&lock, flags); ++ ++ if (!dev->relay_fwlog) { ++ spin_unlock_irqrestore(&lock, flags); ++ return; ++ } ++ + dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4); + if (dest) { + *(u32 *)dest = hdrlen + len; +@@ -1294,17 +1338,50 @@ void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int + .msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR), + }; + +- if (!dev->relay_fwlog) +- return; ++#ifdef MTK_DEBUG ++ struct { ++ __le32 magic; ++ u8 version; ++ u8 _rsv; ++ __le16 serial_id; ++ __le32 timestamp; ++ __le16 msg_type; ++ __le16 len; ++ } hdr2 = { ++ .version = 0x1, ++ .magic = cpu_to_le32(FW_BIN_LOG_MAGIC_V2), ++ .msg_type = PKT_TYPE_RX_FW_MONITOR, ++ }; ++#endif + ++#ifdef MTK_DEBUG ++ /* old magic num */ ++ if (!(dev->fw.debug_wm & BIT(7))) { ++ hdr.timestamp = mt76_rr(dev, MT_LPON_FRCR(0)); ++ hdr.len = *(__le16 *)data; ++ mt7915_debugfs_write_fwlog(dev, &hdr, sizeof(hdr), data, len); ++ } else { ++ hdr2.serial_id = dev->dbg.fwlog_seq++; ++ hdr2.timestamp = mt76_rr(dev, MT_LPON_FRCR(0)); ++ hdr2.len = *(__le16 *)data; ++ mt7915_debugfs_write_fwlog(dev, &hdr2, sizeof(hdr2), data, len); ++ } ++#else + hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0))); + hdr.len = *(__le16 *)data; + mt7915_debugfs_write_fwlog(dev, &hdr, sizeof(hdr), data, len); ++#endif + } + + bool mt7915_debugfs_rx_log(struct mt7915_dev *dev, const void *data, int len) + { ++#ifdef MTK_DEBUG ++ if (get_unaligned_le32(data) != FW_BIN_LOG_MAGIC && ++ get_unaligned_le32(data) != FW_BIN_LOG_MAGIC_V2 && ++ get_unaligned_le32(data) != PKT_BIN_DEBUG_MAGIC) ++#else + if (get_unaligned_le32(data) != FW_BIN_LOG_MAGIC) ++#endif + return false; + + if (dev->relay_fwlog) +diff --git a/mt7915/mac.c b/mt7915/mac.c +index 4604a68..d99864f 100644 +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -282,6 +282,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, + __le16 fc = 0; + int idx; + ++#ifdef MTK_DEBUG ++ if (dev->dbg.dump_rx_raw) ++ mt7915_packet_log_to_host(dev, skb->data, skb->len, PKT_BIN_DEBUG_RX_RAW, 0); ++#endif + memset(status, 0, sizeof(*status)); + + if ((rxd1 & MT_RXD1_NORMAL_BAND_IDX) && !phy->mt76->band_idx) { +@@ -466,6 +470,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, + } + + hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; ++#ifdef MTK_DEBUG ++ if (dev->dbg.dump_rx_pkt) ++ mt7915_packet_log_to_host(dev, skb->data, skb->len, PKT_BIN_DEBUG_RX, hdr_gap); ++#endif + if (hdr_trans && ieee80211_has_morefrags(fc)) { + struct ieee80211_vif *vif; + int err; +@@ -804,6 +812,12 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + tx_info->buf[1].skip_unmap = true; + tx_info->nbuf = MT_CT_DMA_BUF_NUM; + ++#ifdef MTK_DEBUG ++ if (dev->dbg.dump_txd) ++ mt7915_packet_log_to_host(dev, txwi, MT_TXD_SIZE, PKT_BIN_DEBUG_TXD, 0); ++ if (dev->dbg.dump_tx_pkt) ++ mt7915_packet_log_to_host(dev, t->skb->data, t->skb->len, PKT_BIN_DEBUG_TX, 0); ++#endif + return 0; + } + +diff --git a/mt7915/main.c b/mt7915/main.c +index e10cdb3..3ac3df3 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -73,7 +73,11 @@ int mt7915_run(struct ieee80211_hw *hw) + if (ret) + goto out; + ++#ifdef MTK_DEBUG ++ ret = mt7915_mcu_set_sku_en(phy, !dev->dbg.sku_disable); ++#else + ret = mt7915_mcu_set_sku_en(phy, true); ++#endif + if (ret) + goto out; + +@@ -254,6 +258,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, + mvif->sta.wcid.hw_key_idx = -1; + mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; + mt76_wcid_init(&mvif->sta.wcid); ++ mvif->sta.vif = mvif; + + mt7915_mac_wtbl_update(dev, idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index 3e3d57c..1a3647a 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -205,6 +205,11 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, + else + qid = MT_MCUQ_WM; + ++#ifdef MTK_DEBUG ++ if (dev->dbg.dump_mcu_pkt) ++ mt7915_packet_log_to_host(dev, skb->data, skb->len, PKT_BIN_DEBUG_MCU, 0); ++#endif ++ + return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0); + } + +@@ -2385,7 +2390,10 @@ static int mt7915_red_set_watermark(struct mt7915_dev *dev) + sizeof(req), false); + } + +-static int mt7915_mcu_set_red(struct mt7915_dev *dev, bool enabled) ++#ifndef MTK_DEBUG ++static ++#endif ++int mt7915_mcu_set_red(struct mt7915_dev *dev, bool enabled) + { + #define RED_DISABLE 0 + #define RED_BY_WA_ENABLE 2 +@@ -3519,6 +3527,8 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable) + .sku_enable = enable, + }; + ++ pr_info("%s: enable = %d\n", __func__, enable); ++ + return mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, + sizeof(req), true); +@@ -4185,6 +4195,23 @@ out: + return ret; + } + ++#ifdef MTK_DEBUG ++int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp) ++{ ++ struct { ++ __le32 args[3]; ++ } req = { ++ .args = { ++ cpu_to_le32(a1), ++ cpu_to_le32(a2), ++ cpu_to_le32(a3), ++ }, ++ }; ++ ++ return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), wait_resp); ++} ++#endif ++ + int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set) + { + struct { +@@ -4214,6 +4241,25 @@ int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set) + return 0; + } + ++#ifdef MTK_DEBUG ++int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable) ++{ ++ struct { ++ u16 action; ++ u8 _rsv1[2]; ++ u16 wcid; ++ u8 enable; ++ u8 _rsv2[5]; ++ } __packed req = { ++ .action = cpu_to_le16(1), ++ .wcid = cpu_to_le16(wcid), ++ .enable = enable, ++ }; ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MEC_CTRL), &req, sizeof(req), true); ++} ++#endif ++ + int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif) + { + #define IP_DSCP_NUM 64 +diff --git a/mt7915/mcu.h b/mt7915/mcu.h +index fa0847d..9ae0f07 100644 +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -347,6 +347,10 @@ enum { + MCU_WA_PARAM_PDMA_RX = 0x04, + MCU_WA_PARAM_CPU_UTIL = 0x0b, + MCU_WA_PARAM_RED = 0x0e, ++#ifdef MTK_DEBUG ++ MCU_WA_PARAM_RED_SHOW_STA = 0xf, ++ MCU_WA_PARAM_RED_TARGET_DELAY = 0x10, ++#endif + MCU_WA_PARAM_BSS_ACQ_PKT_CNT = 0x12, + MCU_WA_PARAM_RED_SETTING = 0x40, + }; +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 66d87d7..398f851 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -9,6 +9,7 @@ + #include "../mt76_connac.h" + #include "regs.h" + ++#define MTK_DEBUG 1 + #define MT7915_MAX_INTERFACES 19 + #define MT7915_WTBL_SIZE 288 + #define MT7916_WTBL_SIZE 544 +@@ -244,6 +245,14 @@ struct mt7915_phy { + #endif + }; + ++#ifdef MTK_DEBUG ++enum { ++ ADIE0, ++ ADIE1, ++ ADIE_MAX_CNT, ++}; ++#endif ++ + struct mt7915_dev { + union { /* must be first */ + struct mt76_dev mt76; +@@ -327,6 +336,33 @@ struct mt7915_dev { + void __iomem *dcm; + void __iomem *sku; + ++#ifdef MTK_DEBUG ++ u16 wlan_idx; ++ struct { ++ u32 fixed_rate; ++ u32 l1debugfs_reg; ++ u32 l2debugfs_reg; ++ u32 mac_reg; ++ u32 fw_dbg_module; ++ u8 fw_dbg_lv; ++ u32 bcn_total_cnt[2]; ++ u16 fwlog_seq; ++ bool dump_mcu_pkt; ++ bool dump_txd; ++ bool dump_tx_pkt; ++ bool dump_rx_pkt; ++ bool dump_rx_raw; ++ u32 token_idx; ++ u8 sku_disable; ++ } dbg; ++ const struct mt7915_dbg_reg_desc *dbg_reg; ++ ++ struct { ++ u16 id; ++ u16 version; ++ } adie[ADIE_MAX_CNT]; ++#endif ++ + bool wmm_pbc_enable; + struct work_struct wmm_pbc_work; + u32 adie_type; +@@ -611,4 +647,24 @@ void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, + bool pci, int *irq); + ++#ifdef MTK_DEBUG ++int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir); ++int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp); ++int mt7915_mcu_set_red(struct mt7915_dev *dev, bool enabled); ++void mt7915_dump_tmac_info(u8 *tmac_info); ++int mt7915_mcu_set_txpower_level(struct mt7915_phy *phy, u8 drop_level); ++void mt7915_packet_log_to_host(struct mt7915_dev *dev, const void *data, int len, int type, int des_len); ++int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable); ++ ++#define PKT_BIN_DEBUG_MAGIC 0xc8763123 ++enum { ++ PKT_BIN_DEBUG_MCU, ++ PKT_BIN_DEBUG_TXD, ++ PKT_BIN_DEBUG_TX, ++ PKT_BIN_DEBUG_RX, ++ PKT_BIN_DEBUG_RX_RAW, ++}; ++ ++#endif ++ + #endif +diff --git a/mt7915/mt7915_debug.h b/mt7915/mt7915_debug.h +new file mode 100644 +index 0000000..1ec8de9 +--- /dev/null ++++ b/mt7915/mt7915_debug.h +@@ -0,0 +1,1442 @@ ++#ifndef __MT7915_DEBUG_H ++#define __MT7915_DEBUG_H ++ ++#ifdef MTK_DEBUG ++ ++#define DBG_INVALID_BASE 0xffffffff ++#define DBG_INVALID_OFFSET 0x0 ++ ++struct __dbg_map { ++ u32 phys; ++ u32 maps; ++ u32 size; ++}; ++ ++struct __dbg_reg { ++ u32 base; ++ u32 offs; ++}; ++ ++struct __dbg_mask { ++ u32 end; ++ u32 start; ++}; ++ ++enum dbg_base_rev { ++ MT_DBG_WFDMA0_BASE, ++ MT_DBG_WFDMA1_BASE, ++ MT_DBG_WFDMA0_PCIE1_BASE, ++ MT_DBG_WFDMA1_PCIE1_BASE, ++ MT_DBG_WFDMA_EXT_CSR_BASE, ++ MT_DBG_SWDEF_BASE, ++ __MT_DBG_BASE_REV_MAX, ++}; ++ ++enum dbg_reg_rev { ++ DBG_INT_SOURCE_CSR, ++ DBG_INT_MASK_CSR, ++ DBG_INT1_SOURCE_CSR, ++ DBG_INT1_MASK_CSR, ++ DBG_TX_RING_BASE, ++ DBG_RX_EVENT_RING_BASE, ++ DBG_RX_STS_RING_BASE, ++ DBG_RX_DATA_RING_BASE, ++ DBG_DMA_ICSC_FR0, ++ DBG_DMA_ICSC_FR1, ++ DBG_TMAC_ICSCR0, ++ DBG_RMAC_RXICSRPT, ++ DBG_MIB_M0SDR0, ++ DBG_MIB_M0SDR3, ++ DBG_MIB_M0SDR4, ++ DBG_MIB_M0SDR5, ++ DBG_MIB_M0SDR7, ++ DBG_MIB_M0SDR8, ++ DBG_MIB_M0SDR9, ++ DBG_MIB_M0SDR10, ++ DBG_MIB_M0SDR11, ++ DBG_MIB_M0SDR12, ++ DBG_MIB_M0SDR14, ++ DBG_MIB_M0SDR15, ++ DBG_MIB_M0SDR16, ++ DBG_MIB_M0SDR17, ++ DBG_MIB_M0SDR18, ++ DBG_MIB_M0SDR19, ++ DBG_MIB_M0SDR20, ++ DBG_MIB_M0SDR21, ++ DBG_MIB_M0SDR22, ++ DBG_MIB_M0SDR23, ++ DBG_MIB_M0DR0, ++ DBG_MIB_M0DR1, ++ DBG_MIB_MUBF, ++ DBG_MIB_M0DR6, ++ DBG_MIB_M0DR7, ++ DBG_MIB_M0DR8, ++ DBG_MIB_M0DR9, ++ DBG_MIB_M0DR10, ++ DBG_MIB_M0DR11, ++ DBG_MIB_M0DR12, ++ DBG_WTBLON_WDUCR, ++ DBG_UWTBL_WDUCR, ++ DBG_PLE_DRR_TABLE_CTRL, ++ DBG_PLE_DRR_TABLE_RDATA, ++ DBG_PLE_PBUF_CTRL, ++ DBG_PLE_QUEUE_EMPTY, ++ DBG_PLE_FREEPG_CNT, ++ DBG_PLE_FREEPG_HEAD_TAIL, ++ DBG_PLE_PG_HIF_GROUP, ++ DBG_PLE_HIF_PG_INFO, ++ DBG_PLE_PG_HIF_TXCMD_GROUP, ++ DBG_PLE_HIF_TXCMD_PG_INFO, ++ DBG_PLE_PG_CPU_GROUP, ++ DBG_PLE_CPU_PG_INFO, ++ DBG_PLE_FL_QUE_CTRL, ++ DBG_PLE_NATIVE_TXCMD_Q_EMPTY, ++ DBG_PLE_TXCMD_Q_EMPTY, ++ DBG_PLE_AC_QEMPTY, ++ DBG_PLE_AC_OFFSET, ++ DBG_PLE_STATION_PAUSE, ++ DBG_PLE_DIS_STA_MAP, ++ DBG_PSE_PBUF_CTRL, ++ DBG_PSE_FREEPG_CNT, ++ DBG_PSE_FREEPG_HEAD_TAIL, ++ DBG_PSE_HIF0_PG_INFO, ++ DBG_PSE_PG_HIF1_GROUP, ++ DBG_PSE_HIF1_PG_INFO, ++ DBG_PSE_PG_CPU_GROUP, ++ DBG_PSE_CPU_PG_INFO, ++ DBG_PSE_PG_PLE_GROUP, ++ DBG_PSE_PLE_PG_INFO, ++ DBG_PSE_PG_LMAC0_GROUP, ++ DBG_PSE_LMAC0_PG_INFO, ++ DBG_PSE_PG_LMAC1_GROUP, ++ DBG_PSE_LMAC1_PG_INFO, ++ DBG_PSE_PG_LMAC2_GROUP, ++ DBG_PSE_LMAC2_PG_INFO, ++ DBG_PSE_PG_LMAC3_GROUP, ++ DBG_PSE_LMAC3_PG_INFO, ++ DBG_PSE_PG_MDP_GROUP, ++ DBG_PSE_MDP_PG_INFO, ++ DBG_PSE_PG_PLE1_GROUP, ++ DBG_PSE_PLE1_PG_INFO, ++ DBG_AGG_AALCR0, ++ DBG_AGG_AALCR1, ++ DBG_AGG_AALCR2, ++ DBG_AGG_AALCR3, ++ DBG_AGG_AALCR4, ++ DBG_AGG_B0BRR0, ++ DBG_AGG_B1BRR0, ++ DBG_AGG_B2BRR0, ++ DBG_AGG_B3BRR0, ++ DBG_AGG_AWSCR0, ++ DBG_AGG_PCR0, ++ DBG_AGG_TTCR0, ++ DBG_MIB_M0ARNG0, ++ DBG_MIB_M0DR2, ++ DBG_MIB_M0DR13, ++ DBG_WFDMA_WED_TX_CTRL, ++ DBG_WFDMA_WED_RX_CTRL, ++ __MT_DBG_REG_REV_MAX, ++}; ++ ++enum dbg_mask_rev { ++ DBG_MIB_M0SDR10_RX_MDRDY_COUNT, ++ DBG_MIB_M0SDR14_AMPDU, ++ DBG_MIB_M0SDR15_AMPDU_ACKED, ++ DBG_MIB_RX_FCS_ERROR_COUNT, ++ __MT_DBG_MASK_REV_MAX, ++}; ++ ++enum dbg_bit_rev { ++ __MT_DBG_BIT_REV_MAX, ++}; ++ ++static const u32 mt7915_dbg_base[] = { ++ [MT_DBG_WFDMA0_BASE] = 0xd4000, ++ [MT_DBG_WFDMA1_BASE] = 0xd5000, ++ [MT_DBG_WFDMA0_PCIE1_BASE] = 0xd8000, ++ [MT_DBG_WFDMA1_PCIE1_BASE] = 0xd9000, ++ [MT_DBG_WFDMA_EXT_CSR_BASE] = 0xd7000, ++ [MT_DBG_SWDEF_BASE] = 0x41f200, ++}; ++ ++static const u32 mt7916_dbg_base[] = { ++ [MT_DBG_WFDMA0_BASE] = 0xd4000, ++ [MT_DBG_WFDMA1_BASE] = 0xd5000, ++ [MT_DBG_WFDMA0_PCIE1_BASE] = 0xd8000, ++ [MT_DBG_WFDMA1_PCIE1_BASE] = 0xd9000, ++ [MT_DBG_WFDMA_EXT_CSR_BASE] = 0xd7000, ++ [MT_DBG_SWDEF_BASE] = 0x411400, ++}; ++ ++static const u32 mt7981_dbg_base[] = { ++ [MT_DBG_WFDMA0_BASE] = 0x24000, ++ [MT_DBG_WFDMA1_BASE] = 0x25000, ++ [MT_DBG_WFDMA0_PCIE1_BASE] = 0x28000, ++ [MT_DBG_WFDMA1_PCIE1_BASE] = 0x29000, ++ [MT_DBG_WFDMA_EXT_CSR_BASE] = 0x27000, ++ [MT_DBG_SWDEF_BASE] = 0x411400, ++}; ++ ++static const u32 mt7986_dbg_base[] = { ++ [MT_DBG_WFDMA0_BASE] = 0x24000, ++ [MT_DBG_WFDMA1_BASE] = 0x25000, ++ [MT_DBG_WFDMA0_PCIE1_BASE] = 0x28000, ++ [MT_DBG_WFDMA1_PCIE1_BASE] = 0x29000, ++ [MT_DBG_WFDMA_EXT_CSR_BASE] = 0x27000, ++ [MT_DBG_SWDEF_BASE] = 0x411400, ++}; ++ ++/* mt7915 regs with different base and offset */ ++static const struct __dbg_reg mt7915_dbg_reg[] = { ++ [DBG_WFDMA_WED_TX_CTRL] = { MT_DBG_WFDMA_EXT_CSR_BASE, 0x300 }, ++ [DBG_WFDMA_WED_RX_CTRL] = { MT_DBG_WFDMA_EXT_CSR_BASE, 0x400 }, ++ [DBG_INT_SOURCE_CSR] = { MT_DBG_WFDMA_EXT_CSR_BASE, 0x10 }, ++ [DBG_INT_MASK_CSR] = { MT_DBG_WFDMA_EXT_CSR_BASE, 0x14 }, ++ [DBG_INT1_SOURCE_CSR] = { MT_DBG_WFDMA_EXT_CSR_BASE, 0x88 }, ++ [DBG_INT1_MASK_CSR] = { MT_DBG_WFDMA_EXT_CSR_BASE, 0x8c }, ++ [DBG_TX_RING_BASE] = { MT_DBG_WFDMA1_BASE, 0x400 }, ++ [DBG_RX_EVENT_RING_BASE] = { MT_DBG_WFDMA1_BASE, 0x500 }, ++ [DBG_RX_STS_RING_BASE] = { MT_DBG_WFDMA1_BASE, 0x510 }, ++ [DBG_RX_DATA_RING_BASE] = { MT_DBG_WFDMA0_BASE, 0x500 }, ++ [DBG_DMA_ICSC_FR0] = { DBG_INVALID_BASE, 0x0f0 }, ++ [DBG_DMA_ICSC_FR1] = { DBG_INVALID_BASE, 0x0f4 }, ++ [DBG_TMAC_ICSCR0] = { DBG_INVALID_BASE, 0x200 }, ++ [DBG_RMAC_RXICSRPT] = { DBG_INVALID_BASE, 0x618}, ++ [DBG_MIB_M0SDR0] = { DBG_INVALID_BASE, 0x010}, ++ [DBG_MIB_M0SDR3] = { DBG_INVALID_BASE, 0x014}, ++ [DBG_MIB_M0SDR4] = { DBG_INVALID_BASE, 0x018}, ++ [DBG_MIB_M0SDR5] = { DBG_INVALID_BASE, 0x01c}, ++ [DBG_MIB_M0SDR7] = { DBG_INVALID_BASE, 0x024}, ++ [DBG_MIB_M0SDR8] = { DBG_INVALID_BASE, 0x028}, ++ [DBG_MIB_M0SDR9] = { DBG_INVALID_BASE, 0x02C}, ++ [DBG_MIB_M0SDR10] = { DBG_INVALID_BASE, 0x030}, ++ [DBG_MIB_M0SDR11] = { DBG_INVALID_BASE, 0x034}, ++ [DBG_MIB_M0SDR12] = { DBG_INVALID_BASE, 0x038}, ++ [DBG_MIB_M0SDR14] = { DBG_INVALID_BASE, 0x040}, ++ [DBG_MIB_M0SDR15] = { DBG_INVALID_BASE, 0x044}, ++ [DBG_MIB_M0SDR16] = { DBG_INVALID_BASE, 0x048}, ++ [DBG_MIB_M0SDR17] = { DBG_INVALID_BASE, 0x04c}, ++ [DBG_MIB_M0SDR18] = { DBG_INVALID_BASE, 0x050}, ++ [DBG_MIB_M0SDR19] = { DBG_INVALID_BASE, 0x054}, ++ [DBG_MIB_M0SDR20] = { DBG_INVALID_BASE, 0x058}, ++ [DBG_MIB_M0SDR21] = { DBG_INVALID_BASE, 0x05c}, ++ [DBG_MIB_M0SDR22] = { DBG_INVALID_BASE, 0x060}, ++ [DBG_MIB_M0SDR23] = { DBG_INVALID_BASE, 0x064}, ++ [DBG_MIB_M0DR0] = { DBG_INVALID_BASE, 0x0a0}, ++ [DBG_MIB_M0DR1] = { DBG_INVALID_BASE, 0x0a4}, ++ [DBG_MIB_MUBF] = { DBG_INVALID_BASE, 0x090}, ++ [DBG_MIB_M0DR6] = { DBG_INVALID_BASE, 0x0b8}, ++ [DBG_MIB_M0DR7] = { DBG_INVALID_BASE, 0x0bc}, ++ [DBG_MIB_M0DR8] = { DBG_INVALID_BASE, 0x0c0}, ++ [DBG_MIB_M0DR9] = { DBG_INVALID_BASE, 0x0c4}, ++ [DBG_MIB_M0DR10] = { DBG_INVALID_BASE, 0x0c8}, ++ [DBG_MIB_M0DR11] = { DBG_INVALID_BASE, 0x0cc}, ++ [DBG_MIB_M0DR12] = { DBG_INVALID_BASE, 0x160}, ++ [DBG_WTBLON_WDUCR] = { DBG_INVALID_BASE, 0x0}, ++ [DBG_UWTBL_WDUCR] = { DBG_INVALID_BASE, 0x0}, ++ [DBG_PLE_DRR_TABLE_CTRL] = { DBG_INVALID_BASE, 0x388}, ++ [DBG_PLE_DRR_TABLE_RDATA] = { DBG_INVALID_BASE, 0x350}, ++ [DBG_PLE_PBUF_CTRL] = { DBG_INVALID_BASE, 0x014}, ++ [DBG_PLE_QUEUE_EMPTY] = { DBG_INVALID_BASE, 0x0b0}, ++ [DBG_PLE_FREEPG_CNT] = { DBG_INVALID_BASE, 0x100}, ++ [DBG_PLE_FREEPG_HEAD_TAIL] = { DBG_INVALID_BASE, 0x104}, ++ [DBG_PLE_PG_HIF_GROUP] = { DBG_INVALID_BASE, 0x110}, ++ [DBG_PLE_HIF_PG_INFO] = { DBG_INVALID_BASE, 0x114}, ++ [DBG_PLE_PG_HIF_TXCMD_GROUP] = { DBG_INVALID_BASE, 0x120}, ++ [DBG_PLE_HIF_TXCMD_PG_INFO] = { DBG_INVALID_BASE, 0x124}, ++ [DBG_PLE_PG_CPU_GROUP] = { DBG_INVALID_BASE, 0x150}, ++ [DBG_PLE_CPU_PG_INFO] = { DBG_INVALID_BASE, 0x154}, ++ [DBG_PLE_FL_QUE_CTRL] = { DBG_INVALID_BASE, 0x1b0}, ++ [DBG_PLE_NATIVE_TXCMD_Q_EMPTY] = { DBG_INVALID_BASE, 0x22c}, ++ [DBG_PLE_TXCMD_Q_EMPTY] = { DBG_INVALID_BASE, 0x230}, ++ [DBG_PLE_AC_QEMPTY] = { DBG_INVALID_BASE, 0x500}, ++ [DBG_PLE_AC_OFFSET] = { DBG_INVALID_BASE, 0x040}, ++ [DBG_PLE_STATION_PAUSE] = { DBG_INVALID_BASE, 0x400}, ++ [DBG_PLE_DIS_STA_MAP] = { DBG_INVALID_BASE, 0x440}, ++ [DBG_PSE_PBUF_CTRL] = { DBG_INVALID_BASE, 0x014}, ++ [DBG_PSE_FREEPG_CNT] = { DBG_INVALID_BASE, 0x100}, ++ [DBG_PSE_FREEPG_HEAD_TAIL] = { DBG_INVALID_BASE, 0x104}, ++ [DBG_PSE_HIF0_PG_INFO] = { DBG_INVALID_BASE, 0x114}, ++ [DBG_PSE_PG_HIF1_GROUP] = { DBG_INVALID_BASE, 0x118}, ++ [DBG_PSE_HIF1_PG_INFO] = { DBG_INVALID_BASE, 0x11c}, ++ [DBG_PSE_PG_CPU_GROUP] = { DBG_INVALID_BASE, 0x150}, ++ [DBG_PSE_CPU_PG_INFO] = { DBG_INVALID_BASE, 0x154}, ++ [DBG_PSE_PG_PLE_GROUP] = { DBG_INVALID_BASE, 0x160}, ++ [DBG_PSE_PLE_PG_INFO] = { DBG_INVALID_BASE, 0x164}, ++ [DBG_PSE_PG_LMAC0_GROUP] = { DBG_INVALID_BASE, 0x170}, ++ [DBG_PSE_LMAC0_PG_INFO] = { DBG_INVALID_BASE, 0x174}, ++ [DBG_PSE_PG_LMAC1_GROUP] = { DBG_INVALID_BASE, 0x178}, ++ [DBG_PSE_LMAC1_PG_INFO] = { DBG_INVALID_BASE, 0x17c}, ++ [DBG_PSE_PG_LMAC2_GROUP] = { DBG_INVALID_BASE, 0x180}, ++ [DBG_PSE_LMAC2_PG_INFO] = { DBG_INVALID_BASE, 0x184}, ++ [DBG_PSE_PG_LMAC3_GROUP] = { DBG_INVALID_BASE, 0x188}, ++ [DBG_PSE_LMAC3_PG_INFO] = { DBG_INVALID_BASE, 0x18c}, ++ [DBG_PSE_PG_MDP_GROUP] = { DBG_INVALID_BASE, 0x198}, ++ [DBG_PSE_MDP_PG_INFO] = { DBG_INVALID_BASE, 0x19c}, ++ [DBG_PSE_PG_PLE1_GROUP] = { DBG_INVALID_BASE, 0x168}, ++ [DBG_PSE_PLE1_PG_INFO] = { DBG_INVALID_BASE, 0x16c}, ++ [DBG_AGG_AALCR0] = { DBG_INVALID_BASE, 0x048}, ++ [DBG_AGG_AALCR1] = { DBG_INVALID_BASE, 0x04c}, ++ [DBG_AGG_AALCR2] = { DBG_INVALID_BASE, 0x050}, ++ [DBG_AGG_AALCR3] = { DBG_INVALID_BASE, 0x054}, ++ [DBG_AGG_AALCR4] = { DBG_INVALID_BASE, 0x058}, ++ [DBG_AGG_B0BRR0] = { DBG_INVALID_BASE, 0x100}, ++ [DBG_AGG_B1BRR0] = { DBG_INVALID_BASE, 0x104}, ++ [DBG_AGG_B2BRR0] = { DBG_INVALID_BASE, 0x108}, ++ [DBG_AGG_B3BRR0] = { DBG_INVALID_BASE, 0x10c}, ++ [DBG_AGG_AWSCR0] = { DBG_INVALID_BASE, 0x030}, ++ [DBG_AGG_PCR0] = { DBG_INVALID_BASE, 0x040}, ++ [DBG_AGG_TTCR0] = { DBG_INVALID_BASE, 0x04c}, ++ [DBG_MIB_M0ARNG0] = { DBG_INVALID_BASE, 0x4b8}, ++ [DBG_MIB_M0DR2] = { DBG_INVALID_BASE, 0x0a8}, ++ [DBG_MIB_M0DR13] = { DBG_INVALID_BASE, 0x164}, ++}; ++ ++/* mt7986/mt7916 regs with different base and offset */ ++static const struct __dbg_reg mt7916_dbg_reg[] = { ++ [DBG_WFDMA_WED_TX_CTRL] = { MT_DBG_WFDMA_EXT_CSR_BASE, 0x300 }, ++ [DBG_WFDMA_WED_RX_CTRL] = { MT_DBG_WFDMA_EXT_CSR_BASE, 0x400 }, ++ [DBG_INT_SOURCE_CSR] = { MT_DBG_WFDMA0_BASE, 0x200 }, ++ [DBG_INT_MASK_CSR] = { MT_DBG_WFDMA0_BASE, 0x204 }, ++ [DBG_INT1_SOURCE_CSR] = { MT_DBG_WFDMA0_PCIE1_BASE, 0x200 }, ++ [DBG_INT1_MASK_CSR] = { MT_DBG_WFDMA0_PCIE1_BASE, 0x204 }, ++ [DBG_TX_RING_BASE] = { MT_DBG_WFDMA0_BASE, 0x400 }, ++ [DBG_RX_EVENT_RING_BASE] = { MT_DBG_WFDMA0_BASE, 0x500 }, ++ [DBG_RX_STS_RING_BASE] = { MT_DBG_WFDMA0_BASE, 0x520 }, ++ [DBG_RX_DATA_RING_BASE] = { MT_DBG_WFDMA0_BASE, 0x540 }, ++ [DBG_DMA_ICSC_FR0] = { DBG_INVALID_BASE, 0x05c }, ++ [DBG_DMA_ICSC_FR1] = { DBG_INVALID_BASE, 0x060 }, ++ [DBG_TMAC_ICSCR0] = { DBG_INVALID_BASE, 0x120 }, ++ [DBG_RMAC_RXICSRPT] = { DBG_INVALID_BASE, 0xd0 }, ++ [DBG_MIB_M0SDR0] = { DBG_INVALID_BASE, 0x7d8}, ++ [DBG_MIB_M0SDR3] = { DBG_INVALID_BASE, 0x698}, ++ [DBG_MIB_M0SDR4] = { DBG_INVALID_BASE, 0x788}, ++ [DBG_MIB_M0SDR5] = { DBG_INVALID_BASE, 0x780}, ++ [DBG_MIB_M0SDR7] = { DBG_INVALID_BASE, 0x5a8}, ++ [DBG_MIB_M0SDR8] = { DBG_INVALID_BASE, 0x78c}, ++ [DBG_MIB_M0SDR9] = { DBG_INVALID_BASE, 0x024}, ++ [DBG_MIB_M0SDR10] = { DBG_INVALID_BASE, 0x76c}, ++ [DBG_MIB_M0SDR11] = { DBG_INVALID_BASE, 0x790}, ++ [DBG_MIB_M0SDR12] = { DBG_INVALID_BASE, 0x558}, ++ [DBG_MIB_M0SDR14] = { DBG_INVALID_BASE, 0x564}, ++ [DBG_MIB_M0SDR15] = { DBG_INVALID_BASE, 0x564}, ++ [DBG_MIB_M0SDR16] = { DBG_INVALID_BASE, 0x7fc}, ++ [DBG_MIB_M0SDR17] = { DBG_INVALID_BASE, 0x800}, ++ [DBG_MIB_M0SDR18] = { DBG_INVALID_BASE, 0x030}, ++ [DBG_MIB_M0SDR19] = { DBG_INVALID_BASE, 0x5ac}, ++ [DBG_MIB_M0SDR20] = { DBG_INVALID_BASE, 0x5b0}, ++ [DBG_MIB_M0SDR21] = { DBG_INVALID_BASE, 0x5b4}, ++ [DBG_MIB_M0SDR22] = { DBG_INVALID_BASE, 0x770}, ++ [DBG_MIB_M0SDR23] = { DBG_INVALID_BASE, 0x774}, ++ [DBG_MIB_M0DR0] = { DBG_INVALID_BASE, 0x594}, ++ [DBG_MIB_M0DR1] = { DBG_INVALID_BASE, 0x598}, ++ [DBG_MIB_MUBF] = { DBG_INVALID_BASE, 0x7ac}, ++ [DBG_MIB_M0DR6] = { DBG_INVALID_BASE, 0x658}, ++ [DBG_MIB_M0DR7] = { DBG_INVALID_BASE, 0x65c}, ++ [DBG_MIB_M0DR8] = { DBG_INVALID_BASE, 0x56c}, ++ [DBG_MIB_M0DR9] = { DBG_INVALID_BASE, 0x570}, ++ [DBG_MIB_M0DR10] = { DBG_INVALID_BASE, 0x578}, ++ [DBG_MIB_M0DR11] = { DBG_INVALID_BASE, 0x574}, ++ [DBG_MIB_M0DR12] = { DBG_INVALID_BASE, 0x654}, ++ [DBG_WTBLON_WDUCR] = { DBG_INVALID_BASE, 0x200}, ++ [DBG_UWTBL_WDUCR] = { DBG_INVALID_BASE, 0x094}, ++ [DBG_PLE_DRR_TABLE_CTRL] = { DBG_INVALID_BASE, 0x490}, ++ [DBG_PLE_DRR_TABLE_RDATA] = { DBG_INVALID_BASE, 0x470}, ++ [DBG_PLE_PBUF_CTRL] = { DBG_INVALID_BASE, 0x004}, ++ [DBG_PLE_QUEUE_EMPTY] = { DBG_INVALID_BASE, 0x360}, ++ [DBG_PLE_FREEPG_CNT] = { DBG_INVALID_BASE, 0x380}, ++ [DBG_PLE_FREEPG_HEAD_TAIL] = { DBG_INVALID_BASE, 0x384}, ++ [DBG_PLE_PG_HIF_GROUP] = { DBG_INVALID_BASE, 0x00c}, ++ [DBG_PLE_HIF_PG_INFO] = { DBG_INVALID_BASE, 0x388}, ++ [DBG_PLE_PG_HIF_TXCMD_GROUP] = { DBG_INVALID_BASE, 0x014}, ++ [DBG_PLE_HIF_TXCMD_PG_INFO] = { DBG_INVALID_BASE, 0x390}, ++ [DBG_PLE_PG_CPU_GROUP] = { DBG_INVALID_BASE, 0x018}, ++ [DBG_PLE_CPU_PG_INFO] = { DBG_INVALID_BASE, 0x394}, ++ [DBG_PLE_FL_QUE_CTRL] = { DBG_INVALID_BASE, 0x3e0}, ++ [DBG_PLE_NATIVE_TXCMD_Q_EMPTY] = { DBG_INVALID_BASE, 0x370}, ++ [DBG_PLE_TXCMD_Q_EMPTY] = { DBG_INVALID_BASE, 0x36c}, ++ [DBG_PLE_AC_QEMPTY] = { DBG_INVALID_BASE, 0x600}, ++ [DBG_PLE_AC_OFFSET] = { DBG_INVALID_BASE, 0x080}, ++ [DBG_PLE_STATION_PAUSE] = { DBG_INVALID_BASE, 0x100}, ++ [DBG_PLE_DIS_STA_MAP] = { DBG_INVALID_BASE, 0x180}, ++ [DBG_PSE_PBUF_CTRL] = { DBG_INVALID_BASE, 0x004}, ++ [DBG_PSE_FREEPG_CNT] = { DBG_INVALID_BASE, 0x380}, ++ [DBG_PSE_FREEPG_HEAD_TAIL] = { DBG_INVALID_BASE, 0x384}, ++ [DBG_PSE_HIF0_PG_INFO] = { DBG_INVALID_BASE, 0x150}, ++ [DBG_PSE_PG_HIF1_GROUP] = { DBG_INVALID_BASE, 0x154}, ++ [DBG_PSE_HIF1_PG_INFO] = { DBG_INVALID_BASE, 0x160}, ++ [DBG_PSE_PG_CPU_GROUP] = { DBG_INVALID_BASE, 0x118}, ++ [DBG_PSE_CPU_PG_INFO] = { DBG_INVALID_BASE, 0x158}, ++ [DBG_PSE_PG_PLE_GROUP] = { DBG_INVALID_BASE, 0x11c}, ++ [DBG_PSE_PLE_PG_INFO] = { DBG_INVALID_BASE, 0x15c}, ++ [DBG_PSE_PG_LMAC0_GROUP] = { DBG_INVALID_BASE, 0x124}, ++ [DBG_PSE_LMAC0_PG_INFO] = { DBG_INVALID_BASE, 0x164}, ++ [DBG_PSE_PG_LMAC1_GROUP] = { DBG_INVALID_BASE, 0x128}, ++ [DBG_PSE_LMAC1_PG_INFO] = { DBG_INVALID_BASE, 0x168}, ++ [DBG_PSE_PG_LMAC2_GROUP] = { DBG_INVALID_BASE, 0x12c}, ++ [DBG_PSE_LMAC2_PG_INFO] = { DBG_INVALID_BASE, 0x16c}, ++ [DBG_PSE_PG_LMAC3_GROUP] = { DBG_INVALID_BASE, 0x130}, ++ [DBG_PSE_LMAC3_PG_INFO] = { DBG_INVALID_BASE, 0x17c}, ++ [DBG_PSE_PG_MDP_GROUP] = { DBG_INVALID_BASE, 0x134}, ++ [DBG_PSE_MDP_PG_INFO] = { DBG_INVALID_BASE, 0x174}, ++ [DBG_PSE_PG_PLE1_GROUP] = { DBG_INVALID_BASE, 0x120}, ++ [DBG_PSE_PLE1_PG_INFO] = { DBG_INVALID_BASE, 0x160}, ++ [DBG_AGG_AALCR0] = { DBG_INVALID_BASE, 0x028}, ++ [DBG_AGG_AALCR1] = { DBG_INVALID_BASE, 0x144}, ++ [DBG_AGG_AALCR2] = { DBG_INVALID_BASE, 0x14c}, ++ [DBG_AGG_AALCR3] = { DBG_INVALID_BASE, 0x154}, ++ [DBG_AGG_AALCR4] = { DBG_INVALID_BASE, 0x02c}, ++ [DBG_AGG_B0BRR0] = { DBG_INVALID_BASE, 0x08c}, ++ [DBG_AGG_B1BRR0] = { DBG_INVALID_BASE, 0x148}, ++ [DBG_AGG_B2BRR0] = { DBG_INVALID_BASE, 0x150}, ++ [DBG_AGG_B3BRR0] = { DBG_INVALID_BASE, 0x158}, ++ [DBG_AGG_AWSCR0] = { DBG_INVALID_BASE, 0x05c}, ++ [DBG_AGG_PCR0] = { DBG_INVALID_BASE, 0x06c}, ++ [DBG_AGG_TTCR0] = { DBG_INVALID_BASE, 0x07c}, ++ [DBG_MIB_M0ARNG0] = { DBG_INVALID_BASE, 0x0b0}, ++ [DBG_MIB_M0DR2] = { DBG_INVALID_BASE, 0x7dc}, ++ [DBG_MIB_M0DR13] = { DBG_INVALID_BASE, 0x7ec}, ++}; ++ ++static const struct __dbg_mask mt7915_dbg_mask[] = { ++ [DBG_MIB_M0SDR10_RX_MDRDY_COUNT]= {25, 0}, ++ [DBG_MIB_M0SDR14_AMPDU] = {23, 0}, ++ [DBG_MIB_M0SDR15_AMPDU_ACKED] = {23, 0}, ++ [DBG_MIB_RX_FCS_ERROR_COUNT] = {15, 0}, ++}; ++ ++static const struct __dbg_mask mt7916_dbg_mask[] = { ++ [DBG_MIB_M0SDR10_RX_MDRDY_COUNT]= {31, 0}, ++ [DBG_MIB_M0SDR14_AMPDU] = {31, 0}, ++ [DBG_MIB_M0SDR15_AMPDU_ACKED] = {31, 0}, ++ [DBG_MIB_RX_FCS_ERROR_COUNT] = {31, 16}, ++}; ++ ++/* used to differentiate between generations */ ++struct mt7915_dbg_reg_desc { ++ const u32 id; ++ const u32 *base_rev; ++ const struct __dbg_reg *reg_rev; ++ const struct __dbg_mask *mask_rev; ++}; ++ ++static const struct mt7915_dbg_reg_desc dbg_reg_s[] = { ++ { 0x7915, ++ mt7915_dbg_base, ++ mt7915_dbg_reg, ++ mt7915_dbg_mask ++ }, ++ { 0x7906, ++ mt7916_dbg_base, ++ mt7916_dbg_reg, ++ mt7916_dbg_mask ++ }, ++ { 0x7981, ++ mt7981_dbg_base, ++ mt7916_dbg_reg, ++ mt7916_dbg_mask ++ }, ++ { 0x7986, ++ mt7986_dbg_base, ++ mt7916_dbg_reg, ++ mt7916_dbg_mask ++ }, ++}; ++ ++struct bin_debug_hdr { ++ __le32 magic_num; ++ __le16 serial_id; ++ __le16 msg_type; ++ __le16 len; ++ __le16 des_len; /* descriptor len for rxd */ ++} __packed; ++ ++/* fw wm info related strcture */ ++struct cos_msg_trace_t { ++ u32 dest_id; ++ u8 msg_id; ++ u32 pcount; ++ u32 qread; ++ u32 ts_enq; ++ u32 ts_deq; ++ u32 ts_finshq; ++}; ++ ++struct cos_task_info_struct { ++ u32 task_name_ptr; ++ u32 task_qname_ptr; ++ u32 task_priority; ++ u16 task_stack_size; ++ u8 task_ext_qsize; ++ u32 task_id; ++ u32 task_ext_qid; ++ u32 task_main_func; ++ u32 task_init_func; ++}; ++ ++struct cos_program_trace_t{ ++ u32 _dest_id; ++ u32 _msg_id; ++ u32 _msg_sn; ++ u32 _ts_gpt2; ++ u32 _LP; ++ char _name[12]; ++} ; ++ ++struct mt7915_cos_program_trace_t{ ++ u32 _dest_id; ++ u32 _msg_id; ++ u32 _msg_sn; ++ u32 _ts_gpt2; ++ u32 _ts_gpt4; ++ u32 _LP; ++ char _name[12]; ++} ; ++ ++struct cos_msg_type { ++ u32 finish_cnt; ++ u32 exe_time; ++ u32 exe_peak; ++}; ++ ++struct cos_task_type{ ++ u32 tc_stack_start; ++ u32 tc_stack_end; ++ u32 tc_stack_pointer; ++ u32 tc_stack_size; ++ u32 tc_schedule_count; ++ u8 tc_status; ++ u8 tc_priority; ++ u8 tc_weight; ++ u8 RSVD[28]; ++ u32 tc_entry_func; ++ u32 tc_exe_start; ++ u32 tc_exe_time; ++ u32 tc_exe_peak; ++ u32 tc_pcount; ++}; ++ ++#define __DBG_REG_MAP(_dev, id, ofs) ((_dev)->dbg_reg->base_rev[(id)] + (ofs)) ++#define __DBG_REG_BASE(_dev, id) ((_dev)->dbg_reg->reg_rev[(id)].base) ++#define __DBG_REG_OFFS(_dev, id) ((_dev)->dbg_reg->reg_rev[(id)].offs) ++ ++#define __DBG_MASK(_dev, id) GENMASK((_dev)->dbg_reg->mask_rev[(id)].end, \ ++ (_dev)->dbg_reg->mask_rev[(id)].start) ++#define __DBG_REG(_dev, id) __DBG_REG_MAP((_dev), __DBG_REG_BASE((_dev), (id)), \ ++ __DBG_REG_OFFS((_dev), (id))) ++ ++#define __DBG_FIELD_GET(id, _reg) (((_reg) & __DBG_MASK(dev, (id))) >> \ ++ dev->dbg_reg->mask_rev[(id)].start) ++#define __DBG_FIELD_PREP(id, _reg) (((_reg) << dev->dbg_reg->mask_rev[(id)].start) & \ ++ __DBG_MASK(dev, (id))) ++ ++ ++#define MT_DBG_TX_RING_BASE __DBG_REG(dev, DBG_TX_RING_BASE) ++#define MT_DBG_RX_EVENT_RING_BASE __DBG_REG(dev, DBG_RX_EVENT_RING_BASE) ++#define MT_DBG_RX_STS_RING_BASE __DBG_REG(dev, DBG_RX_STS_RING_BASE) ++#define MT_DBG_RX_DATA_RING_BASE __DBG_REG(dev, DBG_RX_DATA_RING_BASE) ++#define MT_DBG_WFDMA_WED_TX_CTRL_BASE __DBG_REG(dev, DBG_WFDMA_WED_TX_CTRL) ++#define MT_DBG_WFDMA_WED_RX_CTRL_BASE __DBG_REG(dev, DBG_WFDMA_WED_RX_CTRL) ++ ++#define MT_DBG_TX_RING_CTRL(n) (MT_DBG_TX_RING_BASE + (0x10 * (n))) ++#define MT_DBG_RX_DATA_RING_CTRL(n) (MT_DBG_RX_DATA_RING_BASE + (0x10 * (n))) ++#define MT_DBG_RX_EVENT_RING_CTRL(n) (MT_DBG_RX_EVENT_RING_BASE + (0x10 * (n))) ++ ++#define MT_DBG_WFDMA_WED_TX_CTRL(n) (MT_DBG_WFDMA_WED_TX_CTRL_BASE + (0x10 * (n))) ++#define MT_DBG_WFDMA_WED_RX_CTRL(n) (MT_DBG_WFDMA_WED_RX_CTRL_BASE + (0x10 * (n))) ++/* WFDMA COMMON */ ++#define MT_DBG_INT_SOURCE_CSR __DBG_REG(dev, DBG_INT_SOURCE_CSR) ++#define MT_DBG_INT_MASK_CSR __DBG_REG(dev, DBG_INT_MASK_CSR) ++#define MT_DBG_INT1_SOURCE_CSR __DBG_REG(dev, DBG_INT1_SOURCE_CSR) ++#define MT_DBG_INT1_MASK_CSR __DBG_REG(dev, DBG_INT1_MASK_CSR) ++ ++/* WFDMA0 */ ++#define MT_DBG_WFDMA0(_ofs) __DBG_REG_MAP(dev, MT_DBG_WFDMA0_BASE, (_ofs)) ++ ++#define MT_DBG_WFDMA0_INT_SOURCE_CSR MT_DBG_WFDMA0(0x200) ++#define MT_DBG_WFDMA0_INT_MASK_CSR MT_DBG_WFDMA0(0x204) ++ ++#define MT_DBG_WFDMA0_GLO_CFG MT_DBG_WFDMA0(0x208) ++#define MT_DBG_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0) ++#define MT_DBG_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) ++#define MT_DBG_WFDMA0_GLO_CFG_TX_BUSY_MASK BIT(1) ++#define MT_DBG_WFDMA0_GLO_CFG_RX_BUSY_MASK BIT(3) ++ ++ ++/* WFDMA1 */ ++#define MT_DBG_WFDMA1(_ofs) __DBG_REG_MAP(dev, MT_DBG_WFDMA1_BASE, (_ofs)) ++#define MT_DBG_WFDMA1_INT_SOURCE_CSR MT_DBG_WFDMA1(0x200) ++#define MT_DBG_WFDMA1_INT_MASK_CSR MT_DBG_WFDMA1(0x204) ++ ++#define MT_DBG_WFDMA1_GLO_CFG MT_DBG_WFDMA1(0x208) ++ ++#define MT_DBG_WFDMA1_GLO_CFG_TX_DMA_EN BIT(0) ++#define MT_DBG_WFDMA1_GLO_CFG_RX_DMA_EN BIT(2) ++#define MT_DBG_WFDMA1_GLO_CFG_TX_BUSY_MASK BIT(1) ++#define MT_DBG_WFDMA1_GLO_CFG_RX_BUSY_MASK BIT(3) ++ ++/* WFDMA0 PCIE1 */ ++#define MT_DBG_WFDMA0_PCIE1(_ofs) __DBG_REG_MAP(dev, MT_DBG_WFDMA0_PCIE1_BASE, (_ofs)) ++ ++#define MT_DBG_WFDMA0_PCIE1_INT_SOURCE_CSR MT_DBG_WFDMA0_PCIE1(0x200) ++#define MT_DBG_WFDMA0_PCIE1_INT_MASK_CSR MT_DBG_WFDMA0_PCIE1(0x204) ++#define MT_DBG_WFDMA0_PCIE1_GLO_CFG MT_DBG_WFDMA0_PCIE1(0x208) ++#define MT_DBG_WFDMA0_PCIE1_RX1_CTRL0 MT_DBG_WFDMA1_PCIE1(0x510) ++ ++#define MT_DBG_WFDMA0_PCIE1_GLO_CFG_TX_DMA_EN BIT(0) ++#define MT_DBG_WFDMA0_PCIE1_GLO_CFG_TX_BUSY_MASK BIT(1) ++#define MT_DBG_WFDMA0_PCIE1_GLO_CFG_RX_DMA_EN BIT(2) ++#define MT_DBG_WFDMA0_PCIE1_GLO_CFG_RX_BUSY_MASK BIT(3) ++ ++/* WFDMA1 PCIE1 */ ++#define MT_DBG_WFDMA1_PCIE1(_ofs) __DBG_REG_MAP(dev, MT_DBG_WFDMA1_PCIE1_BASE, (_ofs)) ++#define MT_DBG_WFDMA1_PCIE1_INT_SOURCE_CSR MT_DBG_WFDMA1_PCIE1(0x200) ++#define MT_DBG_WFDMA1_PCIE1_INT_MASK_CSR MT_DBG_WFDMA1_PCIE1(0x204) ++#define MT_DBG_WFDMA1_PCIE1_GLO_CFG MT_DBG_WFDMA1_PCIE1(0x208) ++#define MT_DBG_WFDMA1_PCIE1_TX19_CTRL0 MT_DBG_WFDMA1_PCIE1(0x330) ++#define MT_DBG_WFDMA1_PCIE1_RX2_CTRL0 MT_DBG_WFDMA1_PCIE1(0x520) ++ ++#define MT_DBG_WFDMA1_PCIE1_GLO_CFG_TX_DMA_EN BIT(0) ++#define MT_DBG_WFDMA1_PCIE1_GLO_CFG_TX_BUSY_MASK BIT(1) ++#define MT_DBG_WFDMA1_PCIE1_GLO_CFG_RX_DMA_EN BIT(2) ++#define MT_DBG_WFDMA1_PCIE1_GLO_CFG_RX_BUSY_MASK BIT(3) ++ ++#define MT_DBG_WFDMA_HOST_DMA0_GLO_CFG_RX_DMA_EN_MASK BIT(2) ++#define MT_DBG_WFDMA_HOST_DMA0_GLO_CFG_TX_DMA_EN_MASK BIT(0) ++#define MT_DBG_WFDMA_HOST_DMA0_GLO_CFG_RX_DMA_BUSY_MASK BIT(3) ++#define MT_DBG_WFDMA_HOST_DMA0_GLO_CFG_TX_DMA_BUSY_MASK BIT(1) ++ ++ ++/* WF DMA TOP: band 0(0x820E7000),band 1(0x820F7000) */ ++#define MT_DBG_WF_DMA_BASE(_band) ((_band) ? 0x820F7000 : 0x820E7000) ++#define MT_DBG_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs)) ++ ++#define MT_DBG_DMA_DCR0(_band) MT_DBG_WF_DMA((_band), 0x000) ++#define MT_DBG_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3) ++#define MT_DBG_DMA_DCR0_RXD_G5_EN BIT(23) ++ ++#define MT_DBG_DMA_ICSC_FR0(_band) MT_DBG_WF_DMA((_band), __DBG_REG_OFFS(dev, DBG_DMA_ICSC_FR0)) ++#define MT_DBG_DMA_ICSC_FR0_RXBF_EN BIT(25) ++#define MT_DBG_DMA_ICSC_FR0_EN BIT(24) ++#define MT_DBG_DMA_ICSC_FR0_TOUT_MASK GENMASK(23, 16) ++#define MT_DBG_DMA_ICSC_FR0_PID_MASK GENMASK(9, 8) ++#define MT_DBG_DMA_ICSC_FR0_QID_MASK GENMASK(6, 0) ++ ++#define MT_DBG_DMA_ICSC_FR1(_band) MT_DBG_WF_DMA((_band), __DBG_REG_OFFS(dev, DBG_DMA_ICSC_FR1)) ++#define MT_DBG_DMA_ICSC_FR1_AGG_SIZE_MASK GENMASK(26, 16) ++#define MT_DBG_DMA_ICSC_FR1_MAX_FRAME_SIZE_MASK GENMASK(10, 0) ++ ++/* TMAC: band 0(0x820e4000), band 1(0x820f4000) */ ++#define MT_DBG_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000) ++#define MT_DBG_WF_TMAC(_band, ofs) (MT_DBG_WF_TMAC_BASE(_band) + (ofs)) ++ ++#define MT_DBG_TMAC_ICSCR0(_band) MT_DBG_WF_TMAC((_band), __DBG_REG_OFFS(dev, DBG_TMAC_ICSCR0)) ++#define MT_DBG_TMAC_ICSCR0_ICSRPT_EN BIT(0) ++ ++/* RMAC: band 0(0x820E5000), band 1(0x820f5000) */ ++#define MT_DBG_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820E5000) ++#define MT_DBG_WF_RMAC(_band, ofs) (MT_DBG_WF_RMAC_BASE(_band) + (ofs)) ++ ++#define MT_DBG_RMAC_RXICSRPT(_band) MT_DBG_WF_RMAC((_band), __DBG_REG_OFFS(dev, DBG_RMAC_RXICSRPT)) ++#define MT_DBG_RMAC_RXICSRPT_ICSRPT_EN BIT(0) ++ ++/* MIB: band 0(0x820ed000), band 1(0x820fd000) */ ++#define MT_DBG_MIB_BASE(_band) ((_band) ? 0x820fd000 : 0x820ed000) ++#define MT_DBG_MIB(_band, ofs) (MT_DBG_MIB_BASE(_band) + (ofs)) ++ ++ ++#define MT_DBG_MIB_M0SCR0(_band) MT_DBG_MIB((_band), 0x00) ++#define MT_DBG_MIB_M0PBSCR(_band) MT_DBG_MIB((_band), 0x04) ++ ++#define MT_DBG_MIB_M0SDR0(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR0)) ++#define MT_DBG_MIB_M0SDR3(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR3)) ++#define MT_DBG_MIB_RX_FCS_ERROR_COUNT_MASK __DBG_MASK(dev, DBG_MIB_RX_FCS_ERROR_COUNT) ++#define MT_DBG_MIB_M0SDR4(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR4)) ++#define MT_DBG_MIB_M0SDR5(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR5)) ++#define MT_DBG_MIB_M0SDR6(_band) MT_DBG_MIB((_band), 0x20) ++#define MT_DBG_MIB_M0SDR7(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR7)) ++#define MT_DBG_MIB_M0SDR8(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR8)) ++#define MT_DBG_MIB_M0SDR9(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR9)) ++#define MT_DBG_MIB_M0SDR10(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR10)) ++#define MT_DBG_MIB_M0SDR10_RX_MDRDY_COUNT_MASK __DBG_MASK(dev, DBG_MIB_M0SDR10_RX_MDRDY_COUNT) ++#define MT_DBG_MIB_M0SDR11(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR11)) ++ ++#define MT_DBG_MIB_M0SDR12(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR12)) ++ ++#define MT_DBG_MIB_M0SDR14(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR14)) ++#define MT_DBG_MIB_M0SDR14_AMPDU_MASK __DBG_MASK(dev, DBG_MIB_M0SDR14_AMPDU) ++#define MT_DBG_MIB_M0SDR15(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR15)) ++#define MT_DBG_MIB_M0SDR15_AMPDU_ACKED_MASK __DBG_MASK(dev, DBG_MIB_M0SDR15_AMPDU_ACKED) ++#define MT_DBG_MIB_M0SDR16(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR16)) ++#define MT_DBG_MIB_M0SDR17(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR17)) ++#define MT_DBG_MIB_M0SDR18(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR18)) ++#define MT_DBG_MIB_M0SDR19(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR19)) ++#define MT_DBG_MIB_M0SDR20(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR20)) ++#define MT_DBG_MIB_M0SDR21(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR21)) ++#define MT_DBG_MIB_M0SDR22(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR22)) ++#define MT_DBG_MIB_M0SDR23(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0SDR23)) ++#define MT_DBG_MIB_M0DR0(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR0)) ++#define MT_DBG_MIB_M0DR1(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR1)) ++ ++#define MT_DBG_MIB_MUBF(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_MUBF)) ++#define MT_DBG_MIB_M0DR6(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR6)) ++#define MT_DBG_MIB_M0DR7(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR7)) ++#define MT_DBG_MIB_M0DR8(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR8)) ++#define MT_DBG_MIB_M0DR9(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR9)) ++#define MT_DBG_MIB_M0DR10(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR10)) ++#define MT_DBG_MIB_M0DR11(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR11)) ++ #define MT_DBG_MIB_M0DR12(_band) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR12)) ++ ++/* WTBLON TOP: 0x820D4000/pcie(0x34000) rbus(0x434000) */ ++#define MT_DBG_WTBLON_TOP_BASE 0x820D4000 ++#define MT_DBG_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) ++#define MT_DBG_WTBLON_TOP_WDUCR MT_DBG_WTBLON_TOP(__DBG_REG_OFFS(dev, DBG_WTBLON_WDUCR)) ++#define MT_DBG_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) ++ ++#define WF_WTBLON_TOP_B0BTCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1000) // 5000 ++#define WF_WTBLON_TOP_B0BTBCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1010) // 5010 ++#define WF_WTBLON_TOP_B0BRCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1020) // 5020 ++#define WF_WTBLON_TOP_B0BRBCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1030) // 5030 ++#define WF_WTBLON_TOP_B0BTDCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1040) // 5040 ++#define WF_WTBLON_TOP_B0BRDCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1050) // 5050 ++#define WF_WTBLON_TOP_B0MBTCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1100) // 5100 ++#define WF_WTBLON_TOP_B0MBTBCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1140) // 5140 ++#define WF_WTBLON_TOP_B0MBRCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1180) // 5180 ++#define WF_WTBLON_TOP_B0MBRBCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x11C0) // 51C0 ++ ++#define WF_WTBLON_TOP_B1BTCRn_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x1800) // 5800 ++ ++/* WTBLON TOP: 0x820C4000/pcie(0xa8000) rbus(0x4a8000) */ ++#define MT_DBG_UWTBL_TOP_BASE 0x820C4000 ++#define MT_DBG_UWTBL_TOP(ofs) (MT_DBG_UWTBL_TOP_BASE + (ofs)) ++ ++#define MT_DBG_UWTBL_TOP_WDUCR MT_DBG_UWTBL_TOP(__DBG_REG_OFFS(dev, DBG_UWTBL_WDUCR)) ++ ++#define MT_UWTBL_TOP_WDUCR_TARGET BIT(31) ++#define MT_UWTBL_TOP_WDUCR_GROUP GENMASK(3, 0) ++ ++ ++/* WTBL : 0x820D8000/pcie(0x38000) rbus(0x438000) */ ++#define MT_DBG_WTBL_BASE 0x820D8000 ++ ++/* PLE related CRs. */ ++#define MT_DBG_PLE_BASE 0x820C0000 ++#define MT_DBG_PLE(ofs) (MT_DBG_PLE_BASE + (ofs)) ++ ++#define MT_DBG_PLE_DRR_TAB_CTRL MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_DRR_TABLE_CTRL)) ++#define MT_DBG_PLE_DRR_TAB_RD_OFS __DBG_REG_OFFS(dev, DBG_PLE_DRR_TABLE_RDATA) ++ ++#define MT_DBG_PLE_DRR_TABLE_RDATA0 MT_DBG_PLE(MT_DBG_PLE_DRR_TAB_RD_OFS + 0x0) ++#define MT_DBG_PLE_DRR_TABLE_RDATA1 MT_DBG_PLE(MT_DBG_PLE_DRR_TAB_RD_OFS + 0x4) ++#define MT_DBG_PLE_DRR_TABLE_RDATA2 MT_DBG_PLE(MT_DBG_PLE_DRR_TAB_RD_OFS + 0x8) ++#define MT_DBG_PLE_DRR_TABLE_RDATA3 MT_DBG_PLE(MT_DBG_PLE_DRR_TAB_RD_OFS + 0xc) ++#define MT_DBG_PLE_DRR_TABLE_RDATA4 MT_DBG_PLE(MT_DBG_PLE_DRR_TAB_RD_OFS + 0x10) ++#define MT_DBG_PLE_DRR_TABLE_RDATA5 MT_DBG_PLE(MT_DBG_PLE_DRR_TAB_RD_OFS + 0x14) ++#define MT_DBG_PLE_DRR_TABLE_RDATA6 MT_DBG_PLE(MT_DBG_PLE_DRR_TAB_RD_OFS + 0x18) ++#define MT_DBG_PLE_DRR_TABLE_RDATA7 MT_DBG_PLE(MT_DBG_PLE_DRR_TAB_RD_OFS+ 0x1c) ++ ++#define MT_DBG_PLE_PBUF_CTRL_ADDR MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_PBUF_CTRL)) ++#define MT_DBG_PLE_QUEUE_EMPTY MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_QUEUE_EMPTY)) ++#define MT_DBG_PLE_FREEPG_CNT MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_FREEPG_CNT)) ++#define MT_DBG_PLE_FREEPG_HEAD_TAIL MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_FREEPG_HEAD_TAIL)) ++#define MT_DBG_PLE_PG_HIF_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_PG_HIF_GROUP)) ++#define MT_DBG_PLE_HIF_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_HIF_PG_INFO)) ++#define MT_DBG_PLE_PG_HIF_TXCMD_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_PG_HIF_TXCMD_GROUP)) ++#define MT_DBG_PLE_HIF_TXCMD_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_HIF_TXCMD_PG_INFO)) ++#define MT_DBG_PLE_PG_CPU_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_PG_CPU_GROUP)) ++#define MT_DBG_PLE_CPU_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_CPU_PG_INFO)) ++#define PLE_FL_QUE_CTRL_OFFSET __DBG_REG_OFFS(dev, DBG_PLE_FL_QUE_CTRL) ++#define MT_DBG_PLE_FL_QUE_CTRL0 MT_DBG_PLE(PLE_FL_QUE_CTRL_OFFSET + 0x0) ++#define MT_DBG_PLE_FL_QUE_CTRL1 MT_DBG_PLE(PLE_FL_QUE_CTRL_OFFSET + 0x4) ++#define MT_DBG_PLE_FL_QUE_CTRL2 MT_DBG_PLE(PLE_FL_QUE_CTRL_OFFSET + 0x8) ++#define MT_DBG_PLE_FL_QUE_CTRL3 MT_DBG_PLE(PLE_FL_QUE_CTRL_OFFSET + 0xc) ++#define MT_DBG_PLE_NATIVE_TXCMD_Q_EMPTY MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_NATIVE_TXCMD_Q_EMPTY)) ++#define MT_DBG_PLE_TXCMD_Q_EMPTY MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_TXCMD_Q_EMPTY)) ++ ++#define MT_DBG_PLE_PBUF_CTRL_PAGE_SIZE_MASK BIT(31) ++#define MT_DBG_PLE_PBUF_CTRL_OFFSET_MASK GENMASK(25, 17) ++#define MT_DBG_PLE_PBUF_CTRL_TOTAL_PAGE_NUM_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_FREEPG_CNT_FREEPG_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PLE_FREEPG_CNT_FFA_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK GENMASK(11, 0) ++#define MT_DBG_PLE_PG_HIF_GROUP_HIF_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_PG_HIF_GROUP_HIF_MIN_QUOTA_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_HIF_PG_INFO_HIF_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_HIF_PG_INFO_HIF_RSV_CNT_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_HIF_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_HIF_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_CPU_PG_INFO_CPU_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_CPU_PG_INFO_CPU_RSV_CNT_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_Q_EMPTY_ALL_AC_EMPTY_MASK BIT(24) ++#define MT_DBG_PLE_FL_QUE_CTRL0_EXECUTE_MASK BIT(31) ++#define MT_DBG_PLE_FL_QUE_CTRL0_Q_BUF_QID_MASK GENMASK(30, 24) ++ ++#define MT_PLE_FL_QUE_CTRL0_Q_BUF_QID_SHFT 24 ++#define MT_PLE_FL_QUE_CTRL0_Q_BUF_PID_SHFT 10 ++ ++#define MT_DBG_PLE_FL_QUE_CTRL2_Q_TAIL_FID_MASK GENMASK(27, 16) ++#define MT_DBG_PLE_FL_QUE_CTRL2_Q_HEAD_FID_MASK GENMASK(11, 0) ++#define MT_DBG_PLE_FL_QUE_CTRL3_Q_PKT_NUM_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PLE_STATION_PAUSE(n) MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_STATION_PAUSE) + ((n) << 2)) ++#define MT_DBG_PLE_DIS_STA_MAP(n) MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_DIS_STA_MAP) + ((n) << 2)) ++#define MT_DBG_PLE_AC_QEMPTY(ac, n) MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PLE_AC_QEMPTY) + \ ++ __DBG_REG_OFFS(dev, DBG_PLE_AC_OFFSET) * (ac) + ((n) << 2)) ++ ++#define MT_DBG_PLE_AMSDU_PACK_MSDU_CNT(n) MT_DBG_PLE(0x10e0 + ((n) << 2)) ++ ++/* pseinfo related CRs. */ ++#define MT_DBG_PSE_BASE 0x820C8000 ++#define MT_DBG_PSE(ofs) (MT_DBG_PSE_BASE + (ofs)) ++ ++#define MT_DBG_PSE_PBUF_CTRL MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PBUF_CTRL)) ++#define MT_DBG_PSE_QUEUE_EMPTY MT_DBG_PSE(0x0b0) ++#define MT_DBG_PSE_FREEPG_CNT MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_FREEPG_CNT)) ++#define MT_DBG_PSE_FREEPG_HEAD_TAIL MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_FREEPG_HEAD_TAIL)) ++#define MT_DBG_PSE_PG_HIF0_GROUP MT_DBG_PSE(0x110) ++#define MT_DBG_PSE_HIF0_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_HIF0_PG_INFO)) ++#define MT_DBG_PSE_PG_HIF1_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_HIF1_GROUP)) ++#define MT_DBG_PSE_HIF1_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_HIF1_PG_INFO)) ++#define MT_DBG_PSE_PG_CPU_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_CPU_GROUP)) ++#define MT_DBG_PSE_CPU_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_CPU_PG_INFO)) ++#define MT_DBG_PSE_PG_LMAC0_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC0_GROUP)) ++#define MT_DBG_PSE_LMAC0_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC0_PG_INFO)) ++#define MT_DBG_PSE_PG_LMAC1_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC1_GROUP)) ++#define MT_DBG_PSE_LMAC1_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC1_PG_INFO)) ++#define MT_DBG_PSE_PG_LMAC2_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC2_GROUP)) ++#define MT_DBG_PSE_LMAC2_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC2_PG_INFO)) ++#define MT_DBG_PSE_PG_PLE_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_PLE_GROUP)) ++#define MT_DBG_PSE_PLE_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PLE_PG_INFO)) ++#define MT_DBG_PSE_PG_LMAC3_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC3_GROUP)) ++#define MT_DBG_PSE_LMAC3_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC3_PG_INFO)) ++#define MT_DBG_PSE_PG_MDP_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_MDP_GROUP)) ++#define MT_DBG_PSE_MDP_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_MDP_PG_INFO)) ++#define MT_DBG_PSE_PG_PLE1_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_PLE1_GROUP)) ++#define MT_DBG_PSE_PLE1_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PLE1_PG_INFO)) ++ ++#define MT_DBG_PSE_PBUF_CTRL_PAGE_SIZE_CFG_MASK BIT(31) ++#define MT_DBG_PSE_PBUF_CTRL_PBUF_OFFSET_MASK GENMASK(25, 17) ++#define MT_DBG_PSE_PBUF_CTRL_TOTAL_PAGE_NUM_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_QUEUE_EMPTY_RLS_Q_EMTPY_MASK BIT(31) ++#define MT_DBG_PSE_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_MASK BIT(23) ++#define MT_DBG_PSE_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_MASK BIT(22) ++#define MT_DBG_PSE_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_MASK BIT(21) ++#define MT_DBG_PSE_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_SHFT BIT(20) ++#define MT_DBG_PSE_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_MASK BIT(19) ++#define MT_DBG_PSE_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_MASK BIT(18) ++#define MT_DBG_PSE_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_MASK BIT(17) ++#define MT_DBG_PSE_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_MASK BIT(16) ++#define MT_DBG_PSE_QUEUE_EMPTY_HIF_5_EMPTY_MASK BIT(13) ++#define MT_DBG_PSE_QUEUE_EMPTY_HIF_4_EMPTY_MASK BIT(12) ++#define MT_DBG_PSE_QUEUE_EMPTY_HIF_3_EMPTY_MASK BIT(11) ++#define MT_DBG_PSE_QUEUE_EMPTY_HIF_2_EMPTY_MASK BIT(10) ++#define MT_DBG_PSE_QUEUE_EMPTY_HIF_1_EMPTY_MASK BIT(9) ++#define MT_DBG_PSE_QUEUE_EMPTY_HIF_0_EMPTY_MASK BIT(8) ++#define MT_DBG_PSE_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK BIT(3) ++#define MT_DBG_PSE_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK BIT(2) ++#define MT_DBG_PSE_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK BIT(1) ++#define MT_DBG_PSE_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK BIT(0) ++#define MT_DBG_PSE_FREEPG_CNT_FFA_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_FREEPG_CNT_FREEPG_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_HIF0_PG_INFO_HIF0_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_HIF0_PG_INFO_HIF0_RSV_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_HIF1_GROUP_HIF1_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PG_HIF1_GROUP_HIF1_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_HIF1_PG_INFO_HIF1_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_HIF1_PG_INFO_HIF1_RSV_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_CPU_PG_INFO_CPU_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_CPU_PG_INFO_CPU_RSV_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_PLE_GROUP_PLE_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PG_PLE_GROUP_PLE_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PLE_PG_INFO_PLE_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PLE_PG_INFO_PLE_RSV_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_LMAC0_PG_INFO_LMAC0_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_LMAC0_PG_INFO_LMAC0_RSV_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_LMAC1_PG_INFO_LMAC1_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_LMAC1_PG_INFO_LMAC1_RSV_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_LMAC2_PG_INFO_LMAC2_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_LMAC2_PG_INFO_LMAC2_RSV_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_LMAC3_PG_INFO_LMAC3_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_LMAC3_PG_INFO_LMAC3_RSV_CNT_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_PG_MDP_GROUP_MDP_MAX_QUOTA_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_PG_MDP_GROUP_MDP_MIN_QUOTA_MASK GENMASK(11, 0) ++#define MT_DBG_PSE_MDP_PG_INFO_MDP_SRC_CNT_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_MDP_PG_INFO_MDP_RSV_CNT_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PSE_FL_QUE_CTRL_0_ADDR MT_DBG_PLE(0x1b0) ++#define MT_DBG_PSE_FL_QUE_CTRL_0_EXECUTE_MASK BIT(31) ++#define MT_DBG_PSE_FL_QUE_CTRL_0_Q_BUF_QID_SHFT 24 ++#define MT_DBG_PSE_FL_QUE_CTRL_0_Q_BUF_PID_SHFT 10 ++#define MT_DBG_PSE_FL_QUE_CTRL_0_Q_BUF_WLANID_MASK GENMASK(9, 0) ++ ++#define MT_DBG_PSE_FL_QUE_CTRL_2_ADDR MT_DBG_PLE(0x1b8) ++#define MT_DBG_PSE_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK GENMASK(27, 16) ++#define MT_DBG_PSE_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK GENMASK(11, 0) ++ ++#define MT_DBG_PSE_FL_QUE_CTRL_3_ADDR MT_DBG_PLE(0x1bc) ++#define MT_DBG_PSE_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK GENMASK(11, 0) ++ ++ ++/* AGG */ ++#define MT_DBG_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000) ++#define MT_DBG_AGG(_band, ofs) (MT_DBG_AGG_BASE(_band) + (ofs)) ++ ++#define MT_DBG_AGG_AALCR0(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_AALCR0)) ++#define MT_DBG_AGG_AALCR1(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_AALCR1)) ++#define MT_DBG_AGG_AALCR2(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_AALCR2)) ++#define MT_DBG_AGG_AALCR3(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_AALCR3)) ++#define MT_DBG_AGG_AALCR4(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_AALCR4)) ++#define MT_DBG_AGG_B0BRR0(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_B0BRR0)) ++#define MT_DBG_AGG_B1BRR0(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_B1BRR0)) ++#define MT_DBG_AGG_B2BRR0(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_B2BRR0)) ++#define MT_DBG_AGG_B3BRR0(_band) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_B3BRR0)) ++#define MT_DBG_AGG_AWSCR(_band, n) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_AWSCR0) + ((n) << 2)) ++#define MT_DBG_AGG_PCR(_band, n) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_PCR0) + ((n) << 2)) ++#define MT_DBG_AGG_TTCR(_band, n) MT_DBG_AGG((_band), __DBG_REG_OFFS(dev, DBG_AGG_TTCR0) + ((n) << 2)) ++#define MT_DBG_MIB_M0ARNG(_band, n) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0ARNG0) + ((n) << 2)) ++#define MT_DBG_MIB_M0DR2(_band, n) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR2) + ((n) << 2)) ++#define MT_DBG_MIB_M0DR13(_band, n) MT_DBG_MIB((_band), __DBG_REG_OFFS(dev, DBG_MIB_M0DR13) + ((n) << 2)) ++ ++#define MT_DBG_AGG_AALCR_ACx3_AGG_LIMIT_MASK GENMASK(31, 24) ++#define MT_DBG_AGG_AALCR_ACx2_AGG_LIMIT_MASK GENMASK(23, 16) ++#define MT_DBG_AGG_AALCR_ACx1_AGG_LIMIT_MASK GENMASK(15, 8) ++#define MT_DBG_AGG_AALCR_ACx0_AGG_LIMIT_MASK GENMASK(7, 0) ++#define MT_DBG_AGG_AALCR4_ALTX0_AGG_LIMIT_MASK GENMASK(7, 0) ++ ++#define MT_DBG_AGG_AWSCR0_WINSIZE3_MASK GENMASK(31, 24) ++#define MT_DBG_AGG_AWSCR0_WINSIZE2_MASK GENMASK(23, 16) ++#define MT_DBG_AGG_AWSCR0_WINSIZE1_MASK GENMASK(15, 8) ++#define MT_DBG_AGG_AWSCR0_WINSIZE0_MASK GENMASK(7, 0) ++ ++#define MT_DBG_AGG_AWSCR1_WINSIZE7_MASK GENMASK(31, 24) ++#define MT_DBG_AGG_AWSCR1_WINSIZE6_MASK GENMASK(23, 16) ++#define MT_DBG_AGG_AWSCR1_WINSIZE5_MASK GENMASK(15, 8) ++#define MT_DBG_AGG_AWSCR1_WINSIZE4_MASK GENMASK(7, 0) ++ ++#define MT_DBG_AGG_AWSCR2_WINSIZEB_MASK GENMASK(31, 24) ++#define MT_DBG_AGG_AWSCR2_WINSIZEA_MASK GENMASK(23, 16) ++#define MT_DBG_AGG_AWSCR2_WINSIZE9_MASK GENMASK(15, 8) ++#define MT_DBG_AGG_AWSCR2_WINSIZE8_MASK GENMASK(7, 0) ++ ++#define MT_DBG_AGG_AWSCR3_WINSIZEE_MASK GENMASK(23, 16) ++#define MT_DBG_AGG_AWSCR3_WINSIZED_MASK GENMASK(15, 8) ++#define MT_DBG_AGG_AWSCR3_WINSIZEC_MASK GENMASK(7, 0) ++ ++#define MT_DBG_MIB_M0ARNG0_AGG_RANG_SEL3_MASK GENMASK(31, 24) ++#define MT_DBG_MIB_M0ARNG0_AGG_RANG_SEL2_MASK GENMASK(23, 16) ++#define MT_DBG_MIB_M0ARNG0_AGG_RANG_SEL1_MASK GENMASK(15, 8) ++#define MT_DBG_MIB_M0ARNG0_AGG_RANG_SEL0_MASK GENMASK(7, 0) ++ ++#define MT_DBG_MIB_M0ARNG1_AGG_RANG_SEL7_MASK GENMASK(31, 24) ++#define MT_DBG_MIB_M0ARNG1_AGG_RANG_SEL6_MASK GENMASK(23, 16) ++#define MT_DBG_MIB_M0ARNG1_AGG_RANG_SEL5_MASK GENMASK(15, 8) ++#define MT_DBG_MIB_M0ARNG1_AGG_RANG_SEL4_MASK GENMASK(7, 0) ++ ++#define MT_DBG_MIB_M0ARNG2_AGG_RANG_SEL11_MASK GENMASK(31, 24) ++#define MT_DBG_MIB_M0ARNG2_AGG_RANG_SEL10_MASK GENMASK(23, 16) ++#define MT_DBG_MIB_M0ARNG2_AGG_RANG_SEL9_MASK GENMASK(15, 8) ++#define MT_DBG_MIB_M0ARNG2_AGG_RANG_SEL8_MASK GENMASK(7, 0) ++ ++#define MT_DBG_MIB_M0ARNG3_AGG_RANG_SEL14_MASK GENMASK(23, 16) ++#define MT_DBG_MIB_M0ARNG3_AGG_RANG_SEL13_MASK GENMASK(15, 8) ++#define MT_DBG_MIB_M0ARNG3_AGG_RANG_SEL12_MASK GENMASK(7, 0) ++ ++#define MT_DBG_MIB_M0DR2_TRX_AGG_RANGE1_CNT_MASK GENMASK(31, 16) ++#define MT_DBG_MIB_M0DR2_TRX_AGG_RANGE0_CNT_MASK GENMASK(15, 0) ++#define MT_DBG_MIB_M0DR3_TRX_AGG_RANGE3_CNT_MASK GENMASK(31, 16) ++#define MT_DBG_MIB_M0DR3_TRX_AGG_RANGE2_CNT_MASK GENMASK(15, 0) ++#define MT_DBG_MIB_M0DR4_TRX_AGG_RANGE5_CNT_MASK GENMASK(31, 16) ++#define MT_DBG_MIB_M0DR4_TRX_AGG_RANGE4_CNT_MASK GENMASK(15, 0) ++#define MT_DBG_MIB_M0DR5_TRX_AGG_RANGE7_CNT_MASK GENMASK(31, 16) ++#define MT_DBG_MIB_M0DR5_TRX_AGG_RANGE6_CNT_MASK GENMASK(15, 0) ++#define MT_DBG_MIB_M0DR13_TRX_AGG_RANGE9_CNT_MASK GENMASK(31, 16) ++#define MT_DBG_MIB_M0DR13_TRX_AGG_RANGE8_CNT_MASK GENMASK(15, 0) ++#define MT_DBG_MIB_M0DR14_TRX_AGG_RANGE11_CNT_MASK GENMASK(31, 16) ++#define MT_DBG_MIB_M0DR14_TRX_AGG_RANGE10_CNT_MASK GENMASK(15, 0) ++#define MT_DBG_MIB_M0DR15_TRX_AGG_RANGE13_CNT_MASK GENMASK(31, 16) ++#define MT_DBG_MIB_M0DR15_TRX_AGG_RANGE12_CNT_MASK GENMASK(15, 0) ++#define MT_DBG_MIB_M0DR16_TRX_AGG_RANGE15_CNT_MASK GENMASK(31, 16) ++#define MT_DBG_MIB_M0DR16_TRX_AGG_RANGE14_CNT_MASK GENMASK(15, 0) ++ ++/* mt7915 host DMA*/ ++#define MT_DBG_INT_DMA1_R0_DONE BIT(0) ++#define MT_DBG_INT_DMA1_R1_DONE BIT(1) ++#define MT_DBG_INT_DMA1_R2_DONE BIT(2) ++ ++#define MT_DBG_INT_DMA1_T16_DONE BIT(26) ++#define MT_DBG_INT_DMA1_T17_DONE BIT(27) ++#define MT_DBG_INT_DMA1_T18_DONE BIT(30) ++#define MT_DBG_INT_DMA1_T19_DONE BIT(31) ++#define MT_DBG_INT_DMA1_T20_DONE BIT(15) ++ ++#define MT_DBG_EXT_WRAP_INT_DMA0_R0_DONE BIT(16) ++#define MT_DBG_EXT_WRAP_INT_DMA0_R1_DONE BIT(17) ++ ++/* mt7986 host DMA */ ++#define MT_DBG_INT_DMA0_R0_DONE BIT(0) ++#define MT_DBG_INT_DMA0_R1_DONE BIT(1) ++#define MT_DBG_INT_DMA0_R2_DONE BIT(2) ++#define MT_DBG_INT_DMA0_R3_DONE BIT(3) ++#define MT_DBG_INT_DMA0_R4_DONE BIT(22) ++#define MT_DBG_INT_DMA0_R5_DONE BIT(23) ++ ++#define MT_DBG_INT_DMA0_T16_DONE BIT(26) ++#define MT_DBG_INT_DMA0_T17_DONE BIT(27) ++#define MT_DBG_INT_DMA0_T18_DONE BIT(30) ++#define MT_DBG_INT_DMA0_T19_DONE BIT(31) ++#define MT_DBG_INT_DMA0_T20_DONE BIT(25) ++ ++/* MCU DMA */ ++#define WF_WFDMA_MCU_DMA0_BASE 0x54000000 ++#define WF_WFDMA_MCU_DMA0_HOST_INT_STA_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x200) // 0200 ++#define WF_WFDMA_MCU_DMA0_HOST_INT_ENA_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0X204) // 0204 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x208) // 0208 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK 0x00000008 // RX_DMA_BUSY[3] ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK 0x00000004 // RX_DMA_EN[2] ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK 0x00000002 // TX_DMA_BUSY[1] ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK 0x00000001 // TX_DMA_EN[0] ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 ++ ++#define WF_WFDMA_MCU_DMA1_BASE 0x55000000 ++#define WF_WFDMA_MCU_DMA1_HOST_INT_STA_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x200) // 0200 ++#define WF_WFDMA_MCU_DMA1_HOST_INT_ENA_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0X204) // 0204 ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x208) // 0208 ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK 0x00000008 // RX_DMA_BUSY[3] ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_MASK 0x00000004 // RX_DMA_EN[2] ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK 0x00000002 // TX_DMA_BUSY[1] ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_MASK 0x00000001 // TX_DMA_EN[0] ++#define WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 ++#define WF_WFDMA_MCU_DMA1_WPDMA_TX_RING0_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x300) // 0300 ++#define WF_WFDMA_MCU_DMA1_WPDMA_TX_RING1_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x310) // 0310 ++#define WF_WFDMA_MCU_DMA1_WPDMA_TX_RING2_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x320) // 0320 ++#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING0_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x500) // 0500 ++#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING1_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x510) // 0510 ++#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING2_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x520) // 0520 ++#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING3_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x530) // 0530 ++#define WF_WFDMA_MCU_DMA1_WPDMA_RX_RING4_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_BASE + 0x540) // 0540 ++ ++#define WF_WFDMA_MCU_DMA1_PCIE1_BASE 0x59000000 ++#define WF_WFDMA_MCU_DMA1_PCIE1_HOST_INT_STA_ADDR (WF_WFDMA_MCU_DMA1_PCIE1_BASE + 0x200) // 0200 ++#define WF_WFDMA_MCU_DMA1_PCIE1_HOST_INT_ENA_ADDR (WF_WFDMA_MCU_DMA1_PCIE1_BASE + 0X204) // 0204 ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_ADDR (WF_WFDMA_MCU_DMA1_PCIE1_BASE + 0x208) // 0208 ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK 0x00000008 // RX_DMA_BUSY[3] ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_RX_DMA_EN_MASK 0x00000004 // RX_DMA_EN[2] ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK 0x00000002 // TX_DMA_BUSY[1] ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_TX_DMA_EN_MASK 0x00000001 // TX_DMA_EN[0] ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_TX_RING2_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_PCIE1_BASE + 0x320) // 0320 ++#define WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_RX_RING3_CTRL0_ADDR (WF_WFDMA_MCU_DMA1_PCIE1_BASE + 0x530) // 0530 ++ ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x300) // 0300 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING1_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x310) // 0310 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING2_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x320) // 0320 ++/* mt7986 add */ ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING3_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x330) // 0330 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING4_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x340) // 0340 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING5_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x350) // 0350 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING6_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x360) // 0360 ++ ++ ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x500) // 0500 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x510) // 0510 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING2_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x520) // 0520 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING3_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x530) // 0530 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING4_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x540) // 0540 ++ ++/* mt7986 add */ ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING5_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x550) // 0550 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING6_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x560) // 0560 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING7_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x570) // 0570 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING8_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x580) // 0580 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING9_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x590) // 0590 ++ ++/* MEM DMA */ ++#define WF_WFDMA_MEM_DMA_BASE 0x58000000 ++#define WF_WFDMA_MEM_DMA_HOST_INT_STA_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x200) // 0200 ++#define WF_WFDMA_MEM_DMA_HOST_INT_ENA_ADDR (WF_WFDMA_MEM_DMA_BASE + 0X204) // 0204 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x208) // 0208 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK 0x00000008 // RX_DMA_BUSY[3] ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_MASK 0x00000004 // RX_DMA_EN[2] ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK 0x00000002 // TX_DMA_BUSY[1] ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_MASK 0x00000001 // TX_DMA_EN[0] ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING0_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x300) // 0300 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING1_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x310) // 0310 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING0_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x500) // 0500 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING1_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x510) // 0510 ++ ++enum resource_attr { ++ HIF_TX_DATA, ++ HIF_TX_CMD, ++ HIF_TX_CMD_WM, /* direct path to WMCPU, only exist for WFDMA arch with 2 CPU */ ++ HIF_TX_FWDL, ++ HIF_RX_DATA, ++ HIF_RX_EVENT, ++ RING_ATTR_NUM ++}; ++ ++struct hif_pci_tx_ring_desc { ++ u32 hw_int_mask; ++ u16 ring_size; ++ enum resource_attr ring_attr; ++ u8 band_idx; ++ char *const ring_info; ++}; ++ ++struct hif_pci_rx_ring_desc { ++ u32 hw_desc_base; ++ u32 hw_int_mask; ++ u16 ring_size; ++ enum resource_attr ring_attr; ++ u16 max_rx_process_cnt; ++ u16 max_sw_read_idx_inc; ++ char *const ring_info; ++ bool flags; ++}; ++ ++const struct hif_pci_tx_ring_desc mt7915_tx_ring_layout[] = { ++ { ++ .hw_int_mask = MT_DBG_INT_DMA1_T16_DONE, ++ .ring_size = 128, ++ .ring_attr = HIF_TX_FWDL, ++ .ring_info = "FWDL" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA1_T17_DONE, ++ .ring_size = 256, ++ .ring_attr = HIF_TX_CMD_WM, ++ .ring_info = "cmd to WM" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA1_T18_DONE, ++ .ring_size = 2048, ++ .ring_attr = HIF_TX_DATA, ++ .ring_info = "band0 TXD" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA1_T19_DONE, ++ .ring_size = 2048, ++ .ring_attr = HIF_TX_DATA, ++ .ring_info = "band1 TXD" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA1_T20_DONE, ++ .ring_size = 256, ++ .ring_attr = HIF_TX_CMD, ++ .ring_info = "cmd to WA" ++ } ++}; ++ ++const struct hif_pci_rx_ring_desc mt7915_rx_ring_layout[] = { ++ { ++ .hw_int_mask = MT_DBG_EXT_WRAP_INT_DMA0_R0_DONE, ++ .ring_size = 1536, ++ .ring_attr = HIF_RX_DATA, ++ .ring_info = "band0 RX data" ++ }, ++ { ++ .hw_int_mask = MT_DBG_EXT_WRAP_INT_DMA0_R1_DONE, ++ .ring_size = 1536, ++ .ring_attr = HIF_RX_DATA, ++ .ring_info = "band1 RX data" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA1_R0_DONE, ++ .ring_size = 512, ++ .ring_attr = HIF_RX_EVENT, ++ .ring_info = "event from WM" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA1_R1_DONE, ++ .ring_size = 1024, ++ .ring_attr = HIF_RX_EVENT, ++ .ring_info = "event from WA band0", ++ .flags = true ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA1_R2_DONE, ++ .ring_size = 512, ++ .ring_attr = HIF_RX_EVENT, ++ .ring_info = "event from WA band1" ++ } ++}; ++ ++const struct hif_pci_tx_ring_desc mt7986_tx_ring_layout[] = { ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_T16_DONE, ++ .ring_size = 128, ++ .ring_attr = HIF_TX_FWDL, ++ .ring_info = "FWDL" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_T17_DONE, ++ .ring_size = 256, ++ .ring_attr = HIF_TX_CMD_WM, ++ .ring_info = "cmd to WM" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_T18_DONE, ++ .ring_size = 2048, ++ .ring_attr = HIF_TX_DATA, ++ .ring_info = "band0 TXD" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_T19_DONE, ++ .ring_size = 2048, ++ .ring_attr = HIF_TX_DATA, ++ .ring_info = "band1 TXD" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_T20_DONE, ++ .ring_size = 256, ++ .ring_attr = HIF_TX_CMD, ++ .ring_info = "cmd to WA" ++ } ++}; ++ ++const struct hif_pci_rx_ring_desc mt7986_rx_ring_layout[] = { ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_R4_DONE, ++ .ring_size = 1536, ++ .ring_attr = HIF_RX_DATA, ++ .ring_info = "band0 RX data" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_R5_DONE, ++ .ring_size = 1536, ++ .ring_attr = HIF_RX_DATA, ++ .ring_info = "band1 RX data" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_R0_DONE, ++ .ring_size = 512, ++ .ring_attr = HIF_RX_EVENT, ++ .ring_info = "event from WM" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_R1_DONE, ++ .ring_size = 512, ++ .ring_attr = HIF_RX_EVENT, ++ .ring_info = "event from WA" ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_R2_DONE, ++ .ring_size = 1024, ++ .ring_attr = HIF_RX_EVENT, ++ .ring_info = "STS WA band0", ++ .flags = true ++ }, ++ { ++ .hw_int_mask = MT_DBG_INT_DMA0_R3_DONE, ++ .ring_size = 512, ++ .ring_attr = HIF_RX_EVENT, ++ .ring_info = "STS WA band1" ++ }, ++}; ++ ++/* mibinfo related CRs. */ ++#define BN0_WF_MIB_TOP_BASE 0x820ed000 ++#define BN1_WF_MIB_TOP_BASE 0x820fd000 ++ ++#define BN0_WF_MIB_TOP_BTOCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x400) // D400 ++#define BN0_WF_MIB_TOP_BTBCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x428) // D428 ++#define BN0_WF_MIB_TOP_BTDCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x4F0) // D4F0 ++ ++#define BN0_WF_MIB_TOP_BSDR0_ADDR (BN0_WF_MIB_TOP_BASE + 0x688) // D688 ++#define BN0_WF_MIB_TOP_BSDR1_ADDR (BN0_WF_MIB_TOP_BASE + 0x690) // D690 ++ ++#define BN0_WF_MIB_TOP_BSDR2_ADDR (BN0_WF_MIB_TOP_BASE + 0x518) // D518 ++#define BN0_WF_MIB_TOP_BSDR3_ADDR (BN0_WF_MIB_TOP_BASE + 0x520) // D520 ++#define BN0_WF_MIB_TOP_BSDR4_ADDR (BN0_WF_MIB_TOP_BASE + 0x528) // D528 ++#define BN0_WF_MIB_TOP_BSDR5_ADDR (BN0_WF_MIB_TOP_BASE + 0x530) // D530 ++#define BN0_WF_MIB_TOP_BSDR6_ADDR (BN0_WF_MIB_TOP_BASE + 0x538) // D538 ++ ++#define BN0_WF_MIB_TOP_BROCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x5B8) // D5B8 ++#define BN0_WF_MIB_TOP_BRBCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x5E0) // D5E0 ++#define BN0_WF_MIB_TOP_BRDCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x630) // D630 ++ ++#define BN0_WF_MIB_TOP_M0SDR0_BEACONTXCOUNT_MASK 0x0000FFFF // BEACONTXCOUNT[15..0] ++ ++#define BN0_WF_MIB_TOP_M0SDR4_RX_FIFO_FULL_COUNT_MASK 0x0000FFFF // RX_FIFO_FULL_COUNT[15..0] ++ ++#define BN0_WF_MIB_TOP_M0SDR5_RX_MPDU_COUNT_MASK 0xFFFFFFFF // RX_MPDU_COUNT[31..0] ++ ++#define BN0_WF_MIB_TOP_M0SDR6_CHANNEL_IDLE_COUNT_MASK 0x0000FFFF // CHANNEL_IDLE_COUNT[15..0] ++ ++#define BN1_WF_MIB_TOP_BTOCR_ADDR (BN1_WF_MIB_TOP_BASE + 0x400) // D400 ++ ++#define BN0_WF_MIB_TOP_M0SDR7_VEC_MISS_COUNT_MASK 0x0000FFFF // VEC_MISS_COUNT[15..0] ++#define BN0_WF_MIB_TOP_M0SDR8_DELIMITER_FAIL_COUNT_MASK 0x0000FFFF // DELIMITER_FAIL_COUNT[15..0] ++#define BN0_WF_MIB_TOP_M0SDR9_CCA_NAV_TX_TIME_MASK 0x00FFFFFF // CCA_NAV_TX_TIME[23..0] ++ ++#define BN0_WF_MIB_TOP_M0SDR11_RX_LEN_MISMATCH_MASK 0x0000FFFF // RX_LEN_MISMATCH[15..0] ++ ++#define BN0_WF_MIB_TOP_M0SDR16_P_CCA_TIME_MASK 0x00FFFFFF // P_CCA_TIME[23..0] ++#define BN0_WF_MIB_TOP_M0SDR17_S_CCA_TIME_MASK 0x00FFFFFF // S_CCA_TIME[23..0] ++#define BN0_WF_MIB_TOP_M0SDR18_P_ED_TIME_MASK 0x00FFFFFF // P_ED_TIME[23..0] ++#define BN0_WF_MIB_TOP_M0SDR19_CCK_MDRDY_TIME_MASK 0x00FFFFFF // CCK_MDRDY_TIME[23..0] ++#define BN0_WF_MIB_TOP_M0SDR20_OFDM_LG_MIXED_VHT_MDRDY_TIME_MASK 0x00FFFFFF // OFDM_LG_MIXED_VHT_MDRDY_TIME[23..0] ++#define BN0_WF_MIB_TOP_M0SDR21_OFDM_GREEN_MDRDY_TIME_MASK 0x00FFFFFF // OFDM_GREEN_MDRDY_TIME[23..0] ++ ++#define BN0_WF_MIB_TOP_M0SDR22_ADDR (BN0_WF_MIB_TOP_BASE + 0x60) // D060 ++#define BN0_WF_MIB_TOP_M0SDR23_ADDR (BN0_WF_MIB_TOP_BASE + 0x64) // D064 ++ ++#define BN0_WF_MIB_TOP_M0SDR34_MUBF_TX_COUNT_MASK 0x0000FFFF // MUBF_TX_COUNT[15..0] ++ ++#define BN0_WF_MIB_TOP_M0DR0_TX_40MHZ_CNT_MASK 0xFFFF0000 // TX_40MHZ_CNT[31..16] ++#define BN0_WF_MIB_TOP_M0DR0_TX_40MHZ_CNT_SHFT 16 ++#define BN0_WF_MIB_TOP_M0DR0_TX_20MHZ_CNT_MASK 0x0000FFFF // TX_20MHZ_CNT[15..0] ++#define BN0_WF_MIB_TOP_M0DR0_TX_20MHZ_CNT_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_M0DR1_TX_160MHZ_CNT_MASK 0xFFFF0000 // TX_160MHZ_CNT[31..16] ++#define BN0_WF_MIB_TOP_M0DR1_TX_160MHZ_CNT_SHFT 16 ++#define BN0_WF_MIB_TOP_M0DR1_TX_80MHZ_CNT_MASK 0x0000FFFF // TX_80MHZ_CNT[15..0] ++#define BN0_WF_MIB_TOP_M0DR1_TX_80MHZ_CNT_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_M0DR6_TX_DDLMT_RNG2_CNT_MASK 0xFFFF0000 // TX_DDLMT_RNG2_CNT[31..16] ++#define BN0_WF_MIB_TOP_M0DR6_TX_DDLMT_RNG2_CNT_SHFT 16 ++#define BN0_WF_MIB_TOP_M0DR6_TX_DDLMT_RNG1_CNT_MASK 0x0000FFFF // TX_DDLMT_RNG1_CNT[15..0] ++#define BN0_WF_MIB_TOP_M0DR6_TX_DDLMT_RNG1_CNT_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_M0DR7_TX_DDLMT_RNG4_CNT_MASK 0xFFFF0000 // TX_DDLMT_RNG4_CNT[31..16] ++#define BN0_WF_MIB_TOP_M0DR7_TX_DDLMT_RNG4_CNT_SHFT 16 ++#define BN0_WF_MIB_TOP_M0DR7_TX_DDLMT_RNG3_CNT_MASK 0x0000FFFF // TX_DDLMT_RNG3_CNT[15..0] ++#define BN0_WF_MIB_TOP_M0DR7_TX_DDLMT_RNG3_CNT_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_M0DR10_MU_FAIL_PPDU_CNT_MASK 0x0000FFFF // MU_FAIL_PPDU_CNT[15..0] ++ ++#define BN0_WF_MIB_TOP_M0B0SDR0_ADDR (BN0_WF_MIB_TOP_BASE + 0x100) // D100 ++#define BN0_WF_MIB_TOP_M0B0SDR0_RTSRETRYCOUNT_MASK 0xFFFF0000 // RTSRETRYCOUNT[31..16] ++#define BN0_WF_MIB_TOP_M0B0SDR0_RTSRETRYCOUNT_SHFT 16 ++#define BN0_WF_MIB_TOP_M0B0SDR0_RTSTXCOUNT_MASK 0x0000FFFF // RTSTXCOUNT[15..0] ++#define BN0_WF_MIB_TOP_M0B0SDR0_RTSTXCOUNT_SHFT 0 ++#define BN0_WF_MIB_TOP_M0B0SDR1_ADDR (BN0_WF_MIB_TOP_BASE + 0x104) // D104 ++#define BN0_WF_MIB_TOP_M0B0SDR1_ACKFAILCOUNT_MASK 0xFFFF0000 // ACKFAILCOUNT[31..16] ++#define BN0_WF_MIB_TOP_M0B0SDR1_ACKFAILCOUNT_SHFT 16 ++#define BN0_WF_MIB_TOP_M0B0SDR1_BAMISSCOUNT_MASK 0x0000FFFF // BAMISSCOUNT[15..0] ++#define BN0_WF_MIB_TOP_M0B0SDR1_BAMISSCOUNT_SHFT 0 ++#define BN0_WF_MIB_TOP_M0B0SDR2_ADDR (BN0_WF_MIB_TOP_BASE + 0x108) // D108 ++#define BN0_WF_MIB_TOP_M0B0SDR2_FRAMERETRY2COUNT_MASK 0xFFFF0000 // FRAMERETRY2COUNT[31..16] ++#define BN0_WF_MIB_TOP_M0B0SDR2_FRAMERETRY2COUNT_SHFT 16 ++#define BN0_WF_MIB_TOP_M0B0SDR2_FRAMERETRYCOUNT_MASK 0x0000FFFF // FRAMERETRYCOUNT[15..0] ++#define BN0_WF_MIB_TOP_M0B0SDR2_FRAMERETRYCOUNT_SHFT 0 ++#define BN0_WF_MIB_TOP_M0B0SDR3_ADDR (BN0_WF_MIB_TOP_BASE + 0x10C) // D10C ++#define BN0_WF_MIB_TOP_M0B0SDR3_FRAMERETRY3COUNT_MASK 0x0000FFFF // FRAMERETRY3COUNT[15..0] ++#define BN0_WF_MIB_TOP_M0B0SDR3_FRAMERETRY3COUNT_SHFT 0 ++#define BN0_WF_MIB_TOP_M0DR12_TX_DDLMT_RNG0_CNT_MASK 0x0000FFFF // TX_DDLMT_RNG0_CNT[15..0] ++ ++ ++#define BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2np1_MASK 0xFFFF0000 // TX_OK_COUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2n_MASK 0x0000FFFF // TX_OK_COUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BTDCR_TX_DATA_COUNT2np1_MASK 0xFFFF0000 // TX_DATA_COUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BTDCR_TX_DATA_COUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BTDCR_TX_DATA_COUNT2n_MASK 0x0000FFFF // TX_DATA_COUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BTDCR_TX_DATA_COUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2np1_MASK 0xFFFF0000 // RX_OK_COUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2n_MASK 0x0000FFFF // RX_OK_COUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BRDCR_RX_DATA_COUNT2np1_MASK 0xFFFF0000 // RX_DATA_COUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BRDCR_RX_DATA_COUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BRDCR_RX_DATA_COUNT2n_MASK 0x0000FFFF // RX_DATA_COUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BRDCR_RX_DATA_COUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BSDR0_RTSTXCOUNT2np1_MASK 0xFFFF0000 // RTSTXCOUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BSDR0_RTSTXCOUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BSDR0_RTSTXCOUNT2n_MASK 0x0000FFFF // RTSTXCOUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BSDR0_RTSTXCOUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BSDR1_RTSRETRYCOUNT2np1_MASK 0xFFFF0000 // RTSRETRYCOUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BSDR1_RTSRETRYCOUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BSDR1_RTSRETRYCOUNT2n_MASK 0x0000FFFF // RTSRETRYCOUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BSDR1_RTSRETRYCOUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BSDR2_BAMISSCOUNT2np1_MASK 0xFFFF0000 // BAMISSCOUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BSDR2_BAMISSCOUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BSDR2_BAMISSCOUNT2n_MASK 0x0000FFFF // BAMISSCOUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BSDR2_BAMISSCOUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BSDR3_ACKFAILCOUNT2np1_MASK 0xFFFF0000 // ACKFAILCOUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BSDR3_ACKFAILCOUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BSDR3_ACKFAILCOUNT2n_MASK 0x0000FFFF // ACKFAILCOUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BSDR3_ACKFAILCOUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BSDR4_FRAMERETRYCOUNT2np1_MASK 0xFFFF0000 // FRAMERETRYCOUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BSDR4_FRAMERETRYCOUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BSDR4_FRAMERETRYCOUNT2n_MASK 0x0000FFFF // FRAMERETRYCOUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BSDR4_FRAMERETRYCOUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BSDR5_FRAMERETRY2COUNT2np1_MASK 0xFFFF0000 // FRAMERETRY2COUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BSDR5_FRAMERETRY2COUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BSDR5_FRAMERETRY2COUNT2n_MASK 0x0000FFFF // FRAMERETRY2COUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BSDR5_FRAMERETRY2COUNT2n_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_BSDR6_FRAMERETRY3COUNT2np1_MASK 0xFFFF0000 // FRAMERETRY3COUNT2np1[31..16] ++#define BN0_WF_MIB_TOP_BSDR6_FRAMERETRY3COUNT2np1_SHFT 16 ++#define BN0_WF_MIB_TOP_BSDR6_FRAMERETRY3COUNT2n_MASK 0x0000FFFF // FRAMERETRY3COUNT2n[15..0] ++#define BN0_WF_MIB_TOP_BSDR6_FRAMERETRY3COUNT2n_SHFT 0 ++/* TXD */ ++ ++#define MT_TXD1_ETYP BIT(15) ++#define MT_TXD1_VLAN BIT(14) ++#define MT_TXD1_RMVL BIT(13) ++#define MT_TXD1_AMS BIT(13) ++#define MT_TXD1_EOSP BIT(12) ++#define MT_TXD1_MRD BIT(11) ++ ++#define MT_TXD7_CTXD BIT(26) ++#define MT_TXD7_CTXD_CNT GENMASK(25, 23) ++#define MT_TXD7_TAT GENMASK(9, 0) ++ ++#endif ++#endif +diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c +new file mode 100644 +index 0000000..62d3a99 +--- /dev/null ++++ b/mt7915/mtk_debugfs.c +@@ -0,0 +1,3750 @@ ++#include ++#include "mt7915.h" ++#include "mt7915_debug.h" ++#include "mac.h" ++#include "mcu.h" ++ ++#ifdef MTK_DEBUG ++#define LWTBL_IDX2BASE_ID GENMASK(14, 8) ++#define LWTBL_IDX2BASE_DW GENMASK(7, 2) ++#define LWTBL_IDX2BASE(_id, _dw) (MT_DBG_WTBL_BASE | \ ++ FIELD_PREP(LWTBL_IDX2BASE_ID, _id) | \ ++ FIELD_PREP(LWTBL_IDX2BASE_DW, _dw)) ++ ++#define UWTBL_IDX2BASE_ID GENMASK(12, 6) ++#define UWTBL_IDX2BASE_DW GENMASK(5, 2) ++#define UWTBL_IDX2BASE(_id, _dw) (MT_DBG_UWTBL_TOP_BASE | 0x2000 | \ ++ FIELD_PREP(UWTBL_IDX2BASE_ID, _id) | \ ++ FIELD_PREP(UWTBL_IDX2BASE_DW, _dw)) ++ ++#define KEYTBL_IDX2BASE_KEY GENMASK(12, 6) ++#define KEYTBL_IDX2BASE_DW GENMASK(5, 2) ++#define KEYTBL_IDX2BASE(_key, _dw) (MT_DBG_UWTBL_TOP_BASE | 0x2000 | \ ++ FIELD_PREP(KEYTBL_IDX2BASE_KEY, _key) | \ ++ FIELD_PREP(KEYTBL_IDX2BASE_DW, _dw)) ++ ++enum mt7915_wtbl_type { ++ WTBL_TYPE_LMAC, /* WTBL in LMAC */ ++ WTBL_TYPE_UMAC, /* WTBL in UMAC */ ++ WTBL_TYPE_KEY, /* Key Table */ ++ MAX_NUM_WTBL_TYPE ++}; ++ ++static int mt7915_wtbl_read_raw(struct mt7915_dev *dev, u16 idx, ++ enum mt7915_wtbl_type type, u16 start_dw, ++ u16 len, void *buf) ++{ ++ u32 *dest_cpy = (u32 *)buf; ++ u32 size_dw = len; ++ u32 src = 0; ++ ++ if (!buf) ++ return 0xFF; ++ ++ if (type == WTBL_TYPE_LMAC) { ++ mt76_wr(dev, MT_DBG_WTBLON_TOP_WDUCR, ++ FIELD_PREP(MT_DBG_WTBLON_TOP_WDUCR_GROUP, (idx >> 7))); ++ src = LWTBL_IDX2BASE(idx, start_dw); ++ } else if (type == WTBL_TYPE_UMAC) { ++ mt76_wr(dev, MT_DBG_UWTBL_TOP_WDUCR, ++ FIELD_PREP(MT_UWTBL_TOP_WDUCR_GROUP, (idx >> 7))); ++ src = UWTBL_IDX2BASE(idx, start_dw); ++ } else if (type == WTBL_TYPE_KEY) { ++ mt76_wr(dev, MT_DBG_UWTBL_TOP_WDUCR, ++ MT_UWTBL_TOP_WDUCR_TARGET | ++ FIELD_PREP(MT_UWTBL_TOP_WDUCR_GROUP, (idx >> 7))); ++ src = KEYTBL_IDX2BASE(idx, start_dw); ++ } ++ ++ while (size_dw--) { ++ *dest_cpy++ = mt76_rr(dev, src); ++ src += 4; ++ }; ++ ++ return 0; ++} ++ ++static int mt7915_wtbl_write_raw(struct mt7915_dev *dev, u16 idx, ++ enum mt7915_wtbl_type type, u16 start_dw, ++ u32 val) ++{ ++ u32 addr = 0; ++ ++ if (type == WTBL_TYPE_LMAC) { ++ mt76_wr(dev, MT_DBG_WTBLON_TOP_WDUCR, ++ FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (idx >> 7))); ++ addr = LWTBL_IDX2BASE(idx, start_dw); ++ } else if (type == WTBL_TYPE_UMAC) { ++ mt76_wr(dev, MT_DBG_UWTBL_TOP_WDUCR, ++ FIELD_PREP(MT_UWTBL_TOP_WDUCR_GROUP, (idx >> 7))); ++ addr = UWTBL_IDX2BASE(idx, start_dw); ++ } else if (type == WTBL_TYPE_KEY) { ++ mt76_wr(dev, MT_DBG_UWTBL_TOP_WDUCR, ++ MT_UWTBL_TOP_WDUCR_TARGET | ++ FIELD_PREP(MT_UWTBL_TOP_WDUCR_GROUP, (idx >> 7))); ++ addr = KEYTBL_IDX2BASE(idx, start_dw); ++ } ++ ++ mt76_wr(dev, addr, val); ++ ++ return 0; ++} ++ ++void mt7915_packet_log_to_host(struct mt7915_dev *dev, const void *data, int len, int type, int des_len) ++{ ++ struct bin_debug_hdr *hdr; ++ char *buf; ++ ++ if (len > 1500 - sizeof(*hdr)) ++ len = 1500 - sizeof(*hdr); ++ ++ buf = kzalloc(sizeof(*hdr) + len, GFP_KERNEL); ++ if (!buf) ++ return; ++ ++ hdr = (struct bin_debug_hdr *)buf; ++ hdr->magic_num = cpu_to_le32(PKT_BIN_DEBUG_MAGIC); ++ hdr->serial_id = cpu_to_le16(dev->dbg.fwlog_seq++); ++ hdr->msg_type = cpu_to_le16(type); ++ hdr->len = cpu_to_le16(len); ++ hdr->des_len = cpu_to_le16(des_len); ++ ++ memcpy(buf + sizeof(*hdr), data, len); ++ ++ mt7915_debugfs_rx_log(dev, buf, sizeof(*hdr) + len); ++} ++ ++static int ++mt7915_fw_debug_module_set(void *data, u64 module) ++{ ++ struct mt7915_dev *dev = data; ++ ++ dev->dbg.fw_dbg_module = module; ++ return 0; ++} ++ ++static int ++mt7915_fw_debug_module_get(void *data, u64 *module) ++{ ++ struct mt7915_dev *dev = data; ++ ++ *module = dev->dbg.fw_dbg_module; ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_module, mt7915_fw_debug_module_get, ++ mt7915_fw_debug_module_set, "%lld\n"); ++ ++static int ++mt7915_fw_debug_level_set(void *data, u64 level) ++{ ++ struct mt7915_dev *dev = data; ++ ++ dev->dbg.fw_dbg_lv = level; ++ mt7915_mcu_fw_dbg_ctrl(dev, dev->dbg.fw_dbg_module, dev->dbg.fw_dbg_lv); ++ return 0; ++} ++ ++static int ++mt7915_fw_debug_level_get(void *data, u64 *level) ++{ ++ struct mt7915_dev *dev = data; ++ ++ *level = dev->dbg.fw_dbg_lv; ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_level, mt7915_fw_debug_level_get, ++ mt7915_fw_debug_level_set, "%lld\n"); ++ ++#define MAX_TX_MODE 12 ++static char *HW_TX_MODE_STR[] = {"CCK", "OFDM", "HT-Mix", "HT-GF", "VHT", ++ "N/A", "N/A", "N/A", "HE_SU", "HE_EXT_SU", ++ "HE_TRIG", "HE_MU", "N/A"}; ++static char *HW_TX_RATE_CCK_STR[] = {"1M", "2Mlong", "5.5Mlong", "11Mlong", ++ "N/A", "2Mshort", "5.5Mshort", "11Mshort", ++ "N/A"}; ++static char *HW_TX_RATE_OFDM_STR[] = {"6M", "9M", "12M", "18M", "24M", "36M", ++ "48M", "54M", "N/A"}; ++static char *fcap_str[] = {"20MHz", "20/40MHz", "20/40/80MHz", ++ "20/40/80/160/80+80MHz"}; ++ ++static char *hw_rate_ofdm_str(u16 ofdm_idx) ++{ ++ switch (ofdm_idx) { ++ case 11: /* 6M */ ++ return HW_TX_RATE_OFDM_STR[0]; ++ ++ case 15: /* 9M */ ++ return HW_TX_RATE_OFDM_STR[1]; ++ ++ case 10: /* 12M */ ++ return HW_TX_RATE_OFDM_STR[2]; ++ ++ case 14: /* 18M */ ++ return HW_TX_RATE_OFDM_STR[3]; ++ ++ case 9: /* 24M */ ++ return HW_TX_RATE_OFDM_STR[4]; ++ ++ case 13: /* 36M */ ++ return HW_TX_RATE_OFDM_STR[5]; ++ ++ case 8: /* 48M */ ++ return HW_TX_RATE_OFDM_STR[6]; ++ ++ case 12: /* 54M */ ++ return HW_TX_RATE_OFDM_STR[7]; ++ ++ default: ++ return HW_TX_RATE_OFDM_STR[8]; ++ } ++} ++ ++static char *hw_rate_str(u8 mode, u16 rate_idx) ++{ ++ if (mode == 0) ++ return rate_idx < 8 ? HW_TX_RATE_CCK_STR[rate_idx] : HW_TX_RATE_CCK_STR[8]; ++ else if (mode == 1) ++ return hw_rate_ofdm_str(rate_idx); ++ else ++ return "MCS"; ++} ++ ++static void parse_rate(struct seq_file *s, u16 rate_idx, u16 txrate) ++{ ++ u16 txmode, mcs, nss, stbc; ++ ++ txmode = FIELD_GET(GENMASK(9, 6), txrate); ++ mcs = FIELD_GET(GENMASK(5, 0), txrate); ++ nss = FIELD_GET(GENMASK(12, 10), txrate); ++ stbc = FIELD_GET(BIT(13), txrate); ++ ++ seq_printf(s, "\tRate%d(0x%x):TxMode=%d(%s), TxRate=%d(%s), Nsts=%d, STBC=%d\n", ++ rate_idx + 1, txrate, ++ txmode, (txmode < MAX_TX_MODE ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[MAX_TX_MODE]), ++ mcs, hw_rate_str(txmode, mcs), nss, stbc); ++} ++ ++#define LWTBL_LEN_IN_DW 32 ++#define UWTBL_LEN_IN_DW 8 ++#define ONE_KEY_ENTRY_LEN_IN_DW 8 ++static int mt7915_sta_info(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u8 lwtbl[LWTBL_LEN_IN_DW*4] = {0}; ++ u16 i = 0; ++ ++ for (i=0; i < mt7915_wtbl_size(dev); i++) { ++ mt7915_wtbl_read_raw(dev, i, WTBL_TYPE_LMAC, 0, ++ LWTBL_LEN_IN_DW, lwtbl); ++ if (lwtbl[4] || lwtbl[5] || lwtbl[6] || lwtbl[7] || lwtbl[0] || lwtbl[1]) ++ seq_printf(s, "wcid:%d\tAddr: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ i, lwtbl[4], lwtbl[5], lwtbl[6], lwtbl[7], lwtbl[0], lwtbl[1]); ++ } ++ ++ return 0; ++} ++ ++static int mt7915_wtbl_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u8 lwtbl[LWTBL_LEN_IN_DW*4] = {0}; ++ int x; ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ ++ mt7915_wtbl_read_raw(dev, dev->wlan_idx, WTBL_TYPE_LMAC, 0, ++ LWTBL_LEN_IN_DW, lwtbl); ++ seq_printf(s, "Dump WTBL info of WLAN_IDX:%d\n", dev->wlan_idx); ++ seq_printf(s, "LMAC WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_WTBLON_TOP_WDUCR, ++ mt76_rr(dev, MT_DBG_WTBLON_TOP_WDUCR), ++ LWTBL_IDX2BASE(dev->wlan_idx, 0)); ++ for (x = 0; x < LWTBL_LEN_IN_DW; x++) { ++ seq_printf(s, "DW%02d: %02x %02x %02x %02x\n", ++ x, ++ lwtbl[x * 4 + 3], ++ lwtbl[x * 4 + 2], ++ lwtbl[x * 4 + 1], ++ lwtbl[x * 4]); ++ } ++ ++ seq_printf(s, "\n\tAddr: %02x:%02x:%02x:%02x:%02x:%02x(D0[B0~15], D1[B0~31])\n", ++ lwtbl[4], lwtbl[5], lwtbl[6], lwtbl[7], lwtbl[0], lwtbl[1]); ++ ++ // DW0, DW1 ++ seq_printf(s, "LWTBL DW 0/1\n\t"); ++ addr = (u32 *)&(lwtbl[0]); ++ dw_value = *addr; ++ seq_printf(s, "MUAR_IDX:%lu/ ", FIELD_GET(GENMASK(21, 16), dw_value)); ++ seq_printf(s, "RCA1:%ld/ ", FIELD_GET(BIT(22), dw_value)); ++ seq_printf(s, "KID:%lu/ ", FIELD_GET(GENMASK(24, 23), dw_value)); ++ seq_printf(s, "RCID:%ld/ ", FIELD_GET(BIT(25), dw_value)); ++ seq_printf(s, "FROM_DS:%ld\n\t", FIELD_GET(BIT(26), dw_value)); ++ seq_printf(s, "TO_DS:%ld/ ", FIELD_GET(BIT(27), dw_value)); ++ seq_printf(s, "RV:%ld/ ", FIELD_GET(BIT(28), dw_value)); ++ seq_printf(s, "RCA2:%ld/ ", FIELD_GET(BIT(29), dw_value)); ++ seq_printf(s, "WPI_FLAG:%ld\n", FIELD_GET(BIT(30), dw_value)); ++ ++ // DW2 ++ seq_printf(s, "LWTBL DW 2\n\t"); ++ addr = (u32 *)&(lwtbl[2*4]); ++ dw_value = *addr; ++ seq_printf(s, "AID12:%lu/ ", FIELD_GET(GENMASK(11, 0), dw_value)); ++ seq_printf(s, "SU:%ld/ ", FIELD_GET(BIT(12), dw_value)); ++ seq_printf(s, "SPP_EN:%ld/ ", FIELD_GET(BIT(13), dw_value)); ++ seq_printf(s, "WPI_EVEN:%ld\n\t",FIELD_GET(BIT(14), dw_value)); ++ seq_printf(s, "CIPHER:%lu/ ", FIELD_GET(GENMASK(20, 16), dw_value)); ++ seq_printf(s, "CIPHER_IGTK:%lu/ ",FIELD_GET(GENMASK(22, 21), dw_value)); ++ seq_printf(s, "AAD_OM:%ld\n\t", FIELD_GET(BIT(15), dw_value)); ++ seq_printf(s, "SW:%ld/ ", FIELD_GET(BIT(24), dw_value)); ++ seq_printf(s, "UL:%ld/ ", FIELD_GET(BIT(25), dw_value)); ++ seq_printf(s, "TX_POWER_SAVE:%ld\n\t", FIELD_GET(BIT(26), dw_value)); ++ seq_printf(s, "QOS:%ld/ ", FIELD_GET(BIT(27), dw_value)); ++ seq_printf(s, "HT:%ld/ ", FIELD_GET(BIT(28), dw_value)); ++ seq_printf(s, "VHT:%ld/ ", FIELD_GET(BIT(29), dw_value)); ++ seq_printf(s, "HE:%ld/ ", FIELD_GET(BIT(30), dw_value)); ++ seq_printf(s, "MESH:%ld\n", FIELD_GET(BIT(31), dw_value)); ++ ++ // DW3 ++ seq_printf(s, "LWTBL DW 3\n\t"); ++ addr = (u32 *)&(lwtbl[3*4]); ++ dw_value = *addr; ++ seq_printf(s, "WMM_Q:%lu/ ", FIELD_GET(GENMASK(1, 0), dw_value)); ++ seq_printf(s, "RXD_DUP_MODE:%lu\n\t", FIELD_GET(GENMASK(3, 2), dw_value)); ++ seq_printf(s, "VLAN2ETH:%ld/ ", FIELD_GET(BIT(4), dw_value)); ++ seq_printf(s, "BEAM_CHG:%ld/ ", FIELD_GET(BIT(5), dw_value)); ++ seq_printf(s, "DIS_BA256:%ld\n\t", FIELD_GET(BIT(6), dw_value)); ++ seq_printf(s, "PFMU_IDX:%lu/ ", FIELD_GET(GENMASK(15, 8), dw_value)); ++ seq_printf(s, "ULPF_IDX:%lu\n\t", FIELD_GET(GENMASK(23, 16), dw_value)); ++ seq_printf(s, "RIBF:%ld/ ", FIELD_GET(BIT(24), dw_value)); ++ seq_printf(s, "ULPF:%ld\n\t", FIELD_GET(BIT(25), dw_value)); ++ seq_printf(s, "IGN_FBK:%ld/ ", FIELD_GET(BIT(26), dw_value)); ++ seq_printf(s, "TBF:%ld/ ", FIELD_GET(BIT(29), dw_value)); ++ seq_printf(s, "TBF_VHT:%ld/ ", FIELD_GET(BIT(30), dw_value)); ++ seq_printf(s, "TBF_HE:%ld\n", FIELD_GET(BIT(31), dw_value)); ++ ++ // DW4 ++ seq_printf(s, "LWTBL DW 4\n\t"); ++ addr = (u32 *)&(lwtbl[4*4]); ++ dw_value = *addr; ++ seq_printf(s, "ANT_ID_STS0:%lu/ ", FIELD_GET(GENMASK(2, 0), dw_value)); ++ seq_printf(s, "STS1:%lu/ ", FIELD_GET(GENMASK(5, 3), dw_value)); ++ seq_printf(s, "STS2:%lu/ ", FIELD_GET(GENMASK(8, 6), dw_value)); ++ seq_printf(s, "STS3:%lu\n\t", FIELD_GET(GENMASK(11, 9), dw_value)); ++ seq_printf(s, "ANT_ID_STS4:%lu/ ", FIELD_GET(GENMASK(14, 12), dw_value)); ++ seq_printf(s, "STS5:%lu/ ", FIELD_GET(GENMASK(17, 15), dw_value)); ++ seq_printf(s, "STS6:%ld/ ", FIELD_GET(GENMASK(20, 18), dw_value)); ++ seq_printf(s, "STS7:%lu\n\t", FIELD_GET(GENMASK(23, 21), dw_value)); ++ seq_printf(s, "CASCAD:%ld/ ", FIELD_GET(BIT(24), dw_value)); ++ seq_printf(s, "LDPC_HT:%ld/ ", FIELD_GET(BIT(25), dw_value)); ++ seq_printf(s, "LDPC_VHT:%ld/ ", FIELD_GET(BIT(26), dw_value)); ++ seq_printf(s, "LDPC_HE:%ld\n\t", FIELD_GET(BIT(27), dw_value)); ++ seq_printf(s, "DIS_RHTR:%ld/ ", FIELD_GET(BIT(28), dw_value)); ++ seq_printf(s, "ALL_ACK:%ld/ ", FIELD_GET(BIT(29), dw_value)); ++ seq_printf(s, "DROP:%ld/ ", FIELD_GET(BIT(30), dw_value)); ++ seq_printf(s, "ACK_EN:%ld\n", FIELD_GET(BIT(31), dw_value)); ++ ++ // DW5 ++ seq_printf(s, "LWTBL DW 5\n\t"); ++ addr = (u32 *)&(lwtbl[5*4]); ++ dw_value = *addr; ++ seq_printf(s, "AF:%lu/ ", FIELD_GET(GENMASK(2, 0), dw_value)); ++ seq_printf(s, "AF_HE:%lu/ ", FIELD_GET(GENMASK(4, 3), dw_value)); ++ seq_printf(s, "RTS:%ld/ ", FIELD_GET(BIT(5), dw_value)); ++ seq_printf(s, "SMPS:%ld/ ", FIELD_GET(BIT(6), dw_value)); ++ seq_printf(s, "DYN_BW:%ld\n\t", FIELD_GET(BIT(7), dw_value)); ++ seq_printf(s, "MMSS:%lu/ ", FIELD_GET(GENMASK(10, 8), dw_value)); ++ seq_printf(s, "USR:%ld/ ", FIELD_GET(BIT(11), dw_value)); ++ seq_printf(s, "SR_RATE:%lu/ ", FIELD_GET(GENMASK(14, 12), dw_value)); ++ seq_printf(s, "SR_ABORT:%ld\n\t", FIELD_GET(BIT(15), dw_value)); ++ seq_printf(s, "TX_POWER_OFFSET:%lu/ ", FIELD_GET(GENMASK(21, 16), dw_value)); ++ seq_printf(s, "WTBL_MPDU_SIZE:%lu\n\t", FIELD_GET(GENMASK(23, 22), dw_value)); ++ seq_printf(s, "PE:%lu/ ", FIELD_GET(GENMASK(25, 24), dw_value)); ++ seq_printf(s, "DOPPL:%ld/ ", FIELD_GET(BIT(26), dw_value)); ++ seq_printf(s, "TXOP_PS_CAP:%ld/ ", FIELD_GET(BIT(27), dw_value)); ++ seq_printf(s, "DONOT_UPDATE_I_PSM:%ld\n\t", FIELD_GET(BIT(28), dw_value)); ++ seq_printf(s, "I_PSM:%ld/ ", FIELD_GET(BIT(29), dw_value)); ++ seq_printf(s, "PSM:%ld/ ", FIELD_GET(BIT(30), dw_value)); ++ seq_printf(s, "SKIP_TX:%ld\n", FIELD_GET(BIT(31), dw_value)); ++ ++ // DW6 ++ seq_printf(s, "LWTBL DW 6\n\t"); ++ seq_printf(s, "TID 0/1/2/3/4/5/6/7 BA_WIN_SIZE:"); ++ addr = (u32 *)&(lwtbl[6*4]); ++ dw_value = *addr; ++ seq_printf(s, "%lu/ ", FIELD_GET(GENMASK(3, 0), dw_value)); ++ seq_printf(s, "%lu/ ", FIELD_GET(GENMASK(7, 4), dw_value)); ++ seq_printf(s, "%lu/ ", FIELD_GET(GENMASK(11, 8), dw_value)); ++ seq_printf(s, "%lu/ ", FIELD_GET(GENMASK(15, 12), dw_value)); ++ seq_printf(s, "%lu/ ", FIELD_GET(GENMASK(19, 16), dw_value)); ++ seq_printf(s, "%lu/ ", FIELD_GET(GENMASK(23, 20), dw_value)); ++ seq_printf(s, "%lu/ ", FIELD_GET(GENMASK(27, 24), dw_value)); ++ seq_printf(s, "%lu\n", FIELD_GET(GENMASK(31, 28), dw_value)); ++ ++ // DW7 ++ seq_printf(s, "LWTBL DW 7\n\t"); ++ addr = (u32 *)&(lwtbl[7*4]); ++ dw_value = *addr; ++ seq_printf(s, "CBRN:%lu/ ", FIELD_GET(GENMASK(2, 0), dw_value)); ++ seq_printf(s, "DBNSS_EN:%ld/ ", FIELD_GET(BIT(3), dw_value)); ++ seq_printf(s, "BAF_EN:%ld/ ", FIELD_GET(BIT(4), dw_value)); ++ seq_printf(s, "RDGBA:%ld\n\t", FIELD_GET(BIT(5), dw_value)); ++ seq_printf(s, "RDG:%ld/ ", FIELD_GET(BIT(6), dw_value)); ++ seq_printf(s, "SPE_IDX:%lu/ ", FIELD_GET(GENMASK(11, 7), dw_value)); ++ seq_printf(s, "G2:%ld/ ", FIELD_GET(BIT(12), dw_value)); ++ seq_printf(s, "G4:%ld/ ", FIELD_GET(BIT(13), dw_value)); ++ seq_printf(s, "G8:%ld/ ", FIELD_GET(BIT(14), dw_value)); ++ seq_printf(s, "G16:%ld\n\t", FIELD_GET(BIT(15), dw_value)); ++ seq_printf(s, "G2_LTF:%lu/ ", FIELD_GET(GENMASK(17, 16), dw_value)); ++ seq_printf(s, "G4_LTF:%lu/ ", FIELD_GET(GENMASK(19, 18), dw_value)); ++ seq_printf(s, "G8_LTF:%lu/ ", FIELD_GET(GENMASK(21, 20), dw_value)); ++ seq_printf(s, "G16_LTF:%lu\n\t", FIELD_GET(GENMASK(23, 22), dw_value)); ++ seq_printf(s, "G2_HE:%lu/ ", FIELD_GET(GENMASK(25, 24), dw_value)); ++ seq_printf(s, "G4_HE:%lu/ ", FIELD_GET(GENMASK(27, 27), dw_value)); ++ seq_printf(s, "G8_HE:%lu/ ", FIELD_GET(GENMASK(29, 28), dw_value)); ++ seq_printf(s, "G16_HE:%lu\n", FIELD_GET(GENMASK(31, 30), dw_value)); ++ ++ // DW8 ++ seq_printf(s, "LWTBL DW 8\n\t"); ++ addr = (u32 *)&(lwtbl[8*4]); ++ dw_value = *addr; ++ seq_printf(s, "FAIL_CNT_AC0:%lu/ ", FIELD_GET(GENMASK(4, 0), dw_value)); ++ seq_printf(s, "AC1:%lu/ ", FIELD_GET(GENMASK(9, 5), dw_value)); ++ seq_printf(s, "AC2:%lu/ ", FIELD_GET(GENMASK(14, 10), dw_value)); ++ seq_printf(s, "AC3:%lu\n\t", FIELD_GET(GENMASK(19, 15), dw_value)); ++ seq_printf(s, "PARTIAL_AID:%lu/ ", FIELD_GET(GENMASK(28, 20), dw_value)); ++ seq_printf(s, "CHK_PER:%lu\n", FIELD_GET(BIT(31), dw_value)); ++ ++ // DW9 ++ seq_printf(s, "LWTBL DW 9\n\t"); ++ addr = (u32 *)&(lwtbl[9*4]); ++ dw_value = *addr; ++ seq_printf(s, "RX_AVG_MPDU:%lu/ ", FIELD_GET(GENMASK(13, 0), dw_value)); ++ seq_printf(s, "PRITX_SW_MODE:%ld/ ", FIELD_GET(BIT(16), dw_value)); ++ seq_printf(s, "PRITX_PLR:%ld\n\t", FIELD_GET(BIT(17), dw_value)); ++ seq_printf(s, "PRITX_DCM:%ld/ ", FIELD_GET(BIT(18), dw_value)); ++ seq_printf(s, "PRITX_ER160:%ld/ ", FIELD_GET(BIT(19), dw_value)); ++ seq_printf(s, "PRITX_ERSU:%lu\n\t", FIELD_GET(BIT(20), dw_value)); ++ seq_printf(s, "MPDU_FAIL_CNT:%lu/ ", FIELD_GET(GENMASK(25, 23), dw_value)); ++ seq_printf(s, "MPDU_OK_CNT:%lu/ ", FIELD_GET(GENMASK(28, 26), dw_value)); ++ seq_printf(s, "RATE_IDX:%lu\n\t", FIELD_GET(GENMASK(31, 29), dw_value)); ++ seq_printf(s, "FCAP:%s\n", fcap_str[FIELD_GET(GENMASK(22, 21), dw_value)]); ++ ++ // DW10 ++ seq_printf(s, "LWTBL DW 10\n"); ++ addr = (u32 *)&(lwtbl[10*4]); ++ dw_value = *addr; ++ parse_rate(s, 0, FIELD_GET(GENMASK(13, 0), dw_value)); ++ parse_rate(s, 1, FIELD_GET(GENMASK(29, 16), dw_value)); ++ // DW11 ++ seq_printf(s, "LWTBL DW 11\n"); ++ addr = (u32 *)&(lwtbl[11*4]); ++ dw_value = *addr; ++ parse_rate(s, 2, FIELD_GET(GENMASK(13, 0), dw_value)); ++ parse_rate(s, 3, FIELD_GET(GENMASK(29, 16), dw_value)); ++ // DW12 ++ seq_printf(s, "LWTBL DW 12\n"); ++ addr = (u32 *)&(lwtbl[12*4]); ++ dw_value = *addr; ++ parse_rate(s, 4, FIELD_GET(GENMASK(13, 0), dw_value)); ++ parse_rate(s, 5, FIELD_GET(GENMASK(29, 16), dw_value)); ++ // DW13 ++ seq_printf(s, "LWTBL DW 13\n"); ++ addr = (u32 *)&(lwtbl[13*4]); ++ dw_value = *addr; ++ parse_rate(s, 6, FIELD_GET(GENMASK(13, 0), dw_value)); ++ parse_rate(s, 7, FIELD_GET(GENMASK(29, 16), dw_value)); ++ ++ //DW28 ++ seq_printf(s, "LWTBL DW 28\n\t"); ++ addr = (u32 *)&(lwtbl[28*4]); ++ dw_value = *addr; ++ seq_printf(s, "OM_INFO:%lu/ ", FIELD_GET(GENMASK(11, 0), dw_value)); ++ seq_printf(s, "OM_RXD_DUP_MODE:%u\n\t", !!(dw_value & BIT(12)) ); ++ ++ //DW29 ++ seq_printf(s, "LWTBL DW 29\n"); ++ addr = (u32 *)&(lwtbl[29*4]); ++ dw_value = *addr; ++ seq_printf(s, "USER_RSSI:%lu/ ", FIELD_GET(GENMASK(8, 0), dw_value)); ++ seq_printf(s, "USER_SNR:%lu/ ", FIELD_GET(GENMASK(14, 9), dw_value)); ++ seq_printf(s, "RAPID_REACTION_RATE:%lu/ ", FIELD_GET(GENMASK(26, 16), dw_value)); ++ seq_printf(s, "HT_AMSDU(Read Only):%u/ ", !!(dw_value & BIT(30)) ); ++ seq_printf(s, "AMSDU_CROSS_LG(Read Only):%u\n\t ", !!(dw_value & BIT(31))); ++ ++ //DW30 ++ seq_printf(s, "LWTBL DW 30\n\t"); ++ addr = (u32 *)&(lwtbl[30*4]); ++ dw_value = *addr; ++ seq_printf(s, "RCPI 0:%lu/ ", FIELD_GET(GENMASK(7, 0), dw_value)); ++ seq_printf(s, "RCPI 1:%lu/ ", FIELD_GET(GENMASK(15, 8), dw_value)); ++ seq_printf(s, "RCPI 2:%lu/ ", FIELD_GET(GENMASK(23, 16), dw_value)); ++ seq_printf(s, "RCPI 3:%lu\n\t", FIELD_GET(GENMASK(31, 24), dw_value)); ++ ++ //DW31 ++ seq_printf(s, "LWTBL DW 31\n\t"); ++ addr = (u32 *)&(lwtbl[31*4]); ++ dw_value = *addr; ++ seq_printf(s, "RCPI 4:%lu/ ", FIELD_GET(GENMASK(7, 0), dw_value)); ++ seq_printf(s, "RCPI 5:%lu/ ", FIELD_GET(GENMASK(15, 8), dw_value)); ++ seq_printf(s, "RCPI 6:%lu/ ", FIELD_GET(GENMASK(23, 16), dw_value)); ++ seq_printf(s, "RCPI 7:%lu\n\t", FIELD_GET(GENMASK(31, 24), dw_value)); ++ ++ return 0; ++} ++ ++static int mt7915_uwtbl_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u8 uwtbl[UWTBL_LEN_IN_DW * 4] = {0}; ++ u8 keytbl[ONE_KEY_ENTRY_LEN_IN_DW*4] = {0}; ++ int x; ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u32 amsdu_len = 0; ++ u32 u2SN = 0; ++ u16 keyloc0, keyloc1; ++ ++ mt7915_wtbl_read_raw(dev, dev->wlan_idx, WTBL_TYPE_UMAC, 0, ++ UWTBL_LEN_IN_DW, uwtbl); ++ seq_printf(s, "Dump WTBL info of WLAN_IDX:%d\n", dev->wlan_idx); ++ seq_printf(s, "UMAC WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_UWTBL_TOP_WDUCR, ++ mt76_rr(dev, MT_DBG_UWTBL_TOP_BASE), ++ UWTBL_IDX2BASE(dev->wlan_idx, 0)); ++ for (x = 0; x < UWTBL_LEN_IN_DW; x++) { ++ seq_printf(s, "DW%02d: %02x %02x %02x %02x\n", ++ x, ++ uwtbl[x * 4 + 3], ++ uwtbl[x * 4 + 2], ++ uwtbl[x * 4 + 1], ++ uwtbl[x * 4]); ++ } ++ ++ /* UMAC WTBL DW 0 */ ++ seq_printf(s, "\nUWTBL PN\n\t"); ++ addr = (u32 *)&(uwtbl[0]); ++ dw_value = *addr; ++ seq_printf(s, "PN0:%lu/ ", FIELD_GET(GENMASK(7, 0), dw_value)); ++ seq_printf(s, "PN1:%lu/ ", FIELD_GET(GENMASK(15, 8), dw_value)); ++ seq_printf(s, "PN2:%lu\n\t", FIELD_GET(GENMASK(23, 16), dw_value)); ++ seq_printf(s, "PN3:%lu/ ", FIELD_GET(GENMASK(31, 24), dw_value)); ++ ++ addr = (u32 *)&(uwtbl[1 * 4]); ++ dw_value = *addr; ++ seq_printf(s, "PN4:%lu/ ", FIELD_GET(GENMASK(7, 0), dw_value)); ++ seq_printf(s, "PN5:%lu\n", FIELD_GET(GENMASK(15, 8), dw_value)); ++ ++ /* UMAC WTBL DW SN part */ ++ seq_printf(s, "\nUWTBL SN\n"); ++ addr = (u32 *)&(uwtbl[2 * 4]); ++ dw_value = *addr; ++ seq_printf(s, "TID0_AC0_SN:%lu\n", FIELD_GET(GENMASK(11, 0), dw_value)); ++ seq_printf(s, "TID1_AC1_SN:%lu\n", FIELD_GET(GENMASK(23, 12), dw_value)); ++ ++ u2SN = FIELD_GET(GENMASK(31, 24), dw_value); ++ addr = (u32 *)&(uwtbl[3 * 4]); ++ dw_value = *addr; ++ u2SN |= FIELD_GET(GENMASK(3, 0), dw_value); ++ seq_printf(s, "TID2_AC2_SN:%u\n", u2SN); ++ seq_printf(s, "TID3_AC3_SN:%lu\n", FIELD_GET(GENMASK(15, 4), dw_value)); ++ seq_printf(s, "TID4_SN:%lu\n", FIELD_GET(GENMASK(27, 16), dw_value)); ++ ++ u2SN = FIELD_GET(GENMASK(31, 28), dw_value); ++ addr = (u32 *)&(uwtbl[4 * 4]); ++ dw_value = *addr; ++ u2SN |= FIELD_GET(GENMASK(7, 0), dw_value); ++ seq_printf(s, "TID5_SN:%u\n", u2SN); ++ seq_printf(s, "TID6_SN:%lu\n", FIELD_GET(GENMASK(19, 8), dw_value)); ++ seq_printf(s, "TID7_SN:%lu\n", FIELD_GET(GENMASK(31, 20), dw_value)); ++ ++ addr = (u32 *)&(uwtbl[1 * 4]); ++ dw_value = *addr; ++ seq_printf(s, "COM_SN:%lu\n", FIELD_GET(GENMASK(27, 16), dw_value)); ++ ++ /* UMAC WTBL DW 0 */ ++ seq_printf(s, "\nUWTBL others\n"); ++ ++ addr = (u32 *)&(uwtbl[5 * 4]); ++ dw_value = *addr; ++ keyloc0 = FIELD_GET(GENMASK(10, 0), dw_value); ++ keyloc1 = FIELD_GET(GENMASK(26, 16), dw_value); ++ seq_printf(s, "\tKey Loc 1/2:%lu/%lu\n", ++ FIELD_GET(GENMASK(10, 0), dw_value), ++ FIELD_GET(GENMASK(26, 16), dw_value)); ++ seq_printf(s, "\tUWTBL_QOS:%lu\n", FIELD_GET(BIT(27), dw_value)); ++ seq_printf(s, "\tUWTBL_HT_VHT_HE:%lu\n", FIELD_GET(BIT(28), dw_value)); ++ ++ addr = (u32 *)&(uwtbl[6*4]); ++ dw_value = *addr; ++ seq_printf(s, "\tHW AMSDU Enable:%lu\n", FIELD_GET(BIT(9), dw_value)); ++ ++ amsdu_len = FIELD_GET(GENMASK(5, 0), dw_value); ++ if (amsdu_len == 0) ++ seq_printf(s, "\tHW AMSDU Len:invalid (WTBL value=0x%x)\n", amsdu_len); ++ else if (amsdu_len == 1) ++ seq_printf(s, "\tHW AMSDU Len:%d~%d (WTBL value=0x%x)\n", ++ 1, ++ 255, ++ amsdu_len); ++ else ++ seq_printf(s, "\tHW AMSDU Len:%d~%d (WTBL value=0x%x)\n", ++ 256 * (amsdu_len - 1), ++ 256 * (amsdu_len - 1) + 255, ++ amsdu_len ++ ); ++ seq_printf(s, "\tHW AMSDU Num:%lu (WTBL value=0x%lx)\n", ++ FIELD_GET(GENMASK(8, 6), dw_value) + 1, ++ FIELD_GET(GENMASK(8, 6), dw_value)); ++ ++ /* Parse KEY link */ ++ seq_printf(s, "\n\tkeyloc0:%d\n", keyloc0); ++ if(keyloc0 != GENMASK(10, 0)) { ++ mt7915_wtbl_read_raw(dev, keyloc0, WTBL_TYPE_KEY, ++ 0, ONE_KEY_ENTRY_LEN_IN_DW, keytbl); ++ seq_printf(s, "KEY WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_UWTBL_TOP_WDUCR, ++ mt76_rr(dev, MT_DBG_UWTBL_TOP_BASE), ++ KEYTBL_IDX2BASE(keyloc0, 0)); ++ ++ for (x = 0; x < ONE_KEY_ENTRY_LEN_IN_DW; x++) { ++ seq_printf(s, "DW%02d: %02x %02x %02x %02x\n", ++ x, ++ keytbl[x * 4 + 3], ++ keytbl[x * 4 + 2], ++ keytbl[x * 4 + 1], ++ keytbl[x * 4]); ++ } ++ } ++ ++ seq_printf(s, "\n\tkeyloc1:%d\n", keyloc1); ++ if(keyloc1 != GENMASK(26, 16)) { ++ mt7915_wtbl_read_raw(dev, keyloc1, WTBL_TYPE_KEY, ++ 0, ONE_KEY_ENTRY_LEN_IN_DW, keytbl); ++ seq_printf(s, "KEY WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_UWTBL_TOP_WDUCR, ++ mt76_rr(dev, MT_DBG_UWTBL_TOP_BASE), ++ KEYTBL_IDX2BASE(keyloc1, 0)); ++ ++ for (x = 0; x < ONE_KEY_ENTRY_LEN_IN_DW; x++) { ++ seq_printf(s, "DW%02d: %02x %02x %02x %02x\n", ++ x, ++ keytbl[x * 4 + 3], ++ keytbl[x * 4 + 2], ++ keytbl[x * 4 + 1], ++ keytbl[x * 4]); ++ } ++ } ++ return 0; ++} ++ ++static void ++dump_dma_tx_ring_info(struct seq_file *s, struct mt7915_dev *dev, char *str, u32 ring_base) ++{ ++ u32 base, cnt, cidx, didx, queue_cnt; ++ ++ base= mt76_rr(dev, ring_base); ++ cnt = mt76_rr(dev, ring_base + 4); ++ cidx = mt76_rr(dev, ring_base + 8); ++ didx = mt76_rr(dev, ring_base + 12); ++ queue_cnt = (cidx >= didx) ? (cidx - didx) : (cidx - didx + cnt); ++ ++ seq_printf(s, "%20s %10x %10x %10x %10x %10x\n", str, base, cnt, cidx, didx, queue_cnt); ++} ++ ++static void ++dump_dma_rx_ring_info(struct seq_file *s, struct mt7915_dev *dev, char *str, u32 ring_base) ++{ ++ u32 base, cnt, cidx, didx, queue_cnt; ++ ++ base= mt76_rr(dev, ring_base); ++ cnt = mt76_rr(dev, ring_base + 4); ++ cidx = mt76_rr(dev, ring_base + 8); ++ didx = mt76_rr(dev, ring_base + 12); ++ queue_cnt = (didx > cidx) ? (didx - cidx - 1) : (didx - cidx + cnt - 1); ++ ++ seq_printf(s, "%20s %10x %10x %10x %10x %10x\n", str, base, cnt, cidx, didx, queue_cnt); ++} ++ ++static void ++mt7915_show_host_dma_info(struct seq_file *s, struct mt7915_dev *dev) ++{ ++ u32 sys_ctrl[10] = {}; ++ ++ /* HOST DMA */ ++ sys_ctrl[0] = mt76_rr(dev, MT_DBG_INT_SOURCE_CSR); ++ sys_ctrl[1] = mt76_rr(dev, MT_DBG_INT_MASK_CSR); ++ sys_ctrl[2] = mt76_rr(dev, MT_DBG_WFDMA0_INT_SOURCE_CSR); ++ sys_ctrl[3] = mt76_rr(dev, MT_DBG_WFDMA0_INT_MASK_CSR); ++ sys_ctrl[4] = mt76_rr(dev, MT_DBG_WFDMA1_INT_SOURCE_CSR); ++ sys_ctrl[5] = mt76_rr(dev, MT_DBG_WFDMA1_INT_MASK_CSR); ++ sys_ctrl[6] = mt76_rr(dev, MT_DBG_WFDMA0_GLO_CFG); ++ sys_ctrl[7] = mt76_rr(dev, MT_DBG_WFDMA1_GLO_CFG); ++ seq_printf(s, "HOST_DMA Configuration\n"); ++ seq_printf(s, "%10s %10s %10s %10s %10s %10s\n", ++ "DMA", "IntCSR", "IntMask", "Glocfg", "Tx/RxEn", "Tx/RxBusy"); ++ seq_printf(s, "%10s %10x %10x\n", ++ "Merge", sys_ctrl[0], sys_ctrl[1]); ++ seq_printf(s, "%10s %10x %10x %10x %4lx/%5lx %4lx/%5lx\n", ++ "DMA0", sys_ctrl[2], sys_ctrl[3], sys_ctrl[6], ++ FIELD_GET(MT_DBG_WFDMA0_GLO_CFG_TX_DMA_EN, sys_ctrl[6]), ++ FIELD_GET(MT_DBG_WFDMA0_GLO_CFG_RX_DMA_EN, sys_ctrl[6]), ++ FIELD_GET(MT_DBG_WFDMA0_GLO_CFG_TX_BUSY_MASK, sys_ctrl[6]), ++ FIELD_GET(MT_DBG_WFDMA0_GLO_CFG_RX_BUSY_MASK, sys_ctrl[6])); ++ ++ seq_printf(s, "%10s %10x %10x %10x %4lx/%5lx %4lx/%5lx\n", ++ "DMA1", sys_ctrl[4], sys_ctrl[5], sys_ctrl[7], ++ FIELD_GET(MT_DBG_WFDMA1_GLO_CFG_TX_DMA_EN, sys_ctrl[7]), ++ FIELD_GET(MT_DBG_WFDMA1_GLO_CFG_RX_DMA_EN, sys_ctrl[7]), ++ FIELD_GET(MT_DBG_WFDMA1_GLO_CFG_TX_BUSY_MASK, sys_ctrl[7]), ++ FIELD_GET(MT_DBG_WFDMA1_GLO_CFG_RX_BUSY_MASK, sys_ctrl[7])); ++ ++ sys_ctrl[0] = mt76_rr(dev, MT_DBG_INT1_SOURCE_CSR); ++ sys_ctrl[1] = mt76_rr(dev, MT_DBG_INT1_MASK_CSR); ++ sys_ctrl[2] = mt76_rr(dev, MT_DBG_WFDMA0_PCIE1_INT_SOURCE_CSR); ++ sys_ctrl[3] = mt76_rr(dev, MT_DBG_WFDMA0_PCIE1_INT_MASK_CSR); ++ sys_ctrl[4] = mt76_rr(dev, MT_DBG_WFDMA1_PCIE1_INT_SOURCE_CSR); ++ sys_ctrl[5] = mt76_rr(dev, MT_DBG_WFDMA1_PCIE1_INT_MASK_CSR); ++ sys_ctrl[6] = mt76_rr(dev, MT_DBG_WFDMA0_PCIE1_GLO_CFG); ++ sys_ctrl[7] = mt76_rr(dev, MT_DBG_WFDMA1_PCIE1_GLO_CFG); ++ seq_printf(s, "%10s %10x %10x\n", ++ "MergeP1", sys_ctrl[0], sys_ctrl[1]); ++ seq_printf(s, "%10s %10x %10x %10x %4lx/%5lx %4lx/%5lx\n", ++ "DMA0P1", sys_ctrl[2], sys_ctrl[3], sys_ctrl[6], ++ FIELD_GET(MT_DBG_WFDMA0_PCIE1_GLO_CFG_TX_DMA_EN, sys_ctrl[6]), ++ FIELD_GET(MT_DBG_WFDMA0_PCIE1_GLO_CFG_RX_DMA_EN, sys_ctrl[6]), ++ FIELD_GET(MT_DBG_WFDMA0_PCIE1_GLO_CFG_TX_BUSY_MASK, sys_ctrl[6]), ++ FIELD_GET(MT_DBG_WFDMA0_PCIE1_GLO_CFG_RX_BUSY_MASK, sys_ctrl[6])); ++ seq_printf(s, "%10s %10x %10x %10x %4lx/%5lx %4lx/%5lx\n", ++ "DMA1P1", sys_ctrl[4], sys_ctrl[5], sys_ctrl[7], ++ FIELD_GET(MT_DBG_WFDMA0_PCIE1_GLO_CFG_TX_DMA_EN, sys_ctrl[7]), ++ FIELD_GET(MT_DBG_WFDMA0_PCIE1_GLO_CFG_RX_DMA_EN, sys_ctrl[7]), ++ FIELD_GET(MT_DBG_WFDMA0_PCIE1_GLO_CFG_TX_BUSY_MASK, sys_ctrl[7]), ++ FIELD_GET(MT_DBG_WFDMA0_PCIE1_GLO_CFG_RX_BUSY_MASK, sys_ctrl[7])); ++ ++ seq_printf(s, "HOST_DMA0 Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_rx_ring_info(s, dev, "R0:Data0(MAC2H)", MT_DBG_RX_DATA_RING_CTRL(0)); ++ dump_dma_rx_ring_info(s, dev, "R1:Data1(MAC2H)", MT_DBG_RX_DATA_RING_CTRL(1)); ++ ++ seq_printf(s, "HOST_DMA0 PCIe 1 Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_rx_ring_info(s, dev, "R1:Data1(MAC2H)", MT_DBG_WFDMA0_PCIE1_RX1_CTRL0); ++ ++ seq_printf(s, "HOST_DMA1 Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T16:FWDL", MT_DBG_TX_RING_CTRL(0)); ++ dump_dma_tx_ring_info(s, dev, "T17:Cmd(H2WM)", MT_DBG_TX_RING_CTRL(1)); ++ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { ++ dump_dma_tx_ring_info(s, dev, "T18:TXD0(H2WA)", MT_DBG_WFDMA_WED_TX_CTRL(0)); ++ dump_dma_tx_ring_info(s, dev, "T19:TXD1(H2WA)", MT_DBG_WFDMA_WED_TX_CTRL(1)); ++ } else { ++ dump_dma_tx_ring_info(s, dev, "T18:TXD0(H2WA)", MT_DBG_TX_RING_CTRL(2)); ++ dump_dma_tx_ring_info(s, dev, "T19:TXD1(H2WA)", MT_DBG_TX_RING_CTRL(3)); ++ } ++ dump_dma_tx_ring_info(s, dev, "T20:Cmd(H2WA)", MT_DBG_TX_RING_CTRL(4)); ++ dump_dma_rx_ring_info(s, dev, "R0:Event(WM2H)", MT_DBG_RX_EVENT_RING_CTRL(0)); ++ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) ++ dump_dma_rx_ring_info(s, dev, "R1:TxDone(WA2H)", MT_DBG_WFDMA_WED_RX_CTRL(1)); ++ else ++ dump_dma_rx_ring_info(s, dev, "R1:Event0(WA2H)", MT_DBG_RX_EVENT_RING_CTRL(1)); ++ dump_dma_rx_ring_info(s, dev, "R2:Event1(WA2H)", MT_DBG_RX_EVENT_RING_CTRL(2)); ++ ++ seq_printf(s, "HOST_DMA1 PCIe 1 Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T19:TXD1(H2WA)", MT_DBG_WFDMA1_PCIE1_TX19_CTRL0); ++ dump_dma_rx_ring_info(s, dev, "R2:Event1(WA2H)", MT_DBG_WFDMA1_PCIE1_RX2_CTRL0); ++} ++ ++static void ++mt7915_show_mcu_dma_info(struct seq_file *s, struct mt7915_dev *dev) ++{ ++ u32 sys_ctrl[9] = {}; ++ ++ /* MCU DMA information */ ++ sys_ctrl[0] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR); ++ sys_ctrl[1] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_HOST_INT_STA_ADDR); ++ sys_ctrl[2] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_HOST_INT_ENA_ADDR); ++ ++ sys_ctrl[3] = mt76_rr(dev, WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_ADDR); ++ sys_ctrl[4] = mt76_rr(dev, WF_WFDMA_MCU_DMA1_HOST_INT_STA_ADDR); ++ sys_ctrl[5] = mt76_rr(dev, WF_WFDMA_MCU_DMA1_HOST_INT_ENA_ADDR); ++ sys_ctrl[6] = mt76_rr(dev, WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_ADDR); ++ sys_ctrl[7] = mt76_rr(dev, WF_WFDMA_MCU_DMA1_PCIE1_HOST_INT_STA_ADDR); ++ sys_ctrl[8] = mt76_rr(dev, WF_WFDMA_MCU_DMA1_PCIE1_HOST_INT_ENA_ADDR); ++ ++ seq_printf(s, "MCU_DMA Configuration\n"); ++ seq_printf(s, "%10s %10s %10s %10s %10s %10s\n", ++ "DMA", "IntCSR", "IntMask", "Glocfg", "Tx/RxEn", "Tx/RxBusy"); ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "DMA0", sys_ctrl[1], sys_ctrl[2], sys_ctrl[0], ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK) >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK) >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "DMA1", sys_ctrl[4], sys_ctrl[5], sys_ctrl[3], ++ (sys_ctrl[3] & WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_MASK) >> WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[3] & WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_MASK) >> WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[3] & WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) >> WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[3] & WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) >> WF_WFDMA_MCU_DMA1_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "DMA1P1", sys_ctrl[7], sys_ctrl[8], sys_ctrl[6], ++ (sys_ctrl[6] & WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_TX_DMA_EN_MASK) >> WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[6] & WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_RX_DMA_EN_MASK) >> WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[6] & WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) >> WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[6] & WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) >> WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ ++ seq_printf(s, "MCU_DMA0 Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T0:TXD(WM2MAC)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T1:TXCMD(WM2MAC)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING1_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T2:TXD(WA2MAC)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING2_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R0:Data(MAC2WM)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R1:TxDone(MAC2WM)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R2:SPL(MAC2WM)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING2_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R3:TxDone(MAC2WA)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING3_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R4:TXS(MAC2WA)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING4_CTRL0_ADDR); ++ ++ seq_printf(s, "MCU_DMA1 Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T0:Event(WM2H)", WF_WFDMA_MCU_DMA1_WPDMA_TX_RING0_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T1:Event0(WA2H)", WF_WFDMA_MCU_DMA1_WPDMA_TX_RING1_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T2:Event1(WA2H)", WF_WFDMA_MCU_DMA1_WPDMA_TX_RING2_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R0:FWDL", WF_WFDMA_MCU_DMA1_WPDMA_RX_RING0_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R1:Cmd(H2WM)", WF_WFDMA_MCU_DMA1_WPDMA_RX_RING1_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R2:TXD0(H2WA)", WF_WFDMA_MCU_DMA1_WPDMA_RX_RING2_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R3:TXD1(H2WA)", WF_WFDMA_MCU_DMA1_WPDMA_RX_RING3_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R4:Cmd(H2WA)", WF_WFDMA_MCU_DMA1_WPDMA_RX_RING4_CTRL0_ADDR); ++ ++ seq_printf(s, "MCU_DMA1 PCIe 1 Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T2:Event1(WA2H)", WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_TX_RING2_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R3:TXD1(H2WA)", WF_WFDMA_MCU_DMA1_PCIE1_WPDMA_RX_RING3_CTRL0_ADDR); ++} ++ ++static void ++mt7986_show_host_dma_info(struct seq_file *s, struct mt7915_dev *dev) ++{ ++ u32 sys_ctrl[5] = {}; ++ ++ /* HOST DMA */ ++ sys_ctrl[0] = mt76_rr(dev, MT_DBG_INT_SOURCE_CSR); ++ sys_ctrl[1] = mt76_rr(dev, MT_DBG_INT_MASK_CSR); ++ sys_ctrl[2] = mt76_rr(dev, MT_DBG_WFDMA0_INT_SOURCE_CSR); ++ sys_ctrl[3] = mt76_rr(dev, MT_DBG_WFDMA0_INT_MASK_CSR); ++ sys_ctrl[4] = mt76_rr(dev, MT_DBG_WFDMA0_GLO_CFG); ++ ++ seq_printf(s, "HOST_DMA Configuration\n"); ++ seq_printf(s, "%10s %10s %10s %10s %10s %10s\n", ++ "DMA", "IntCSR", "IntMask", "Glocfg", "Tx/RxEn", "Tx/RxBusy"); ++ seq_printf(s, "%10s %10x %10x\n", ++ "Merge", sys_ctrl[0], sys_ctrl[1]); ++ seq_printf(s, "%10s %10x %10x %10x %4lx/%5lx %4lx/%5lx\n", ++ "DMA0", sys_ctrl[2], sys_ctrl[3], sys_ctrl[4], ++ FIELD_GET(MT_DBG_WFDMA_HOST_DMA0_GLO_CFG_TX_DMA_EN_MASK, sys_ctrl[4]), ++ FIELD_GET(MT_DBG_WFDMA_HOST_DMA0_GLO_CFG_RX_DMA_EN_MASK, sys_ctrl[4]), ++ FIELD_GET(MT_DBG_WFDMA_HOST_DMA0_GLO_CFG_TX_DMA_BUSY_MASK, sys_ctrl[4]), ++ FIELD_GET(MT_DBG_WFDMA_HOST_DMA0_GLO_CFG_RX_DMA_BUSY_MASK, sys_ctrl[4])); ++ ++ ++ seq_printf(s, "HOST_DMA0 Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T16:FWDL", MT_DBG_TX_RING_CTRL(0)); ++ dump_dma_tx_ring_info(s, dev, "T17:Cmd(H2WM)", MT_DBG_TX_RING_CTRL(1)); ++ ++ if (is_mt7916(&dev->mt76) && mtk_wed_device_active(&dev->mt76.mmio.wed)) { ++ dump_dma_tx_ring_info(s, dev, "T18:TXD0(H2WA)", MT_DBG_WFDMA_WED_TX_CTRL(0)); ++ dump_dma_tx_ring_info(s, dev, "T19:TXD1(H2WA)", MT_DBG_WFDMA_WED_TX_CTRL(1)); ++ } else { ++ dump_dma_tx_ring_info(s, dev, "T18:TXD0(H2WA)", MT_DBG_TX_RING_CTRL(2)); ++ dump_dma_tx_ring_info(s, dev, "T19:TXD1(H2WA)", MT_DBG_TX_RING_CTRL(3)); ++ } ++ ++ dump_dma_tx_ring_info(s, dev, "T20:Cmd(H2WA)", MT_DBG_TX_RING_CTRL(4)); ++ dump_dma_rx_ring_info(s, dev, "R0:Event(WM2H)", MT_DBG_RX_DATA_RING_CTRL(0)); ++ dump_dma_rx_ring_info(s, dev, "R1:Event(WA2H)", MT_DBG_RX_EVENT_RING_CTRL(1)); ++ if (is_mt7916(&dev->mt76) && mtk_wed_device_active(&dev->mt76.mmio.wed)) ++ dump_dma_rx_ring_info(s, dev, "R2:TxDone(WA2H)", MT_DBG_WFDMA_WED_RX_CTRL(1)); ++ else ++ dump_dma_rx_ring_info(s, dev, "R2:TxDone(WA2H)", MT_DBG_RX_EVENT_RING_CTRL(2)); ++ dump_dma_rx_ring_info(s, dev, "R3:TxDone1(WA2H)", MT_DBG_RX_EVENT_RING_CTRL(3)); ++ dump_dma_rx_ring_info(s, dev, "R4:Data0(MAC2H)", MT_DBG_RX_DATA_RING_CTRL(0)); ++ dump_dma_rx_ring_info(s, dev, "R5:Data1(MAC2H)", MT_DBG_RX_DATA_RING_CTRL(1)); ++} ++ ++static void ++mt7986_show_mcu_dma_info(struct seq_file *s, struct mt7915_dev *dev) ++{ ++ u32 sys_ctrl[3] = {}; ++ ++ /* MCU DMA information */ ++ sys_ctrl[0] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR); ++ sys_ctrl[1] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_HOST_INT_STA_ADDR); ++ sys_ctrl[2] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_HOST_INT_ENA_ADDR); ++ ++ seq_printf(s, "MCU_DMA Configuration\n"); ++ seq_printf(s, "%10s %10s %10s %10s %10s %10s\n", ++ "DMA", "IntCSR", "IntMask", "Glocfg", "Tx/RxEn", "Tx/RxBusy"); ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "DMA0", sys_ctrl[1], sys_ctrl[2], sys_ctrl[0], ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK) >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK) >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ ++ seq_printf(s, "MCU_DMA0 Ring Configuration\n"); ++ seq_printf(s, "%22s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T0:Event (WM2H)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T1:Event (WA2H)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING1_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T2:TxDone (WA2H)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING2_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T3:TxDone1 (WA2H)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING3_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T4:TXD (WM2MAC)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING4_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T5:TXCMD (WM2MAC)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING5_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T6:TXD (WA2MAC)", WF_WFDMA_MCU_DMA0_WPDMA_TX_RING6_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R0:FWDL", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R1:Cmd (H2WM)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R2:TXD (H2WA)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING2_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R3:TXD1 (H2WA)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING3_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R4:Cmd (H2WA)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING4_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R5:Data (MAC2WM)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING5_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R6:TxDone/STS (MAC2WM)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING6_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R7:RPT (MAC2WM)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING7_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R8:TxDone/STS (MAC2WA)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING8_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R9:Data1 (MAC2WM)", WF_WFDMA_MCU_DMA0_WPDMA_RX_RING9_CTRL0_ADDR); ++ ++} ++ ++static void ++mt7915_show_dma_info(struct seq_file *s, struct mt7915_dev *dev) ++{ ++ u32 sys_ctrl[10] = {}; ++ ++ if(is_mt7915(&dev->mt76)) { ++ mt7915_show_host_dma_info(s, dev); ++ mt7915_show_mcu_dma_info(s, dev); ++ } else { ++ mt7986_show_host_dma_info(s, dev); ++ mt7986_show_mcu_dma_info(s, dev); ++ } ++ ++ /* MEM DMA information */ ++ sys_ctrl[0] = mt76_rr(dev, WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_ADDR); ++ sys_ctrl[1] = mt76_rr(dev, WF_WFDMA_MEM_DMA_HOST_INT_STA_ADDR); ++ sys_ctrl[2] = mt76_rr(dev, WF_WFDMA_MEM_DMA_HOST_INT_ENA_ADDR); ++ ++ seq_printf(s, "MEM_DMA Configuration\n"); ++ seq_printf(s, "%10s %10s %10s %10s %10s %10s\n", ++ "DMA", "IntCSR", "IntMask", "Glocfg", "Tx/RxEn", "Tx/RxBusy"); ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "MEM", sys_ctrl[1], sys_ctrl[2], sys_ctrl[0], ++ (sys_ctrl[0] & WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_MASK) >> WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_MASK) >> WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) >> WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) >> WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ ++ seq_printf(s, "MEM_DMA Ring Configuration\n"); ++ seq_printf(s, "%20s %10s %10s %10s %10s %10s\n", ++ "Name", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T0:CmdEvent(WM2WA)", WF_WFDMA_MEM_DMA_WPDMA_TX_RING0_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T1:CmdEvent(WA2WM)", WF_WFDMA_MEM_DMA_WPDMA_TX_RING1_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R0:CmdEvent(WM2WA)", WF_WFDMA_MEM_DMA_WPDMA_RX_RING0_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R1:CmdEvent(WA2WM)", WF_WFDMA_MEM_DMA_WPDMA_RX_RING1_CTRL0_ADDR); ++} ++ ++static int mt7915_trinfo_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ const struct hif_pci_tx_ring_desc *tx_ring_layout; ++ const struct hif_pci_rx_ring_desc *rx_ring_layout; ++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed; ++ u32 tx_ring_num, rx_ring_num; ++ u32 tbase[5], tcnt[5]; ++ u32 tcidx[5], tdidx[5]; ++ u32 rbase[6], rcnt[6]; ++ u32 rcidx[6], rdidx[6]; ++ int idx; ++ bool flags = false; ++ ++ if(is_mt7915(&dev->mt76)) { ++ tx_ring_layout = &mt7915_tx_ring_layout[0]; ++ rx_ring_layout = &mt7915_rx_ring_layout[0]; ++ tx_ring_num = ARRAY_SIZE(mt7915_tx_ring_layout); ++ rx_ring_num = ARRAY_SIZE(mt7915_rx_ring_layout); ++ } else { ++ tx_ring_layout = &mt7986_tx_ring_layout[0]; ++ rx_ring_layout = &mt7986_rx_ring_layout[0]; ++ tx_ring_num = ARRAY_SIZE(mt7986_tx_ring_layout); ++ rx_ring_num = ARRAY_SIZE(mt7986_rx_ring_layout); ++ } ++ ++ for (idx = 0; idx < tx_ring_num; idx++) { ++ if (mtk_wed_device_active(wed) && ++ (tx_ring_layout[idx].ring_attr == HIF_TX_DATA)) { ++ struct mt76_phy *phy = dev->mt76.phys[MT_BAND0]; ++ struct mt76_phy *ext_phy = dev->mt76.phys[MT_BAND1]; ++ struct mt76_queue *q; ++ ++ tbase[idx] = tcnt[idx] = tcidx[idx] = tdidx[idx] = 0; ++ ++ if (!phy) ++ continue; ++ ++ if (flags && !ext_phy) ++ continue; ++ ++ if (flags && ext_phy) ++ phy = ext_phy; ++ ++ q = phy->q_tx[0]; ++ ++ if (q->wed_regs) { ++ tbase[idx] = mtk_wed_device_reg_read(wed, q->wed_regs); ++ tcnt[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x04); ++ tcidx[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x08); ++ tdidx[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x0c); ++ } ++ ++ flags = true; ++ } else { ++ tbase[idx] = mt76_rr(dev, MT_DBG_TX_RING_CTRL(idx)); ++ tcnt[idx] = mt76_rr(dev, MT_DBG_TX_RING_CTRL(idx) + 0x04); ++ tcidx[idx] = mt76_rr(dev, MT_DBG_TX_RING_CTRL(idx) + 0x08); ++ tdidx[idx] = mt76_rr(dev, MT_DBG_TX_RING_CTRL(idx) + 0x0c);} ++ } ++ ++ for (idx = 0; idx < rx_ring_num; idx++) { ++ if (rx_ring_layout[idx].ring_attr == HIF_RX_DATA) { ++ if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) { ++ struct mt76_queue *q = &dev->mt76.q_rx[MT_RXQ_MAIN]; ++ ++ rbase[idx] = rcnt[idx] = rcidx[idx] = rdidx[idx] = 0; ++ ++ if (idx == 1) ++ q = &dev->mt76.q_rx[MT_RXQ_BAND1]; ++ ++ if (q->wed_regs) { ++ rbase[idx] = mtk_wed_device_reg_read(wed, q->wed_regs); ++ rcnt[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x04); ++ rcidx[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x08); ++ rdidx[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x0c); ++ } ++ } else { ++ rbase[idx] = mt76_rr(dev, MT_DBG_RX_DATA_RING_CTRL(idx)); ++ rcnt[idx] = mt76_rr(dev, MT_DBG_RX_DATA_RING_CTRL(idx) + 0x04); ++ rcidx[idx] = mt76_rr(dev, MT_DBG_RX_DATA_RING_CTRL(idx) + 0x08); ++ rdidx[idx] = mt76_rr(dev, MT_DBG_RX_DATA_RING_CTRL(idx) + 0x0c); ++ } ++ } else { ++ if (mtk_wed_device_active(wed) && rx_ring_layout[idx].flags) { ++ struct mt76_queue *q = &dev->mt76.q_rx[MT_RXQ_MAIN_WA]; ++ ++ if (is_mt7915(&dev->mt76)) ++ q = &dev->mt76.q_rx[MT_RXQ_MCU_WA]; ++ ++ rbase[idx] = mtk_wed_device_reg_read(wed, q->wed_regs); ++ rcnt[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x04); ++ rcidx[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x08); ++ rdidx[idx] = mtk_wed_device_reg_read(wed, q->wed_regs + 0x0c); ++ ++ } else { ++ rbase[idx] = mt76_rr(dev, MT_DBG_RX_EVENT_RING_CTRL(idx - 2)); ++ rcnt[idx] = mt76_rr(dev, MT_DBG_RX_EVENT_RING_CTRL(idx - 2) + 0x04); ++ rcidx[idx] = mt76_rr(dev, MT_DBG_RX_EVENT_RING_CTRL(idx - 2) + 0x08); ++ rdidx[idx] = mt76_rr(dev, MT_DBG_RX_EVENT_RING_CTRL(idx - 2) + 0x0c); ++ } ++ } ++ } ++ ++ seq_printf(s, "=================================================\n"); ++ seq_printf(s, "TxRing Configuration\n"); ++ seq_printf(s, "%4s %10s %8s %1s %6s %6s %6s %6s\n", ++ "Idx", "Attr", "Reg", "Base", "Cnt", "CIDX", "DIDX", ++ "QCnt"); ++ for (idx = 0; idx < tx_ring_num; idx++) { ++ u32 queue_cnt; ++ ++ queue_cnt = (tcidx[idx] >= tdidx[idx]) ? ++ (tcidx[idx] - tdidx[idx]) : ++ (tcidx[idx] - tdidx[idx] + tcnt[idx]); ++ seq_printf(s, "%4d %8s %8x %10x %6x %6x %6x %6x\n", ++ idx, tx_ring_layout[idx].ring_info, ++ MT_DBG_TX_RING_CTRL(idx), tbase[idx], ++ tcnt[idx], tcidx[idx], tdidx[idx], queue_cnt); ++ } ++ ++ seq_printf(s, "RxRing Configuration\n"); ++ seq_printf(s, "%4s %10s %8s %10s %6s %6s %6s %6s\n", ++ "Idx", "Attr", "Reg", "Base", "Cnt", "CIDX", "DIDX", ++ "QCnt"); ++ ++ for (idx = 0; idx < rx_ring_num; idx++) { ++ u32 queue_cnt; ++ ++ queue_cnt = (rdidx[idx] > rcidx[idx]) ? ++ (rdidx[idx] - rcidx[idx] - 1) : ++ (rdidx[idx] - rcidx[idx] + rcnt[idx] - 1); ++ seq_printf(s, "%4d %8s %8x %10x %6x %6x %6x %6x\n", ++ idx, rx_ring_layout[idx].ring_info, ++ (idx < 2) ? MT_DBG_RX_DATA_RING_CTRL(idx): MT_DBG_RX_EVENT_RING_CTRL(idx - 2), ++ rbase[idx], rcnt[idx], rcidx[idx], rdidx[idx], queue_cnt); ++ } ++ ++ mt7915_show_dma_info(s, dev); ++ return 0; ++} ++ ++static int mt7915_drr_info(struct seq_file *s, void *data) ++{ ++#define DL_AC_START 0x00 ++#define DL_AC_END 0x0F ++#define UL_AC_START 0x10 ++#define UL_AC_END 0x1F ++ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 drr_sta_status[16]; ++ u32 drr_ctrl_def_val = 0x80220000, drr_ctrl_val = 0; ++ bool is_show = false; ++ int idx, sta_line = 0, sta_no = 0, max_sta_line = (mt7915_wtbl_size(dev) + 31) / 32; ++ seq_printf(s, "DRR Table STA Info:\n"); ++ ++ for (idx = DL_AC_START; idx <= DL_AC_END; idx++) { ++ is_show = true; ++ drr_ctrl_val = (drr_ctrl_def_val | idx); ++ mt76_wr(dev, MT_DBG_PLE_DRR_TAB_CTRL, drr_ctrl_val); ++ drr_sta_status[0] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA0); ++ drr_sta_status[1] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA1); ++ drr_sta_status[2] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA2); ++ drr_sta_status[3] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA3); ++ drr_sta_status[4] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA4); ++ drr_sta_status[5] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA5); ++ drr_sta_status[6] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA6); ++ drr_sta_status[7] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA7); ++ ++ if (is_mt7915(&dev->mt76) && max_sta_line > 8) { ++ drr_ctrl_val = (drr_ctrl_def_val | idx | 1 << 10); ++ mt76_wr(dev, MT_DBG_PLE_DRR_TAB_CTRL, drr_ctrl_val); ++ drr_sta_status[8] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA0); ++ drr_sta_status[9] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA1); ++ drr_sta_status[10] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA2); ++ drr_sta_status[11] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA3); ++ drr_sta_status[12] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA4); ++ drr_sta_status[13] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA5); ++ drr_sta_status[14] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA6); ++ drr_sta_status[15] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA7); ++ } ++ if (!is_mt7915(&dev->mt76)) ++ max_sta_line = 8; ++ ++ for (sta_line = 0; sta_line < max_sta_line; sta_line++) { ++ if (drr_sta_status[sta_line] > 0) { ++ for (sta_no = 0; sta_no < 32; sta_no++) { ++ if (((drr_sta_status[sta_line] & (0x1 << sta_no)) >> sta_no)) { ++ if (is_show) { ++ seq_printf(s, "\n DL AC%02d Queue Non-Empty STA:\n", idx); ++ is_show = false; ++ } ++ seq_printf(s, "%d ", sta_no + (sta_line * 32)); ++ } ++ } ++ } ++ } ++ } ++ ++ for (idx = UL_AC_START; idx <= UL_AC_END; idx++) { ++ is_show = true; ++ drr_ctrl_val = (drr_ctrl_def_val | idx); ++ mt76_wr(dev, MT_DBG_PLE_DRR_TAB_CTRL, drr_ctrl_val); ++ drr_sta_status[0] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA0); ++ drr_sta_status[1] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA1); ++ drr_sta_status[2] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA2); ++ drr_sta_status[3] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA3); ++ drr_sta_status[4] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA4); ++ drr_sta_status[5] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA5); ++ drr_sta_status[6] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA6); ++ drr_sta_status[7] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA7); ++ ++ if (is_mt7915(&dev->mt76) && max_sta_line > 8) { ++ drr_ctrl_val = (drr_ctrl_def_val | idx | 1 << 10); ++ mt76_wr(dev, MT_DBG_PLE_DRR_TAB_CTRL, drr_ctrl_val); ++ drr_sta_status[8] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA0); ++ drr_sta_status[9] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA1); ++ drr_sta_status[10] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA2); ++ drr_sta_status[11] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA3); ++ drr_sta_status[12] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA4); ++ drr_sta_status[13] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA5); ++ drr_sta_status[14] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA6); ++ drr_sta_status[15] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA7); ++ } ++ ++ if (!is_mt7915(&dev->mt76)) ++ max_sta_line = 8; ++ ++ for (sta_line = 0; sta_line < max_sta_line; sta_line++) { ++ if (drr_sta_status[sta_line] > 0) { ++ for (sta_no = 0; sta_no < 32; sta_no++) { ++ if (((drr_sta_status[sta_line] & (0x1 << sta_no)) >> sta_no)) { ++ if (is_show) { ++ seq_printf(s, "\n UL AC%02d Queue Non-Empty STA:\n", idx); ++ is_show = false; ++ } ++ seq_printf(s, "%d ", sta_no + (sta_line * 32)); ++ } ++ } ++ } ++ } ++ } ++ ++ for (idx = DL_AC_START; idx <= DL_AC_END; idx++) { ++ drr_ctrl_def_val = 0x80420000; ++ drr_ctrl_val = (drr_ctrl_def_val | idx); ++ mt76_wr(dev, MT_DBG_PLE_DRR_TAB_CTRL, drr_ctrl_val); ++ drr_sta_status[0] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA0); ++ drr_sta_status[1] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA1); ++ drr_sta_status[2] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA2); ++ drr_sta_status[3] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA3); ++ drr_sta_status[4] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA4); ++ drr_sta_status[5] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA5); ++ drr_sta_status[6] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA6); ++ drr_sta_status[7] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA7); ++ ++ if (is_mt7915(&dev->mt76) && max_sta_line > 8) { ++ drr_ctrl_val = (drr_ctrl_def_val | idx | 1<<10); ++ mt76_wr(dev, MT_DBG_PLE_DRR_TAB_CTRL, drr_ctrl_val); ++ drr_sta_status[8] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA0); ++ drr_sta_status[9] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA1); ++ drr_sta_status[10] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA2); ++ drr_sta_status[11] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA3); ++ drr_sta_status[12] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA4); ++ drr_sta_status[13] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA5); ++ drr_sta_status[14] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA6); ++ drr_sta_status[15] = mt76_rr(dev, MT_DBG_PLE_DRR_TABLE_RDATA7); ++ } ++ ++ seq_printf(s, "\nBSSGrp[%d]:\n", idx); ++ if (!is_mt7915(&dev->mt76)) ++ max_sta_line = 8; ++ ++ for (sta_line = 0; sta_line < max_sta_line; sta_line++) { ++ seq_printf(s, "0x%08x ", drr_sta_status[sta_line]); ++ ++ if ((sta_line % 4) == 3) ++ seq_printf(s, "\n"); ++ } ++ } ++ ++ return 0; ++} ++ ++#define CR_NUM_OF_AC 17 ++ ++typedef enum _ENUM_UMAC_PORT_T { ++ ENUM_UMAC_HIF_PORT_0 = 0, ++ ENUM_UMAC_CPU_PORT_1 = 1, ++ ENUM_UMAC_LMAC_PORT_2 = 2, ++ ENUM_PLE_CTRL_PSE_PORT_3 = 3, ++ ENUM_UMAC_PSE_PLE_PORT_TOTAL_NUM = 4 ++} ENUM_UMAC_PORT_T, *P_ENUM_UMAC_PORT_T; ++ ++/* N9 MCU QUEUE LIST */ ++typedef enum _ENUM_UMAC_CPU_P_QUEUE_T { ++ ENUM_UMAC_CTX_Q_0 = 0, ++ ENUM_UMAC_CTX_Q_1 = 1, ++ ENUM_UMAC_CTX_Q_2 = 2, ++ ENUM_UMAC_CTX_Q_3 = 3, ++ ENUM_UMAC_CRX = 0, ++ ENUM_UMAC_CIF_QUEUE_TOTAL_NUM = 4 ++} ENUM_UMAC_CPU_P_QUEUE_T, *P_ENUM_UMAC_CPU_P_QUEUE_T; ++ ++/* LMAC PLE TX QUEUE LIST */ ++typedef enum _ENUM_UMAC_LMAC_PLE_TX_P_QUEUE_T { ++ ENUM_UMAC_LMAC_PLE_TX_Q_00 = 0x00, ++ ENUM_UMAC_LMAC_PLE_TX_Q_01 = 0x01, ++ ENUM_UMAC_LMAC_PLE_TX_Q_02 = 0x02, ++ ENUM_UMAC_LMAC_PLE_TX_Q_03 = 0x03, ++ ++ ENUM_UMAC_LMAC_PLE_TX_Q_10 = 0x04, ++ ENUM_UMAC_LMAC_PLE_TX_Q_11 = 0x05, ++ ENUM_UMAC_LMAC_PLE_TX_Q_12 = 0x06, ++ ENUM_UMAC_LMAC_PLE_TX_Q_13 = 0x07, ++ ++ ENUM_UMAC_LMAC_PLE_TX_Q_20 = 0x08, ++ ENUM_UMAC_LMAC_PLE_TX_Q_21 = 0x09, ++ ENUM_UMAC_LMAC_PLE_TX_Q_22 = 0x0a, ++ ENUM_UMAC_LMAC_PLE_TX_Q_23 = 0x0b, ++ ++ ENUM_UMAC_LMAC_PLE_TX_Q_30 = 0x0c, ++ ENUM_UMAC_LMAC_PLE_TX_Q_31 = 0x0d, ++ ENUM_UMAC_LMAC_PLE_TX_Q_32 = 0x0e, ++ ENUM_UMAC_LMAC_PLE_TX_Q_33 = 0x0f, ++ ++ ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0 = 0x10, ++ ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0 = 0x11, ++ ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0 = 0x12, ++ ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0 = 0x13, ++ ++ ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1 = 0x14, ++ ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1 = 0x15, ++ ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1 = 0x16, ++ ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1 = 0x17, ++ ENUM_UMAC_LMAC_PLE_TX_Q_NAF = 0x18, ++ ENUM_UMAC_LMAC_PLE_TX_Q_NBCN = 0x19, ++ ENUM_UMAC_LMAC_PLE_TX_Q_RELEASE = 0x1f, /* DE suggests not to use 0x1f, it's only for hw free queue */ ++ ENUM_UMAC_LMAC_QUEUE_TOTAL_NUM = 24, ++ ++} ENUM_UMAC_LMAC_TX_P_QUEUE_T, *P_ENUM_UMAC_LMAC_TX_P_QUEUE_T; ++ ++typedef struct _EMPTY_QUEUE_INFO_T { ++ char *QueueName; ++ u32 Portid; ++ u32 Queueid; ++} EMPTY_QUEUE_INFO_T, *P_EMPTY_QUEUE_INFO_T; ++ ++static EMPTY_QUEUE_INFO_T ple_queue_empty_info[] = { ++ {"CPU Q0", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_0}, ++ {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, ++ {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, ++ {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, ++ {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, /* 4~7 not defined */ ++ {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0}, /* Q16 */ ++ {"BMC Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_0}, ++ {"BCN Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_0}, ++ {"PSMP Q0", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0}, ++ {"ALTX Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1}, ++ {"BMC Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BMC_1}, ++ {"BCN Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_BNC_1}, ++ {"PSMP Q1", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1}, ++ {"NAF Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NAF}, ++ {"NBCN Q", ENUM_UMAC_LMAC_PORT_2, ENUM_UMAC_LMAC_PLE_TX_Q_NBCN}, ++ {NULL, 0, 0}, {NULL, 0, 0}, /* 18, 19 not defined */ ++ {"FIXFID Q", ENUM_UMAC_LMAC_PORT_2, 0x1a}, ++ {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, ++ {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, /* 21~29 not defined */ ++ {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, 0x7e}, ++ {"RLS2 Q", ENUM_PLE_CTRL_PSE_PORT_3, 0x7f} ++}; ++ ++static EMPTY_QUEUE_INFO_T ple_txcmd_queue_empty_info[] = { ++ {"AC00Q", ENUM_UMAC_LMAC_PORT_2, 0x40}, ++ {"AC01Q", ENUM_UMAC_LMAC_PORT_2, 0x41}, ++ {"AC02Q", ENUM_UMAC_LMAC_PORT_2, 0x42}, ++ {"AC03Q", ENUM_UMAC_LMAC_PORT_2, 0x43}, ++ {"AC10Q", ENUM_UMAC_LMAC_PORT_2, 0x44}, ++ {"AC11Q", ENUM_UMAC_LMAC_PORT_2, 0x45}, ++ {"AC12Q", ENUM_UMAC_LMAC_PORT_2, 0x46}, ++ {"AC13Q", ENUM_UMAC_LMAC_PORT_2, 0x47}, ++ {"AC20Q", ENUM_UMAC_LMAC_PORT_2, 0x48}, ++ {"AC21Q", ENUM_UMAC_LMAC_PORT_2, 0x49}, ++ {"AC22Q", ENUM_UMAC_LMAC_PORT_2, 0x4a}, ++ {"AC23Q", ENUM_UMAC_LMAC_PORT_2, 0x4b}, ++ {"AC30Q", ENUM_UMAC_LMAC_PORT_2, 0x4c}, ++ {"AC31Q", ENUM_UMAC_LMAC_PORT_2, 0x4d}, ++ {"AC32Q", ENUM_UMAC_LMAC_PORT_2, 0x4e}, ++ {"AC33Q", ENUM_UMAC_LMAC_PORT_2, 0x4f}, ++ {"ALTX Q0", ENUM_UMAC_LMAC_PORT_2, 0x50}, ++ {"TF Q0", ENUM_UMAC_LMAC_PORT_2, 0x51}, ++ {"TWT TSF-TF Q0", ENUM_UMAC_LMAC_PORT_2, 0x52}, ++ {"TWT DL Q0", ENUM_UMAC_LMAC_PORT_2, 0x53}, ++ {"TWT UL Q0", ENUM_UMAC_LMAC_PORT_2, 0x54}, ++ {"ALTX Q1", ENUM_UMAC_LMAC_PORT_2, 0x55}, ++ {"TF Q1", ENUM_UMAC_LMAC_PORT_2, 0x56}, ++ {"TWT TSF-TF Q1", ENUM_UMAC_LMAC_PORT_2, 0x57}, ++ {"TWT DL Q1", ENUM_UMAC_LMAC_PORT_2, 0x58}, ++ {"TWT UL Q1", ENUM_UMAC_LMAC_PORT_2, 0x59}, ++ {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, ++}; ++ ++static char* sta_ctrl_reg[] = {"ENABLE", "DISABLE", "PAUSE"}; ++static u32 chip_show_sta_acq_info(struct seq_file *s, struct mt7915_dev *dev, u32 *ple_stat, ++ u32 *sta_pause, u32 *dis_sta_map, ++ u32 dumptxd) ++{ ++ int i, j; ++ u32 total_nonempty_cnt = 0; ++ u32 ac_num = 9, all_ac_num; ++ ++ /* TDO: ac_num = 16 for mt7986 */ ++ if (!is_mt7915(&dev->mt76)) ++ ac_num = 17; ++ ++ all_ac_num = ac_num * 4; ++ ++ for (j = 0; j < all_ac_num; j++) { /* show AC Q info */ ++ for (i = 0; i < 32; i++) { ++ if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) { ++ u32 hfid, tfid, pktcnt, ac_n = j / ac_num, ctrl = 0; ++ u32 sta_num = i + (j % ac_num) * 32, fl_que_ctrl[3] = {0}; ++ //struct wifi_dev *wdev = wdev_search_by_wcid(pAd, sta_num); ++ u32 wmmidx = 0; ++ struct mt7915_sta *msta; ++ struct mt76_wcid *wcid; ++ ++ wcid = rcu_dereference(dev->mt76.wcid[sta_num]); ++ if (!wcid) { ++ printk("ERROR!! no found STA wcid=%d\n", sta_num); ++ continue; ++ } ++ msta = container_of(wcid, struct mt7915_sta, wcid); ++ wmmidx = msta->vif->mt76.wmm_idx; ++ ++ seq_printf(s, "\tSTA%d AC%d: ", sta_num, ac_n); ++ ++ fl_que_ctrl[0] |= MT_DBG_PLE_FL_QUE_CTRL0_EXECUTE_MASK; ++ fl_que_ctrl[0] |= (ENUM_UMAC_LMAC_PORT_2 << MT_PLE_FL_QUE_CTRL0_Q_BUF_PID_SHFT); ++ fl_que_ctrl[0] |= (ac_n << MT_PLE_FL_QUE_CTRL0_Q_BUF_QID_SHFT); ++ fl_que_ctrl[0] |= sta_num; ++ mt76_wr(dev, MT_DBG_PLE_FL_QUE_CTRL0, fl_que_ctrl[0]); ++ fl_que_ctrl[1] = mt76_rr(dev, MT_DBG_PLE_FL_QUE_CTRL2); ++ fl_que_ctrl[2] = mt76_rr(dev, MT_DBG_PLE_FL_QUE_CTRL3); ++ hfid = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL2_Q_HEAD_FID_MASK, fl_que_ctrl[1]); ++ tfid = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL2_Q_TAIL_FID_MASK, fl_que_ctrl[1]); ++ pktcnt = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL3_Q_PKT_NUM_MASK, fl_que_ctrl[2]); ++ seq_printf(s, "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x", ++ tfid, hfid, pktcnt); ++ ++ if (((sta_pause[j % ac_num] & 0x1 << i) >> i) == 1) ++ ctrl = 2; ++ ++ if (((dis_sta_map[j % ac_num] & 0x1 << i) >> i) == 1) ++ ctrl = 1; ++ ++ seq_printf(s, " ctrl = %s", sta_ctrl_reg[ctrl]); ++ seq_printf(s, " (wmmidx=%d)\n", wmmidx); ++ ++ total_nonempty_cnt++; ++ ++ // TODO ++ //if (pktcnt > 0 && dumptxd > 0) ++ // ShowTXDInfo(pAd, hfid); ++ } ++ } ++ } ++ ++ return total_nonempty_cnt; ++} ++ ++static void chip_show_txcmdq_info(struct seq_file *s, struct mt7915_dev *dev, u32 ple_txcmd_stat) ++{ ++ int i; ++ ++ seq_printf(s, "Nonempty TXCMD Q info:\n"); ++ for (i = 0; i < 32; i++) { ++ if (((ple_txcmd_stat & (0x1 << i)) >> i) == 0) { ++ u32 hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; ++ ++ if (ple_txcmd_queue_empty_info[i].QueueName != NULL) { ++ seq_printf(s, "\t%s: ", ple_txcmd_queue_empty_info[i].QueueName); ++ fl_que_ctrl[0] |= MT_DBG_PLE_FL_QUE_CTRL0_EXECUTE_MASK; ++ fl_que_ctrl[0] |= (ple_txcmd_queue_empty_info[i].Portid << ++ MT_PLE_FL_QUE_CTRL0_Q_BUF_PID_SHFT); ++ fl_que_ctrl[0] |= (ple_txcmd_queue_empty_info[i].Queueid << ++ MT_PLE_FL_QUE_CTRL0_Q_BUF_QID_SHFT); ++ } else ++ continue; ++ ++ mt76_wr(dev, MT_DBG_PLE_FL_QUE_CTRL0, fl_que_ctrl[0]); ++ fl_que_ctrl[1] = mt76_rr(dev, MT_DBG_PLE_FL_QUE_CTRL2); ++ fl_que_ctrl[2] = mt76_rr(dev, MT_DBG_PLE_FL_QUE_CTRL3); ++ hfid = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL2_Q_HEAD_FID_MASK, fl_que_ctrl[1]); ++ tfid = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL2_Q_TAIL_FID_MASK, fl_que_ctrl[1]); ++ pktcnt = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL3_Q_PKT_NUM_MASK, fl_que_ctrl[2]); ++ seq_printf(s, "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", ++ tfid, hfid, pktcnt); ++ } ++ } ++} ++ ++static void chip_get_ple_acq_stat(struct mt7915_dev *dev, u32 *ple_stat) ++{ ++ int i; ++ int cr_num = 9, all_cr_num; ++ u32 ac , index; ++ ++ /* TDO: cr_num = 16 for mt7986 */ ++ if(!is_mt7915(&dev->mt76)) ++ cr_num = 17; ++ ++ all_cr_num = cr_num * 4; ++ ++ ple_stat[0] = mt76_rr(dev, MT_DBG_PLE_QUEUE_EMPTY); ++ ++ for(i = 0; i < all_cr_num; i++) { ++ ac = i / cr_num; ++ index = i % cr_num; ++ ple_stat[i + 1] = ++ mt76_rr(dev, MT_DBG_PLE_AC_QEMPTY(ac, index)); ++ ++ } ++} ++ ++static void chip_get_dis_sta_map(struct mt7915_dev *dev, u32 *dis_sta_map) ++{ ++ int i; ++ u32 ac_num = 9; ++ ++ /* TDO: ac_num = 16 for mt7986 */ ++ if (!is_mt7915(&dev->mt76)) ++ ac_num = 17; ++ ++ for(i = 0; i < ac_num; i++) { ++ dis_sta_map[i] = mt76_rr(dev, MT_DBG_PLE_DIS_STA_MAP(i)); ++ } ++} ++ ++static void chip_get_sta_pause(struct mt7915_dev *dev, u32 *sta_pause) ++{ ++ int i; ++ u32 ac_num = 9; ++ ++ /* TDO: ac_num = 16 for mt7986 */ ++ if (!is_mt7915(&dev->mt76)) ++ ac_num = 17; ++ ++ for(i = 0; i < ac_num; i++) { ++ sta_pause[i] = mt76_rr(dev, MT_DBG_PLE_STATION_PAUSE(i)); ++ } ++} ++ ++static int mt7915_pleinfo_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 ple_buf_ctrl, pg_sz, pg_num; ++ u32 ple_stat[70] = {0}, pg_flow_ctrl[8] = {0}; ++ u32 ple_native_txcmd_stat; ++ u32 ple_txcmd_stat; ++ u32 sta_pause[CR_NUM_OF_AC] = {0}, dis_sta_map[CR_NUM_OF_AC] = {0}; ++ u32 fpg_cnt, ffa_cnt, fpg_head, fpg_tail, hif_max_q, hif_min_q; ++ u32 rpg_hif, upg_hif, cpu_max_q, cpu_min_q, rpg_cpu, upg_cpu; ++ int i, j; ++ u32 ac_num = 9, all_ac_num; ++ ++ /* TDO: ac_num = 16 for mt7986 */ ++ if (!is_mt7915(&dev->mt76)) ++ ac_num = 17; ++ ++ all_ac_num = ac_num * 4; ++ ++ ple_buf_ctrl = mt76_rr(dev, MT_DBG_PLE_PBUF_CTRL_ADDR); ++ chip_get_ple_acq_stat(dev, ple_stat); ++ ple_txcmd_stat = mt76_rr(dev, MT_DBG_PLE_TXCMD_Q_EMPTY); ++ ple_native_txcmd_stat = mt76_rr(dev, MT_DBG_PLE_NATIVE_TXCMD_Q_EMPTY); ++ pg_flow_ctrl[0] = mt76_rr(dev, MT_DBG_PLE_FREEPG_CNT); ++ pg_flow_ctrl[1] = mt76_rr(dev, MT_DBG_PLE_FREEPG_HEAD_TAIL); ++ pg_flow_ctrl[2] = mt76_rr(dev, MT_DBG_PLE_PG_HIF_GROUP); ++ pg_flow_ctrl[3] = mt76_rr(dev, MT_DBG_PLE_HIF_PG_INFO); ++ pg_flow_ctrl[4] = mt76_rr(dev, MT_DBG_PLE_PG_CPU_GROUP); ++ pg_flow_ctrl[5] = mt76_rr(dev, MT_DBG_PLE_CPU_PG_INFO); ++ pg_flow_ctrl[6] = mt76_rr(dev, MT_DBG_PLE_PG_HIF_TXCMD_GROUP); ++ pg_flow_ctrl[7] = mt76_rr(dev, MT_DBG_PLE_HIF_TXCMD_PG_INFO); ++ chip_get_dis_sta_map(dev, dis_sta_map); ++ chip_get_sta_pause(dev, sta_pause); ++ ++ seq_printf(s, "PLE Configuration Info:\n"); ++ seq_printf(s, "\tPacket Buffer Control(0x%x): 0x%08x\n", ++ MT_DBG_PLE_PBUF_CTRL_ADDR, ple_buf_ctrl); ++ ++ pg_sz = FIELD_GET(MT_DBG_PLE_PBUF_CTRL_PAGE_SIZE_MASK, ple_buf_ctrl); ++ seq_printf(s, "\t\tPage Size=%d(%d bytes per page)\n", ++ pg_sz, (pg_sz == 1 ? 128 : 64)); ++ seq_printf(s, "\t\tPage Offset=%ld(in unit of 2KB)\n", ++ FIELD_GET(MT_DBG_PLE_PBUF_CTRL_OFFSET_MASK, ple_buf_ctrl)); ++ ++ pg_num = FIELD_GET(MT_DBG_PLE_PBUF_CTRL_TOTAL_PAGE_NUM_MASK, ple_buf_ctrl); ++ seq_printf(s, "\t\tTotal Page=%d pages\n", pg_num); ++ ++ /* Page Flow Control */ ++ seq_printf(s, "PLE Page Flow Control:\n"); ++ seq_printf(s, "\tFree page counter(0x%x): 0x%08x\n", ++ MT_DBG_PLE_FREEPG_CNT, pg_flow_ctrl[0]); ++ fpg_cnt = FIELD_GET(MT_DBG_PLE_FREEPG_CNT_FREEPG_CNT_MASK, pg_flow_ctrl[0]); ++ ++ seq_printf(s, "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); ++ ffa_cnt = FIELD_GET(MT_DBG_PLE_FREEPG_CNT_FFA_CNT_MASK, pg_flow_ctrl[0]); ++ ++ seq_printf(s, "\t\tThe free page numbers of free for all=0x%03x\n", ffa_cnt); ++ seq_printf(s, "\tFree page head and tail(0x%x): 0x%08x\n", ++ MT_DBG_PLE_FREEPG_HEAD_TAIL, pg_flow_ctrl[1]); ++ ++ fpg_head = FIELD_GET(MT_DBG_PLE_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK, pg_flow_ctrl[1]); ++ fpg_tail = FIELD_GET(MT_DBG_PLE_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK, pg_flow_ctrl[1]); ++ seq_printf(s, "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", fpg_tail, fpg_head); ++ seq_printf(s, "\tReserved page counter of HIF group(0x%x): 0x%08x\n", ++ MT_DBG_PLE_PG_HIF_GROUP, pg_flow_ctrl[2]); ++ seq_printf(s, "\tHIF group page status(0x%x): 0x%08x\n", ++ MT_DBG_PLE_HIF_PG_INFO, pg_flow_ctrl[3]); ++ ++ hif_min_q = FIELD_GET(MT_DBG_PLE_PG_HIF_GROUP_HIF_MIN_QUOTA_MASK, pg_flow_ctrl[2]); ++ hif_max_q = FIELD_GET(MT_DBG_PLE_PG_HIF_GROUP_HIF_MAX_QUOTA_MASK, pg_flow_ctrl[2]); ++ seq_printf(s, "\t\tThe max/min quota pages of HIF group=0x%03x/0x%03x\n", hif_max_q, hif_min_q); ++ ++ rpg_hif = FIELD_GET(MT_DBG_PLE_HIF_PG_INFO_HIF_RSV_CNT_MASK, pg_flow_ctrl[3]); ++ upg_hif = FIELD_GET(MT_DBG_PLE_HIF_PG_INFO_HIF_SRC_CNT_MASK, pg_flow_ctrl[3]); ++ seq_printf(s, "\t\tThe used/reserved pages of HIF group=0x%03x/0x%03x\n", upg_hif, rpg_hif); ++ ++ seq_printf(s, "\tReserved page counter of HIF_TXCMD group(0x%x): 0x%08x\n", ++ MT_DBG_PLE_PG_HIF_TXCMD_GROUP, pg_flow_ctrl[6]); ++ seq_printf(s, "\tHIF_TXCMD group page status(0x%x): 0x%08x\n", ++ MT_DBG_PLE_HIF_TXCMD_PG_INFO, pg_flow_ctrl[7]); ++ cpu_min_q = FIELD_GET(MT_DBG_PLE_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK, pg_flow_ctrl[6]); ++ cpu_max_q = FIELD_GET(MT_DBG_PLE_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK, pg_flow_ctrl[6]); ++ seq_printf(s, "\t\tThe max/min quota pages of HIF_TXCMD group=0x%03x/0x%03x\n", cpu_max_q, cpu_min_q); ++ ++ rpg_cpu = FIELD_GET(MT_DBG_PLE_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK, pg_flow_ctrl[7]); ++ upg_cpu = FIELD_GET(MT_DBG_PLE_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK, pg_flow_ctrl[7]); ++ seq_printf(s, "\t\tThe used/reserved pages of HIF_TXCMD group=0x%03x/0x%03x\n", upg_cpu, rpg_cpu); ++ ++ seq_printf(s, "\tReserved page counter of CPU group(0x%x): 0x%08x\n", ++ MT_DBG_PLE_PG_CPU_GROUP, pg_flow_ctrl[4]); ++ seq_printf(s, "\tCPU group page status(0x%x): 0x%08x\n", ++ MT_DBG_PLE_CPU_PG_INFO, pg_flow_ctrl[5]); ++ cpu_min_q = FIELD_GET(MT_DBG_PLE_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK, pg_flow_ctrl[4]); ++ cpu_max_q = FIELD_GET(MT_DBG_PLE_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK, pg_flow_ctrl[4]); ++ seq_printf(s, "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", cpu_max_q, cpu_min_q); ++ ++ rpg_cpu = FIELD_GET(MT_DBG_PLE_CPU_PG_INFO_CPU_RSV_CNT_MASK, pg_flow_ctrl[5]); ++ upg_cpu = FIELD_GET(MT_DBG_PLE_CPU_PG_INFO_CPU_SRC_CNT_MASK, pg_flow_ctrl[5]); ++ seq_printf(s, "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", upg_cpu, rpg_cpu); ++ ++ if ((ple_stat[0] & MT_DBG_PLE_Q_EMPTY_ALL_AC_EMPTY_MASK) == 0) { ++ for (j = 0; j < all_ac_num; j++) { ++ if (j % ac_num == 0) { ++ seq_printf(s, "\n\tNonempty AC%d Q of STA#: ", j / ac_num); ++ } ++ ++ for (i = 0; i < 32; i++) { ++ if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) { ++ seq_printf(s, "%d ", i + (j % ac_num) * 32); ++ } ++ } ++ } ++ ++ seq_printf(s, "\n"); ++ } ++ ++ seq_printf(s, "non-native/native txcmd queue empty = %d/%d\n", ple_txcmd_stat, ple_native_txcmd_stat); ++ ++ seq_printf(s, "Nonempty Q info:\n"); ++ ++ for (i = 0; i < 32; i++) { ++ if (((ple_stat[0] & (0x1 << i)) >> i) == 0) { ++ u32 hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; ++ ++ if (ple_queue_empty_info[i].QueueName != NULL) { ++ seq_printf(s, "\t%s: ", ple_queue_empty_info[i].QueueName); ++ fl_que_ctrl[0] |= MT_DBG_PLE_FL_QUE_CTRL0_EXECUTE_MASK; ++ fl_que_ctrl[0] |= (ple_queue_empty_info[i].Portid << MT_PLE_FL_QUE_CTRL0_Q_BUF_PID_SHFT); ++ fl_que_ctrl[0] |= (ple_queue_empty_info[i].Queueid << MT_PLE_FL_QUE_CTRL0_Q_BUF_QID_SHFT); ++ } else ++ continue; ++ ++ if (ple_queue_empty_info[i].Queueid >= ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_0 && ++ ple_queue_empty_info[i].Queueid <= ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_0) ++ /* band0 set TGID 0, bit31 = 0 */ ++ mt76_wr(dev, MT_DBG_PLE_FL_QUE_CTRL1, 0x0); ++ else if (ple_queue_empty_info[i].Queueid >= ENUM_UMAC_LMAC_PLE_TX_Q_ALTX_1 && ++ ple_queue_empty_info[i].Queueid <= ENUM_UMAC_LMAC_PLE_TX_Q_PSMP_1) ++ /* band1 set TGID 1, bit31 = 1 */ ++ mt76_wr(dev, MT_DBG_PLE_FL_QUE_CTRL1, 0x80000000); ++ ++ mt76_wr(dev, MT_DBG_PLE_FL_QUE_CTRL0, fl_que_ctrl[0]); ++ fl_que_ctrl[1] = mt76_rr(dev, MT_DBG_PLE_FL_QUE_CTRL2); ++ fl_que_ctrl[2] = mt76_rr(dev, MT_DBG_PLE_FL_QUE_CTRL3); ++ hfid = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL2_Q_HEAD_FID_MASK, fl_que_ctrl[1]); ++ tfid = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL2_Q_TAIL_FID_MASK, fl_que_ctrl[1]); ++ pktcnt = FIELD_GET(MT_DBG_PLE_FL_QUE_CTRL3_Q_PKT_NUM_MASK, fl_que_ctrl[2]); ++ seq_printf(s, "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", ++ tfid, hfid, pktcnt); ++ ++ /* TODO */ ++ //if (pktcnt > 0 && dumptxd > 0) ++ // ShowTXDInfo(pAd, hfid); ++ } ++ } ++ ++ chip_show_sta_acq_info(s, dev, ple_stat, sta_pause, dis_sta_map, 0/*dumptxd*/); ++ chip_show_txcmdq_info(s, dev, ple_native_txcmd_stat); ++ ++ return 0; ++} ++ ++typedef enum _ENUM_UMAC_PLE_CTRL_P3_QUEUE_T { ++ ENUM_UMAC_PLE_CTRL_P3_Q_0X1E = 0x1e, ++ ENUM_UMAC_PLE_CTRL_P3_Q_0X1F = 0x1f, ++ ENUM_UMAC_PLE_CTRL_P3_TOTAL_NUM = 2 ++} ENUM_UMAC_PLE_CTRL_P3_QUEUE_T, *P_ENUM_UMAC_PLE_CTRL_P3_QUEUE_T; ++ ++static EMPTY_QUEUE_INFO_T pse_queue_empty_info[] = { ++ {"CPU Q0", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_0}, ++ {"CPU Q1", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_1}, ++ {"CPU Q2", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_2}, ++ {"CPU Q3", ENUM_UMAC_CPU_PORT_1, ENUM_UMAC_CTX_Q_3}, ++ {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, /* 4~7 not defined */ ++ {"HIF Q0", ENUM_UMAC_HIF_PORT_0, 0}, /* Q8 */ ++ {"HIF Q1", ENUM_UMAC_HIF_PORT_0, 1}, ++ {"HIF Q2", ENUM_UMAC_HIF_PORT_0, 2}, ++ {"HIF Q3", ENUM_UMAC_HIF_PORT_0, 3}, ++ {"HIF Q4", ENUM_UMAC_HIF_PORT_0, 4}, ++ {"HIF Q5", ENUM_UMAC_HIF_PORT_0, 5}, ++ {NULL, 0, 0}, {NULL, 0, 0}, /* 14~15 not defined */ ++ {"LMAC Q", ENUM_UMAC_LMAC_PORT_2, 0}, ++ {"MDP TX Q", ENUM_UMAC_LMAC_PORT_2, 1}, ++ {"MDP RX Q", ENUM_UMAC_LMAC_PORT_2, 2}, ++ {"SEC TX Q", ENUM_UMAC_LMAC_PORT_2, 3}, ++ {"SEC RX Q", ENUM_UMAC_LMAC_PORT_2, 4}, ++ {"SFD_PARK Q", ENUM_UMAC_LMAC_PORT_2, 5}, ++ {"MDP_TXIOC Q", ENUM_UMAC_LMAC_PORT_2, 6}, ++ {"MDP_RXIOC Q", ENUM_UMAC_LMAC_PORT_2, 7}, ++ {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, {NULL, 0, 0}, /* 24~30 not defined */ ++ {"RLS Q", ENUM_PLE_CTRL_PSE_PORT_3, ENUM_UMAC_PLE_CTRL_P3_Q_0X1F} ++}; ++ ++static int mt7915_pseinfo_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 pse_buf_ctrl, pg_sz, pg_num; ++ u32 pse_stat, pg_flow_ctrl[22] = {0}; ++ u32 fpg_cnt, ffa_cnt, fpg_head, fpg_tail; ++ u32 max_q, min_q, rsv_pg, used_pg; ++ int i; ++ ++ pse_buf_ctrl = mt76_rr(dev, MT_DBG_PSE_PBUF_CTRL); ++ pse_stat = mt76_rr(dev, MT_DBG_PSE_QUEUE_EMPTY); ++ pg_flow_ctrl[0] = mt76_rr(dev, MT_DBG_PSE_FREEPG_CNT); ++ pg_flow_ctrl[1] = mt76_rr(dev, MT_DBG_PSE_FREEPG_HEAD_TAIL); ++ pg_flow_ctrl[2] = mt76_rr(dev, MT_DBG_PSE_PG_HIF0_GROUP); ++ pg_flow_ctrl[3] = mt76_rr(dev, MT_DBG_PSE_HIF0_PG_INFO); ++ pg_flow_ctrl[4] = mt76_rr(dev, MT_DBG_PSE_PG_HIF1_GROUP); ++ pg_flow_ctrl[5] = mt76_rr(dev, MT_DBG_PSE_HIF1_PG_INFO); ++ pg_flow_ctrl[6] = mt76_rr(dev, MT_DBG_PSE_PG_CPU_GROUP); ++ pg_flow_ctrl[7] = mt76_rr(dev, MT_DBG_PSE_CPU_PG_INFO); ++ pg_flow_ctrl[8] = mt76_rr(dev, MT_DBG_PSE_PG_LMAC0_GROUP); ++ pg_flow_ctrl[9] = mt76_rr(dev, MT_DBG_PSE_LMAC0_PG_INFO); ++ pg_flow_ctrl[10] = mt76_rr(dev, MT_DBG_PSE_PG_LMAC1_GROUP); ++ pg_flow_ctrl[11] = mt76_rr(dev, MT_DBG_PSE_LMAC1_PG_INFO); ++ pg_flow_ctrl[12] = mt76_rr(dev, MT_DBG_PSE_PG_LMAC2_GROUP); ++ pg_flow_ctrl[13] = mt76_rr(dev, MT_DBG_PSE_LMAC2_PG_INFO); ++ pg_flow_ctrl[14] = mt76_rr(dev, MT_DBG_PSE_PG_PLE_GROUP); ++ pg_flow_ctrl[15] = mt76_rr(dev, MT_DBG_PSE_PLE_PG_INFO); ++ pg_flow_ctrl[16] = mt76_rr(dev, MT_DBG_PSE_PG_LMAC3_GROUP); ++ pg_flow_ctrl[17] = mt76_rr(dev, MT_DBG_PSE_LMAC3_PG_INFO); ++ pg_flow_ctrl[18] = mt76_rr(dev, MT_DBG_PSE_PG_MDP_GROUP); ++ pg_flow_ctrl[19] = mt76_rr(dev, MT_DBG_PSE_MDP_PG_INFO); ++ pg_flow_ctrl[20] = mt76_rr(dev, MT_DBG_PSE_PG_PLE1_GROUP); ++ pg_flow_ctrl[21] = mt76_rr(dev,MT_DBG_PSE_PLE1_PG_INFO); ++ ++ /* Configuration Info */ ++ seq_printf(s, "PSE Configuration Info:\n"); ++ seq_printf(s, "\tPacket Buffer Control(0x82068014): 0x%08x\n", pse_buf_ctrl); ++ pg_sz = FIELD_GET(MT_DBG_PSE_PBUF_CTRL_PAGE_SIZE_CFG_MASK, pse_buf_ctrl); ++ ++ seq_printf(s, "\t\tPage Size=%d(%d bytes per page)\n", pg_sz, (pg_sz == 1 ? 256 : 128)); ++ seq_printf(s, "\t\tPage Offset=%ld(in unit of 64KB)\n", ++ FIELD_GET(MT_DBG_PSE_PBUF_CTRL_PBUF_OFFSET_MASK, pse_buf_ctrl)); ++ pg_num = FIELD_GET(MT_DBG_PSE_PBUF_CTRL_TOTAL_PAGE_NUM_MASK, pse_buf_ctrl); ++ ++ seq_printf(s, "\t\tTotal page numbers=%d pages\n", pg_num); ++ ++ /* Page Flow Control */ ++ seq_printf(s, "PSE Page Flow Control:\n"); ++ seq_printf(s, "\tFree page counter(0x82068100): 0x%08x\n", pg_flow_ctrl[0]); ++ fpg_cnt = FIELD_GET(MT_DBG_PSE_FREEPG_CNT_FREEPG_CNT_MASK, pg_flow_ctrl[0]); ++ seq_printf(s, "\t\tThe toal page number of free=0x%03x\n", fpg_cnt); ++ ++ ffa_cnt = FIELD_GET(MT_DBG_PSE_FREEPG_CNT_FFA_CNT_MASK, pg_flow_ctrl[0]); ++ seq_printf(s, "\t\tThe free page numbers of free for all=0x%03x\n", ffa_cnt); ++ ++ seq_printf(s, "\tFree page head and tail(0x82068104): 0x%08x\n", pg_flow_ctrl[1]); ++ fpg_head = FIELD_GET(MT_DBG_PSE_FREEPG_HEAD_TAIL_FREEPG_HEAD_MASK, pg_flow_ctrl[1]); ++ ++ fpg_tail = FIELD_GET(MT_DBG_PSE_FREEPG_HEAD_TAIL_FREEPG_TAIL_MASK, pg_flow_ctrl[1]); ++ seq_printf(s, "\t\tThe tail/head page of free page list=0x%03x/0x%03x\n", fpg_tail, fpg_head); ++ seq_printf(s, "\tReserved page counter of HIF0 group(0x82068110): 0x%08x\n", pg_flow_ctrl[2]); ++ seq_printf(s, "\tHIF0 group page status(0x82068114): 0x%08x\n", pg_flow_ctrl[3]); ++ min_q = FIELD_GET(MT_DBG_PSE_PG_HIF0_GROUP_HIF0_MIN_QUOTA_MASK, pg_flow_ctrl[2]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_HIF0_GROUP_HIF0_MAX_QUOTA_MASK, pg_flow_ctrl[2]); ++ seq_printf(s, "\t\tThe max/min quota pages of HIF0 group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_HIF0_PG_INFO_HIF0_RSV_CNT_MASK, pg_flow_ctrl[3]);; ++ used_pg = FIELD_GET(MT_DBG_PSE_HIF0_PG_INFO_HIF0_SRC_CNT_MASK, pg_flow_ctrl[3]); ++ seq_printf(s, "\t\tThe used/reserved pages of HIF0 group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ seq_printf(s, "\tReserved page counter of HIF1 group(0x82068118): 0x%08x\n", pg_flow_ctrl[4]); ++ seq_printf(s, "\tHIF1 group page status(0x8206811c): 0x%08x\n", pg_flow_ctrl[5]); ++ min_q = FIELD_GET(MT_DBG_PSE_PG_HIF1_GROUP_HIF1_MIN_QUOTA_MASK, pg_flow_ctrl[4]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_HIF1_GROUP_HIF1_MAX_QUOTA_MASK, pg_flow_ctrl[4]); ++ seq_printf(s, "\t\tThe max/min quota pages of HIF1 group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_HIF1_PG_INFO_HIF1_RSV_CNT_MASK, pg_flow_ctrl[5]); ++ used_pg = FIELD_GET(MT_DBG_PSE_HIF1_PG_INFO_HIF1_SRC_CNT_MASK, pg_flow_ctrl[5]); ++ ++ seq_printf(s, "\t\tThe used/reserved pages of HIF1 group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ seq_printf(s, "\tReserved page counter of CPU group(0x82068150): 0x%08x\n", pg_flow_ctrl[6]); ++ seq_printf(s, "\tCPU group page status(0x82068154): 0x%08x\n", pg_flow_ctrl[7]); ++ min_q = FIELD_GET(MT_DBG_PSE_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK, pg_flow_ctrl[6]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK, pg_flow_ctrl[6]); ++ seq_printf(s, "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_CPU_PG_INFO_CPU_RSV_CNT_MASK, pg_flow_ctrl[7]); ++ used_pg = FIELD_GET(MT_DBG_PSE_CPU_PG_INFO_CPU_SRC_CNT_MASK, pg_flow_ctrl[7]); ++ seq_printf(s, "\t\tThe used/reserved pages of CPU group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ seq_printf(s, "\tReserved page counter of LMAC0 group(0x82068170): 0x%08x\n", pg_flow_ctrl[8]); ++ seq_printf(s, "\tLMAC0 group page status(0x82068174): 0x%08x\n", pg_flow_ctrl[9]); ++ min_q = FIELD_GET(MT_DBG_PSE_PG_LMAC0_GROUP_LMAC0_MIN_QUOTA_MASK, pg_flow_ctrl[8]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_LMAC0_GROUP_LMAC0_MAX_QUOTA_MASK, pg_flow_ctrl[8]); ++ seq_printf(s, "\t\tThe max/min quota pages of LMAC0 group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_LMAC0_PG_INFO_LMAC0_RSV_CNT_MASK, pg_flow_ctrl[9]); ++ used_pg = FIELD_GET(MT_DBG_PSE_LMAC0_PG_INFO_LMAC0_SRC_CNT_MASK, pg_flow_ctrl[9]); ++ seq_printf(s, "\t\tThe used/reserved pages of LMAC0 group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ seq_printf(s, "\tReserved page counter of LMAC1 group(0x82068178): 0x%08x\n", pg_flow_ctrl[10]); ++ seq_printf(s, "\tLMAC1 group page status(0x8206817c): 0x%08x\n", pg_flow_ctrl[11]); ++ min_q = FIELD_GET(MT_DBG_TOP_PG_LMAC1_GROUP_LMAC1_MIN_QUOTA_MASK, pg_flow_ctrl[10]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_LMAC1_GROUP_LMAC1_MAX_QUOTA_MASK, pg_flow_ctrl[10]); ++ seq_printf(s, "\t\tThe max/min quota pages of LMAC1 group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_LMAC1_PG_INFO_LMAC1_RSV_CNT_MASK, pg_flow_ctrl[11]); ++ used_pg = FIELD_GET(MT_DBG_PSE_LMAC1_PG_INFO_LMAC1_SRC_CNT_MASK, pg_flow_ctrl[11]); ++ seq_printf(s, "\t\tThe used/reserved pages of LMAC1 group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ seq_printf(s, "\tReserved page counter of LMAC2 group(0x82068180): 0x%08x\n", pg_flow_ctrl[11]); ++ seq_printf(s, "\tLMAC2 group page status(0x82068184): 0x%08x\n", pg_flow_ctrl[12]); ++ min_q = FIELD_GET(MT_DBG_PSE_PG_LMAC2_GROUP_LMAC2_MIN_QUOTA_MASK, pg_flow_ctrl[12]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_LMAC2_GROUP_LMAC2_MAX_QUOTA_MASK, pg_flow_ctrl[12]); ++ seq_printf(s, "\t\tThe max/min quota pages of LMAC2 group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_LMAC2_PG_INFO_LMAC2_RSV_CNT_MASK, pg_flow_ctrl[13]); ++ used_pg = FIELD_GET(MT_DBG_PSE_LMAC2_PG_INFO_LMAC2_SRC_CNT_MASK, pg_flow_ctrl[13]); ++ seq_printf(s, "\t\tThe used/reserved pages of LMAC2 group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ ++ seq_printf(s, "\tReserved page counter of LMAC3 group(0x82068188): 0x%08x\n", pg_flow_ctrl[16]); ++ seq_printf(s, "\tLMAC3 group page status(0x8206818c): 0x%08x\n", pg_flow_ctrl[17]); ++ min_q = FIELD_GET(MT_DBG_TOP_PG_LMAC3_GROUP_LMAC3_MIN_QUOTA_MASK, pg_flow_ctrl[16]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_LMAC3_GROUP_LMAC3_MAX_QUOTA_MASK, pg_flow_ctrl[16]); ++ seq_printf(s, "\t\tThe max/min quota pages of LMAC3 group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_LMAC3_PG_INFO_LMAC3_RSV_CNT_MASK, pg_flow_ctrl[17]); ++ used_pg = FIELD_GET(MT_DBG_PSE_LMAC3_PG_INFO_LMAC3_SRC_CNT_MASK, pg_flow_ctrl[17]); ++ seq_printf(s, "\t\tThe used/reserved pages of LMAC3 group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ ++ seq_printf(s, "\tReserved page counter of PLE group(0x82068160): 0x%08x\n", pg_flow_ctrl[14]); ++ seq_printf(s, "\tPLE group page status(0x82068164): 0x%08x\n", pg_flow_ctrl[15]); ++ min_q = FIELD_GET(MT_DBG_PSE_PG_PLE_GROUP_PLE_MIN_QUOTA_MASK, pg_flow_ctrl[14]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_PLE_GROUP_PLE_MAX_QUOTA_MASK, pg_flow_ctrl[14]); ++ seq_printf(s, "\t\tThe max/min quota pages of PLE group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_PLE_PG_INFO_PLE_RSV_CNT_MASK, pg_flow_ctrl[15]); ++ used_pg = FIELD_GET(MT_DBG_PSE_PLE_PG_INFO_PLE_SRC_CNT_MASK, pg_flow_ctrl[15]); ++ seq_printf(s, "\t\tThe used/reserved pages of PLE group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ ++ seq_printf(s, "\tReserved page counter of PLE1 group(0x82068168): 0x%08x\n", pg_flow_ctrl[14]); ++ seq_printf(s, "\tPLE1 group page status(0x8206816c): 0x%08x\n", pg_flow_ctrl[15]); ++ min_q = FIELD_GET(MT_DBG_PSE_PG_PLE_GROUP_PLE_MIN_QUOTA_MASK, pg_flow_ctrl[20]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_PLE_GROUP_PLE_MAX_QUOTA_MASK, pg_flow_ctrl[20]); ++ seq_printf(s, "\t\tThe max/min quota pages of PLE1 group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_PLE_PG_INFO_PLE_RSV_CNT_MASK, pg_flow_ctrl[21]); ++ used_pg = FIELD_GET(MT_DBG_PSE_PLE_PG_INFO_PLE_SRC_CNT_MASK, pg_flow_ctrl[21]); ++ seq_printf(s, "\t\tThe used/reserved pages of PLE1 group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ ++ seq_printf(s, "\tReserved page counter of MDP group(0x82068198): 0x%08x\n", pg_flow_ctrl[18]); ++ seq_printf(s, "\tMDP group page status(0x8206819c): 0x%08x\n", pg_flow_ctrl[19]); ++ min_q = FIELD_GET(MT_DBG_PSE_PG_MDP_GROUP_MDP_MIN_QUOTA_MASK, pg_flow_ctrl[18]); ++ max_q = FIELD_GET(MT_DBG_PSE_PG_MDP_GROUP_MDP_MAX_QUOTA_MASK, pg_flow_ctrl[18]); ++ seq_printf(s, "\t\tThe max/min quota pages of MDP group=0x%03x/0x%03x\n", max_q, min_q); ++ rsv_pg = FIELD_GET(MT_DBG_PSE_MDP_PG_INFO_MDP_RSV_CNT_MASK, pg_flow_ctrl[19]); ++ used_pg = FIELD_GET(MT_DBG_PSE_MDP_PG_INFO_MDP_SRC_CNT_MASK, pg_flow_ctrl[19]); ++ seq_printf(s, "\t\tThe used/reserved pages of MDP group=0x%03x/0x%03x\n", used_pg, rsv_pg); ++ ++ /* Queue Empty Status */ ++ seq_printf(s, "PSE Queue Empty Status:\n"); ++ seq_printf(s, "\tQUEUE_EMPTY(0x820680b0): 0x%08x\n", pse_stat); ++ seq_printf(s, "\t\tCPU Q0/1/2/3 empty=%ld/%ld/%ld/%ld\n", ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_CPU_Q0_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_CPU_Q1_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_CPU_Q2_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_CPU_Q3_EMPTY_MASK, pse_stat)); ++ ++ seq_printf(s, "\t\tHIF Q0/1/2/3/4/5 empty=%ld/%ld/%ld/%ld/%ld/%ld\n", ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_HIF_0_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_HIF_1_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_HIF_2_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_HIF_3_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_HIF_4_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_HIF_5_EMPTY_MASK, pse_stat)); ++ ++ seq_printf(s, "\t\tLMAC TX Q empty=%ld\n", ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_LMAC_TX_QUEUE_EMPTY_MASK, pse_stat)); ++ seq_printf(s, "\t\tMDP TX Q/RX Q empty=%ld/%ld\n", ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_MDP_TX_QUEUE_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_MDP_RX_QUEUE_EMPTY_MASK, pse_stat)); ++ seq_printf(s, "\t\tSEC TX Q/RX Q empty=%ld/%ld\n", ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_SEC_TX_QUEUE_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_SEC_RX_QUEUE_EMPTY_SHFT, pse_stat)); ++ seq_printf(s, "\t\tSFD PARK Q empty=%ld\n", ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_SFD_PARK_QUEUE_EMPTY_MASK, pse_stat)); ++ seq_printf(s, "\t\tMDP TXIOC Q/RXIOC Q empty=%ld/%ld\n", ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_MDP_TXIOC_QUEUE_EMPTY_MASK, pse_stat), ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_MDP_RXIOC_QUEUE_EMPTY_MASK, pse_stat)); ++ seq_printf(s, "\t\tRLS Q empty=%ld\n", ++ FIELD_GET(MT_DBG_PSE_QUEUE_EMPTY_RLS_Q_EMTPY_MASK, pse_stat)); ++ seq_printf(s, "Nonempty Q info:\n"); ++ ++ for (i = 0; i < 31; i++) { ++ if (((pse_stat & (0x1 << i)) >> i) == 0) { ++ u32 hfid, tfid, pktcnt, fl_que_ctrl[3] = {0}; ++ ++ if (pse_queue_empty_info[i].QueueName != NULL) { ++ seq_printf(s, "\t%s: ", pse_queue_empty_info[i].QueueName); ++ fl_que_ctrl[0] |= MT_DBG_PSE_FL_QUE_CTRL_0_EXECUTE_MASK; ++ fl_que_ctrl[0] |= (pse_queue_empty_info[i].Portid << MT_DBG_PSE_FL_QUE_CTRL_0_Q_BUF_PID_SHFT); ++ fl_que_ctrl[0] |= (pse_queue_empty_info[i].Queueid << MT_DBG_PSE_FL_QUE_CTRL_0_Q_BUF_QID_SHFT); ++ } else ++ continue; ++ ++ fl_que_ctrl[0] |= (0x1 << 31); ++ ++ mt76_wr(dev, MT_DBG_PSE_FL_QUE_CTRL_0_ADDR, fl_que_ctrl[0]); ++ fl_que_ctrl[1] = mt76_rr(dev, MT_DBG_PSE_FL_QUE_CTRL_2_ADDR); ++ fl_que_ctrl[2] = mt76_rr(dev, MT_DBG_PSE_FL_QUE_CTRL_3_ADDR); ++ ++ hfid = FIELD_GET(MT_DBG_PSE_FL_QUE_CTRL_2_QUEUE_HEAD_FID_MASK, fl_que_ctrl[1]); ++ tfid = FIELD_GET(MT_DBG_PSE_FL_QUE_CTRL_2_QUEUE_TAIL_FID_MASK, fl_que_ctrl[1]); ++ pktcnt = FIELD_GET(MT_DBG_PSE_FL_QUE_CTRL_3_QUEUE_PKT_NUM_MASK, fl_que_ctrl[2]); ++ seq_printf(s, "tail/head fid = 0x%03x/0x%03x, pkt cnt = 0x%03x\n", ++ tfid, hfid, pktcnt); ++ } ++ } ++ ++ return 0; ++} ++ ++static int mt7915_mibinfo_read_per_band(struct seq_file *s, int band_idx) ++{ ++#define BSS_NUM 4 ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 mac_val0, mac_val, mac_val1, idx, band_offset = 0; ++ u32 msdr6, msdr7, msdr8, msdr9, msdr10, msdr16, msdr17, msdr18, msdr19, msdr20, msdr21; ++ u32 mbxsdr[BSS_NUM][7]; ++ u32 mbtcr[16], mbtbcr[16], mbrcr[16], mbrbcr[16]; ++ u32 btcr[BSS_NUM], btbcr[BSS_NUM], brcr[BSS_NUM], brbcr[BSS_NUM], btdcr[BSS_NUM], brdcr[BSS_NUM]; ++ u32 mu_cnt[5]; ++ u32 ampdu_cnt[3]; ++ unsigned long per; ++ ++ seq_printf(s, "Band %d MIB Status\n", band_idx); ++ seq_printf(s, "===============================\n"); ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0SCR0(band_idx)); ++ seq_printf(s, "MIB Status Control=0x%x\n", mac_val); ++ if (is_mt7915(&dev->mt76)) { ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0PBSCR(band_idx)); ++ seq_printf(s, "MIB Per-BSS Status Control=0x%x\n", mac_val); ++ } ++ ++ msdr6 = mt76_rr(dev, MT_DBG_MIB_M0SDR6(band_idx)); ++ msdr7 = mt76_rr(dev, MT_DBG_MIB_M0SDR7(band_idx)); ++ msdr8 = mt76_rr(dev, MT_DBG_MIB_M0SDR8(band_idx)); ++ msdr9 = mt76_rr(dev, MT_DBG_MIB_M0SDR9(band_idx)); ++ msdr10 = mt76_rr(dev, MT_DBG_MIB_M0SDR10(band_idx)); ++ msdr16 = mt76_rr(dev, MT_DBG_MIB_M0SDR16(band_idx)); ++ msdr17 = mt76_rr(dev, MT_DBG_MIB_M0SDR17(band_idx)); ++ msdr18 = mt76_rr(dev, MT_DBG_MIB_M0SDR18(band_idx)); ++ msdr19 = mt76_rr(dev, MT_DBG_MIB_M0SDR19(band_idx)); ++ msdr20 = mt76_rr(dev, MT_DBG_MIB_M0SDR20(band_idx)); ++ msdr21 = mt76_rr(dev, MT_DBG_MIB_M0SDR21(band_idx)); ++ ampdu_cnt[0] = mt76_rr(dev, MT_DBG_MIB_M0SDR12(band_idx)); ++ ampdu_cnt[1] = mt76_rr(dev, MT_DBG_MIB_M0SDR14(band_idx)); ++ ampdu_cnt[2] = mt76_rr(dev, MT_DBG_MIB_M0SDR15(band_idx)); ++ ampdu_cnt[1] &= MT_DBG_MIB_M0SDR14_AMPDU_MASK; ++ ampdu_cnt[2] &= MT_DBG_MIB_M0SDR15_AMPDU_ACKED_MASK; ++ ++ seq_printf(s, "===Phy/Timing Related Counters===\n"); ++ seq_printf(s, "\tChannelIdleCnt=0x%x\n", msdr6 & BN0_WF_MIB_TOP_M0SDR6_CHANNEL_IDLE_COUNT_MASK); ++ seq_printf(s, "\tCCA_NAV_Tx_Time=0x%x\n", msdr9 & BN0_WF_MIB_TOP_M0SDR9_CCA_NAV_TX_TIME_MASK); ++ seq_printf(s, "\tRx_MDRDY_CNT=0x%lx\n", msdr10 & MT_DBG_MIB_M0SDR10_RX_MDRDY_COUNT_MASK); ++ seq_printf(s, "\tCCK_MDRDY_TIME=0x%x, OFDM_MDRDY_TIME=0x%x, OFDM_GREEN_MDRDY_TIME=0x%x\n", ++ msdr19 & BN0_WF_MIB_TOP_M0SDR19_CCK_MDRDY_TIME_MASK, ++ msdr20 & BN0_WF_MIB_TOP_M0SDR20_OFDM_LG_MIXED_VHT_MDRDY_TIME_MASK, ++ msdr21 & BN0_WF_MIB_TOP_M0SDR21_OFDM_GREEN_MDRDY_TIME_MASK); ++ seq_printf(s, "\tPrim CCA Time=0x%x\n", msdr16 & BN0_WF_MIB_TOP_M0SDR16_P_CCA_TIME_MASK); ++ seq_printf(s, "\tSec CCA Time=0x%x\n", msdr17 & BN0_WF_MIB_TOP_M0SDR17_S_CCA_TIME_MASK); ++ seq_printf(s, "\tPrim ED Time=0x%x\n", msdr18 & BN0_WF_MIB_TOP_M0SDR18_P_ED_TIME_MASK); ++ ++ seq_printf(s, "===Tx Related Counters(Generic)===\n"); ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0SDR0(band_idx)); ++ dev->dbg.bcn_total_cnt[band_idx] += (mac_val & BN0_WF_MIB_TOP_M0SDR0_BEACONTXCOUNT_MASK); ++ seq_printf(s, "\tBeaconTxCnt=0x%x\n",dev->dbg.bcn_total_cnt[band_idx]); ++ dev->dbg.bcn_total_cnt[band_idx] = 0; ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0DR0(band_idx)); ++ seq_printf(s, "\tTx 20MHz Cnt=0x%x\n", mac_val & BN0_WF_MIB_TOP_M0DR0_TX_20MHZ_CNT_MASK); ++ seq_printf(s, "\tTx 40MHz Cnt=0x%x\n", (mac_val & BN0_WF_MIB_TOP_M0DR0_TX_40MHZ_CNT_MASK) >> BN0_WF_MIB_TOP_M0DR0_TX_40MHZ_CNT_SHFT); ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0DR1(band_idx)); ++ seq_printf(s, "\tTx 80MHz Cnt=0x%x\n", mac_val & BN0_WF_MIB_TOP_M0DR1_TX_80MHZ_CNT_MASK); ++ seq_printf(s, "\tTx 160MHz Cnt=0x%x\n", (mac_val & BN0_WF_MIB_TOP_M0DR1_TX_160MHZ_CNT_MASK) >> BN0_WF_MIB_TOP_M0DR1_TX_160MHZ_CNT_SHFT); ++ seq_printf(s, "\tAMPDU Cnt=0x%x\n", ampdu_cnt[0]); ++ seq_printf(s, "\tAMPDU MPDU Cnt=0x%x\n", ampdu_cnt[1]); ++ seq_printf(s, "\tAMPDU MPDU Ack Cnt=0x%x\n", ampdu_cnt[2]); ++ per = (ampdu_cnt[2] == 0 ? 0 : 1000 * (ampdu_cnt[1] - ampdu_cnt[2]) / ampdu_cnt[1]); ++ seq_printf(s, "\tAMPDU MPDU PER=%ld.%1ld%%\n", per / 10, per % 10); ++ ++ seq_printf(s, "===MU Related Counters===\n"); ++ mu_cnt[0] = mt76_rr(dev, MT_DBG_MIB_MUBF(band_idx)); ++ mu_cnt[1] = mt76_rr(dev, MT_DBG_MIB_M0DR8(band_idx)); ++ mu_cnt[2] = mt76_rr(dev, MT_DBG_MIB_M0DR9(band_idx)); ++ mu_cnt[3] = mt76_rr(dev, MT_DBG_MIB_M0DR10(band_idx)); ++ mu_cnt[4] = mt76_rr(dev, MT_DBG_MIB_M0DR11(band_idx)); ++ seq_printf(s, "\tMUBF_TX_COUNT=0x%x\n", mu_cnt[0] & BN0_WF_MIB_TOP_M0SDR34_MUBF_TX_COUNT_MASK); ++ seq_printf(s, "\tMU_TX_MPDU_COUNT(Ok+Fail)=0x%x\n", mu_cnt[1]); ++ seq_printf(s, "\tMU_TX_OK_MPDU_COUNT=0x%x\n", mu_cnt[2]); ++ seq_printf(s, "\tMU_TO_SU_PPDU_COUNT=0x%x\n", mu_cnt[3] & BN0_WF_MIB_TOP_M0DR10_MU_FAIL_PPDU_CNT_MASK); ++ seq_printf(s, "\tSU_TX_OK_MPDU_COUNT=0x%x\n", mu_cnt[4]); ++ ++ seq_printf(s, "===Rx Related Counters(Generic)===\n"); ++ seq_printf(s, "\tVector Mismacth Cnt=0x%x\n", msdr7 & BN0_WF_MIB_TOP_M0SDR7_VEC_MISS_COUNT_MASK); ++ seq_printf(s, "\tDelimiter Fail Cnt=0x%x\n", msdr8 & BN0_WF_MIB_TOP_M0SDR8_DELIMITER_FAIL_COUNT_MASK); ++ ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0SDR3(band_idx)); ++ seq_printf(s, "\tRxFCSErrCnt=0x%lx\n", __DBG_FIELD_GET(DBG_MIB_RX_FCS_ERROR_COUNT, mac_val)); ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0SDR4(band_idx)); ++ seq_printf(s, "\tRxFifoFullCnt=0x%x\n", (mac_val & BN0_WF_MIB_TOP_M0SDR4_RX_FIFO_FULL_COUNT_MASK)); ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0SDR11(band_idx)); ++ seq_printf(s, "\tRxLenMismatch=0x%x\n", (mac_val & BN0_WF_MIB_TOP_M0SDR11_RX_LEN_MISMATCH_MASK)); ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0SDR5(band_idx)); ++ seq_printf(s, "\tRxMPDUCnt=0x%x\n", (mac_val & BN0_WF_MIB_TOP_M0SDR5_RX_MPDU_COUNT_MASK)); ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0SDR22(band_idx)); ++ seq_printf(s, "\tRx AMPDU Cnt=0x%x\n", mac_val); ++ /* TODO: shiang-MT7615, is MIB_M0SDR23 used for Rx total byte count for all or just AMPDU only??? */ ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0SDR23(band_idx)); ++ seq_printf(s, "\tRx Total ByteCnt=0x%x\n", mac_val); ++ ++ if (is_mt7915(&dev->mt76)) { ++ band_offset = WF_WTBLON_TOP_B1BTCRn_ADDR - WF_WTBLON_TOP_B0BTCRn_ADDR;//check ++ seq_printf(s, "===Per-BSS Related Tx/Rx Counters===\n"); ++ seq_printf(s, "BSS Idx TxCnt/DataCnt TxByteCnt RxCnt/DataCnt RxByteCnt\n"); ++ ++ for (idx = 0; idx < BSS_NUM; idx++) { ++ btcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0BTCRn_ADDR + band_offset + idx * 4); ++ btbcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0BTBCRn_ADDR + band_offset + idx * 4); ++ brcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0BRCRn_ADDR + band_offset + idx * 4); ++ brbcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0BRBCRn_ADDR + band_offset + idx * 4); ++ btdcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0BTDCRn_ADDR + band_offset + idx * 4); ++ brdcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0BRDCRn_ADDR + band_offset + idx * 4); ++ } ++ ++ for (idx = 0; idx < BSS_NUM; idx++) { ++ seq_printf(s, "%d\t 0x%x/0x%x\t 0x%x \t 0x%x/0x%x \t 0x%x\n", ++ idx, btcr[idx], btdcr[idx], btbcr[idx], ++ brcr[idx], brdcr[idx], brbcr[idx]); ++ } ++ ++ band_offset = (BN1_WF_MIB_TOP_BASE - BN0_WF_MIB_TOP_BASE) * band_idx; ++ seq_printf(s, "===Per-MBSS Related MIB Counters===\n"); ++ seq_printf(s, "BSS Idx RTSTx/RetryCnt BAMissCnt AckFailCnt FrmRetry1/2/3Cnt\n"); ++ ++ for (idx = 0; idx < BSS_NUM; idx++) { ++ mbxsdr[idx][0] = mt76_rr(dev, BN0_WF_MIB_TOP_M0B0SDR0_ADDR + band_offset + idx * 0x10); ++ mbxsdr[idx][1] = mt76_rr(dev, BN0_WF_MIB_TOP_M0B0SDR1_ADDR + band_offset + idx * 0x10); ++ mbxsdr[idx][2] = mt76_rr(dev, BN0_WF_MIB_TOP_M0B0SDR2_ADDR + band_offset + idx * 0x10); ++ mbxsdr[idx][3] = mt76_rr(dev, BN0_WF_MIB_TOP_M0B0SDR3_ADDR + band_offset + idx * 0x10); ++ } ++ ++ for (idx = 0; idx < BSS_NUM; idx++) { ++ seq_printf(s, "%d:\t0x%08x/0x%08x 0x%08x \t 0x%08x \t 0x%08x/0x%08x/0x%08x\n", ++ idx, (mbxsdr[idx][0] & BN0_WF_MIB_TOP_M0B0SDR0_RTSTXCOUNT_MASK), ++ (mbxsdr[idx][0] & BN0_WF_MIB_TOP_M0B0SDR0_RTSRETRYCOUNT_MASK) >> BN0_WF_MIB_TOP_M0B0SDR0_RTSRETRYCOUNT_SHFT, ++ (mbxsdr[idx][1] & BN0_WF_MIB_TOP_M0B0SDR1_BAMISSCOUNT_MASK), ++ (mbxsdr[idx][1] & BN0_WF_MIB_TOP_M0B0SDR1_ACKFAILCOUNT_MASK) >> BN0_WF_MIB_TOP_M0B0SDR1_ACKFAILCOUNT_SHFT, ++ (mbxsdr[idx][2] & BN0_WF_MIB_TOP_M0B0SDR2_FRAMERETRYCOUNT_MASK), ++ (mbxsdr[idx][2] & BN0_WF_MIB_TOP_M0B0SDR2_FRAMERETRY2COUNT_MASK) >> BN0_WF_MIB_TOP_M0B0SDR2_FRAMERETRY2COUNT_SHFT, ++ (mbxsdr[idx][3] & BN0_WF_MIB_TOP_M0B0SDR3_FRAMERETRY3COUNT_MASK)); ++ } ++ ++ band_offset = WF_WTBLON_TOP_B1BTCRn_ADDR - WF_WTBLON_TOP_B0BTCRn_ADDR; ++ seq_printf(s, "===Per-MBSS Related Tx/Rx Counters===\n"); ++ seq_printf(s, "MBSSIdx TxCnt TxByteCnt RxCnt RxByteCnt\n"); ++ ++ for (idx = 0; idx < 16; idx++) { ++ mbtcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0MBTCRn_ADDR + band_offset + idx * 4); ++ mbtbcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0MBTBCRn_ADDR + band_offset + idx * 4); ++ mbrcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0MBRCRn_ADDR + band_offset + idx * 4); ++ mbrbcr[idx] = mt76_rr(dev, WF_WTBLON_TOP_B0MBRBCRn_ADDR + band_offset + idx * 4); ++ } ++ ++ for (idx = 0; idx < 16; idx++) { ++ seq_printf(s, "%d\t 0x%08x\t 0x%08x \t 0x%08x \t 0x%08x\n", ++ idx, mbtcr[idx], mbtbcr[idx], mbrcr[idx], mbrbcr[idx]); ++ } ++ return 0; ++ } else { ++ u32 btocr[BSS_NUM], mbtocr[16],mbrocr[16], brocr[BSS_NUM]; ++ u8 bss_nums = BSS_NUM; ++ ++ band_offset = (BN1_WF_MIB_TOP_BTOCR_ADDR - BN0_WF_MIB_TOP_BTOCR_ADDR) * band_idx; ++ seq_printf(s, "===Per-BSS Related Tx/Rx Counters===\n"); ++ seq_printf(s, "BSS Idx TxCnt/DataCnt TxByteCnt RxCnt/DataCnt RxByteCnt\n"); ++ ++ for (idx = 0; idx < BSS_NUM; idx++) { ++ btocr[idx] = mt76_rr(dev, (BN0_WF_MIB_TOP_BTOCR_ADDR + band_offset + (idx >> 1) * 4)); ++ btdcr[idx] = mt76_rr(dev, (BN0_WF_MIB_TOP_BTDCR_ADDR + band_offset + (idx >> 1) * 4)); ++ btbcr[idx] = mt76_rr(dev, (BN0_WF_MIB_TOP_BTBCR_ADDR + band_offset + (idx * 4))); ++ brocr[idx] = mt76_rr(dev, (BN0_WF_MIB_TOP_BROCR_ADDR + band_offset + (idx >> 1) * 4)); ++ brdcr[idx] = mt76_rr(dev, (BN0_WF_MIB_TOP_BRDCR_ADDR + band_offset + (idx >> 1) * 4)); ++ brbcr[idx] = mt76_rr(dev, (BN0_WF_MIB_TOP_BRBCR_ADDR + band_offset + (idx * 4))); ++ ++ if ((idx % 2) == 0) { ++ btocr[idx] = ((btocr[idx] & BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2n_MASK) >> BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2n_SHFT); ++ btdcr[idx] = ((btdcr[idx] & BN0_WF_MIB_TOP_BTDCR_TX_DATA_COUNT2n_MASK) >> BN0_WF_MIB_TOP_BTDCR_TX_DATA_COUNT2n_SHFT); ++ brocr[idx] = ((brocr[idx] & BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2n_MASK) >> BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2n_SHFT); ++ brdcr[idx] = ((brdcr[idx] & BN0_WF_MIB_TOP_BRDCR_RX_DATA_COUNT2n_MASK) >> BN0_WF_MIB_TOP_BRDCR_RX_DATA_COUNT2n_SHFT); ++ } else { ++ btocr[idx] = ((btocr[idx] & BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2np1_MASK) >> BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2np1_SHFT); ++ btdcr[idx] = ((btdcr[idx] & BN0_WF_MIB_TOP_BTDCR_TX_DATA_COUNT2np1_MASK) >> BN0_WF_MIB_TOP_BTDCR_TX_DATA_COUNT2np1_SHFT); ++ brocr[idx] = ((brocr[idx] & BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2np1_MASK) >> BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2np1_SHFT); ++ brdcr[idx] = ((brdcr[idx] & BN0_WF_MIB_TOP_BRDCR_RX_DATA_COUNT2np1_MASK) >> BN0_WF_MIB_TOP_BRDCR_RX_DATA_COUNT2np1_SHFT); ++ } ++ } ++ ++ for (idx = 0; idx < BSS_NUM; idx++) { ++ seq_printf(s, "%d\t 0x%x/0x%x\t 0x%x \t 0x%x/0x%x \t 0x%x\n", ++ idx, btocr[idx], btdcr[idx], btbcr[idx], brocr[idx], brdcr[idx], brbcr[idx]); ++ } ++ ++ band_offset = (BN1_WF_MIB_TOP_BASE - BN0_WF_MIB_TOP_BASE) * band_idx; ++ seq_printf(s, "===Per-MBSS Related MIB Counters===\n"); ++ seq_printf(s, "BSS Idx RTSTx/RetryCnt BAMissCnt AckFailCnt FrmRetry1/2/3Cnt\n"); ++ ++ for (idx = 0; idx < BSS_NUM; idx++) { ++ mbxsdr[idx][0] = mt76_rr(dev, BN0_WF_MIB_TOP_BSDR0_ADDR + band_offset + ((idx >> 1) * 4)); ++ mbxsdr[idx][1] = mt76_rr(dev, BN0_WF_MIB_TOP_BSDR1_ADDR + band_offset + ((idx >> 1) * 4)); ++ mbxsdr[idx][2] = mt76_rr(dev, BN0_WF_MIB_TOP_BSDR2_ADDR + band_offset + ((idx >> 1) * 4)); ++ mbxsdr[idx][3] = mt76_rr(dev, BN0_WF_MIB_TOP_BSDR3_ADDR + band_offset + ((idx >> 1) * 4)); ++ mbxsdr[idx][4] = mt76_rr(dev, BN0_WF_MIB_TOP_BSDR4_ADDR + band_offset + ((idx >> 1) * 4)); ++ mbxsdr[idx][5] = mt76_rr(dev, BN0_WF_MIB_TOP_BSDR5_ADDR + band_offset + ((idx >> 1) * 4)); ++ mbxsdr[idx][6] = mt76_rr(dev, BN0_WF_MIB_TOP_BSDR6_ADDR + band_offset + ((idx >> 1) * 4)); ++ ++ if ((idx % 2) == 0) { ++ mbxsdr[idx][0] = ((mbxsdr[idx][0] & BN0_WF_MIB_TOP_BSDR0_RTSTXCOUNT2n_MASK) >> BN0_WF_MIB_TOP_BSDR0_RTSTXCOUNT2n_SHFT); ++ mbxsdr[idx][1] = ((mbxsdr[idx][1] & BN0_WF_MIB_TOP_BSDR1_RTSRETRYCOUNT2n_MASK) >> BN0_WF_MIB_TOP_BSDR1_RTSRETRYCOUNT2n_SHFT); ++ mbxsdr[idx][2] = ((mbxsdr[idx][2] & BN0_WF_MIB_TOP_BSDR2_BAMISSCOUNT2n_MASK) >> BN0_WF_MIB_TOP_BSDR2_BAMISSCOUNT2n_SHFT); ++ mbxsdr[idx][3] = ((mbxsdr[idx][3] & BN0_WF_MIB_TOP_BSDR3_ACKFAILCOUNT2n_MASK) >> BN0_WF_MIB_TOP_BSDR3_ACKFAILCOUNT2n_SHFT); ++ mbxsdr[idx][4] = ((mbxsdr[idx][4] & BN0_WF_MIB_TOP_BSDR4_FRAMERETRYCOUNT2n_MASK) >> BN0_WF_MIB_TOP_BSDR4_FRAMERETRYCOUNT2n_SHFT); ++ mbxsdr[idx][5] = ((mbxsdr[idx][5] & BN0_WF_MIB_TOP_BSDR5_FRAMERETRY2COUNT2n_MASK) >> BN0_WF_MIB_TOP_BSDR5_FRAMERETRY2COUNT2n_SHFT); ++ mbxsdr[idx][6] = ((mbxsdr[idx][6] & BN0_WF_MIB_TOP_BSDR6_FRAMERETRY3COUNT2n_MASK) >> BN0_WF_MIB_TOP_BSDR6_FRAMERETRY3COUNT2n_SHFT); ++ } else { ++ mbxsdr[idx][0] = ((mbxsdr[idx][0] & BN0_WF_MIB_TOP_BSDR0_RTSTXCOUNT2np1_MASK) >> BN0_WF_MIB_TOP_BSDR0_RTSTXCOUNT2np1_SHFT); ++ mbxsdr[idx][1] = ((mbxsdr[idx][1] & BN0_WF_MIB_TOP_BSDR1_RTSRETRYCOUNT2np1_MASK) >> BN0_WF_MIB_TOP_BSDR1_RTSRETRYCOUNT2np1_SHFT); ++ mbxsdr[idx][2] = ((mbxsdr[idx][2] & BN0_WF_MIB_TOP_BSDR2_BAMISSCOUNT2np1_MASK) >> BN0_WF_MIB_TOP_BSDR2_BAMISSCOUNT2np1_SHFT); ++ mbxsdr[idx][3] = ((mbxsdr[idx][3] & BN0_WF_MIB_TOP_BSDR3_ACKFAILCOUNT2np1_MASK) >> BN0_WF_MIB_TOP_BSDR3_ACKFAILCOUNT2np1_SHFT); ++ mbxsdr[idx][4] = ((mbxsdr[idx][4] & BN0_WF_MIB_TOP_BSDR4_FRAMERETRYCOUNT2np1_MASK) >> BN0_WF_MIB_TOP_BSDR4_FRAMERETRYCOUNT2np1_SHFT); ++ mbxsdr[idx][5] = ((mbxsdr[idx][5] & BN0_WF_MIB_TOP_BSDR5_FRAMERETRY2COUNT2np1_MASK) >> BN0_WF_MIB_TOP_BSDR5_FRAMERETRY2COUNT2np1_SHFT); ++ mbxsdr[idx][6] = ((mbxsdr[idx][6] & BN0_WF_MIB_TOP_BSDR6_FRAMERETRY3COUNT2np1_MASK) >> BN0_WF_MIB_TOP_BSDR6_FRAMERETRY3COUNT2np1_SHFT); ++ } ++ } ++ ++ for (idx = 0; idx < BSS_NUM; idx++) { ++ seq_printf(s, "%d:\t0x%x/0x%x 0x%x \t 0x%x \t 0x%x/0x%x/0x%x\n", ++ idx, ++ mbxsdr[idx][0], mbxsdr[idx][1], mbxsdr[idx][2], mbxsdr[idx][3], ++ mbxsdr[idx][4], mbxsdr[idx][5], mbxsdr[idx][6]); ++ } ++ ++ band_offset = (BN1_WF_MIB_TOP_BTOCR_ADDR - BN0_WF_MIB_TOP_BTOCR_ADDR) * band_idx; ++ seq_printf(s, "===Per-MBSS Related Tx/Rx Counters===\n"); ++ seq_printf(s, "MBSSIdx TxCnt TxByteCnt RxCnt RxByteCnt\n"); ++ ++ for (idx = 0; idx < 16; idx++) { ++ mbtocr[idx] = mt76_rr(dev, BN0_WF_MIB_TOP_BTOCR_ADDR + band_offset + (((bss_nums >> 1) * 4) + ((idx >> 1) * 4))); ++ mbtbcr[idx] = mt76_rr(dev, BN0_WF_MIB_TOP_BTBCR_ADDR + band_offset + (((bss_nums >> 1) * 4) + (idx * 4))); ++ mbrocr[idx] = mt76_rr(dev, BN0_WF_MIB_TOP_BROCR_ADDR + band_offset + (((bss_nums >> 1) * 4) + ((idx >> 1) * 4))); ++ mbrbcr[idx] = mt76_rr(dev, BN0_WF_MIB_TOP_BRBCR_ADDR + band_offset + (((bss_nums >> 1) * 4) + (idx * 4))); ++ ++ if ((idx % 2) == 0) { ++ mbtocr[idx] = ((mbtocr[idx] & BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2n_MASK) >> BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2n_SHFT); ++ mbrocr[idx] = ((mbrocr[idx] & BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2n_MASK) >> BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2n_SHFT); ++ } else { ++ mbtocr[idx] = ((mbtocr[idx] & BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2np1_MASK) >> BN0_WF_MIB_TOP_BTOCR_TX_OK_COUNT2np1_SHFT); ++ mbrocr[idx] = ((mbrocr[idx] & BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2np1_MASK) >> BN0_WF_MIB_TOP_BROCR_RX_OK_COUNT2np1_SHFT); ++ } ++ } ++ ++ for (idx = 0; idx < 16; idx++) { ++ seq_printf(s, "%d\t 0x%08x\t 0x%08x \t 0x%08x \t 0x%08x\n", ++ idx, mbtocr[idx], mbtbcr[idx], mbrocr[idx], mbrbcr[idx]); ++ } ++ } ++ ++ seq_printf(s, "===Dummy delimiter insertion result===\n"); ++ mac_val0 = mt76_rr(dev, MT_DBG_MIB_M0DR11(band_idx)); ++ mac_val = mt76_rr(dev, MT_DBG_MIB_M0DR6(band_idx)); ++ mac_val1 = mt76_rr(dev, MT_DBG_MIB_M0DR7(band_idx)); ++ seq_printf(s, "Range0 = %d\t Range1 = %d\t Range2 = %d\t Range3 = %d\t Range4 = %d\n", ++ (mac_val0 & BN0_WF_MIB_TOP_M0DR12_TX_DDLMT_RNG0_CNT_MASK), ++ (mac_val & BN0_WF_MIB_TOP_M0DR6_TX_DDLMT_RNG1_CNT_MASK), ++ (mac_val & BN0_WF_MIB_TOP_M0DR6_TX_DDLMT_RNG2_CNT_MASK) >> BN0_WF_MIB_TOP_M0DR6_TX_DDLMT_RNG2_CNT_SHFT, ++ (mac_val1 & BN0_WF_MIB_TOP_M0DR7_TX_DDLMT_RNG3_CNT_MASK), ++ (mac_val1 & BN0_WF_MIB_TOP_M0DR7_TX_DDLMT_RNG4_CNT_MASK) >> BN0_WF_MIB_TOP_M0DR7_TX_DDLMT_RNG4_CNT_SHFT); ++ ++ return 0; ++} ++ ++static int mt7915_mibinfo_band0(struct seq_file *s, void *data) ++{ ++ mt7915_mibinfo_read_per_band(s, 0); ++ return 0; ++} ++ ++static int mt7915_mibinfo_band1(struct seq_file *s, void *data) ++{ ++ mt7915_mibinfo_read_per_band(s, 1); ++ return 0; ++} ++ ++static int mt7915_token_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ int id, count = 0; ++ struct mt76_txwi_cache *txwi; ++ ++ seq_printf(s, "Cut through token:\n"); ++ spin_lock_bh(&dev->mt76.token_lock); ++ idr_for_each_entry(&dev->mt76.token, txwi, id) { ++ seq_printf(s, "%4d ", id); ++ count++; ++ if (count % 8 == 0) ++ seq_printf(s, "\n"); ++ } ++ spin_unlock_bh(&dev->mt76.token_lock); ++ seq_printf(s, "\n"); ++ ++ return 0; ++} ++ ++struct txd_l { ++ u32 txd_0; ++ u32 txd_1; ++ u32 txd_2; ++ u32 txd_3; ++ u32 txd_4; ++ u32 txd_5; ++ u32 txd_6; ++ u32 txd_7; ++} __packed; ++ ++char *pkt_ft_str[] = {"cut_through", "store_forward", "cmd", "PDA_FW_Download"}; ++char *hdr_fmt_str[] = { ++ "Non-80211-Frame", ++ "Command-Frame", ++ "Normal-80211-Frame", ++ "enhanced-80211-Frame", ++}; ++/* TMAC_TXD_1.hdr_format */ ++#define TMI_HDR_FT_NON_80211 0x0 ++#define TMI_HDR_FT_CMD 0x1 ++#define TMI_HDR_FT_NOR_80211 0x2 ++#define TMI_HDR_FT_ENH_80211 0x3 ++ ++void mt7915_dump_tmac_info(u8 *tmac_info) ++{ ++ struct txd_l *txd = (struct txd_l *)tmac_info; ++ ++ printk("txd raw data: size=%d\n", MT_TXD_SIZE); ++ print_hex_dump(KERN_ERR , "", DUMP_PREFIX_OFFSET, 16, 1, tmac_info, MT_TXD_SIZE, false); ++ ++ printk("TMAC_TXD Fields:\n"); ++ printk("\tTMAC_TXD_0:\n"); ++ ++ /* DW0 */ ++ /* TX Byte Count [15:0] */ ++ printk("\t\tTxByteCnt = %ld\n", FIELD_GET(MT_TXD0_TX_BYTES, txd->txd_0)); ++ ++ /* PKT_FT: Packet Format [24:23] */ ++ printk("\t\tpkt_ft = %ld(%s)\n", ++ FIELD_GET(MT_TXD0_PKT_FMT, txd->txd_0), ++ pkt_ft_str[FIELD_GET(MT_TXD0_PKT_FMT, txd->txd_0)]); ++ ++ /* Q_IDX [31:25] */ ++ printk("\t\tQueID =0x%lx\n", FIELD_GET(MT_TXD0_Q_IDX, txd->txd_0)); ++ ++ printk("\tTMAC_TXD_1:\n"); ++ ++ /* DW1 */ ++ /* WLAN Indec [9:0] */ ++ printk("\t\tWlan Index = %ld\n", FIELD_GET(MT_TXD1_WLAN_IDX, txd->txd_1)); ++ ++ /* VTA [10] */ ++ printk("\t\tVTA = %d\n", ((txd->txd_1 & MT_TXD1_VTA) ? 1 : 0)); ++ ++ /* HF: Header Format [17:16] */ ++ printk("\t\tHdrFmt = %ld(%s)\n", ++ FIELD_GET(MT_TXD1_HDR_FORMAT, txd->txd_1), ++ FIELD_GET(MT_TXD1_HDR_FORMAT, txd->txd_1) < 4 ? ++ hdr_fmt_str[FIELD_GET(MT_TXD1_HDR_FORMAT, txd->txd_1)] : "N/A"); ++ ++ switch (FIELD_GET(MT_TXD1_HDR_FORMAT, txd->txd_1)) { ++ case TMI_HDR_FT_NON_80211: ++ /* MRD [11], EOSP [12], RMVL [13], VLAN [14], ETYPE [15] */ ++ printk("\t\t\tMRD = %d, EOSP = %d,\ ++ RMVL = %d, VLAN = %d, ETYP = %d\n", ++ (txd->txd_1 & MT_TXD1_MRD) ? 1 : 0, ++ (txd->txd_1 & MT_TXD1_EOSP) ? 1 : 0, ++ (txd->txd_1 & MT_TXD1_RMVL) ? 1 : 0, ++ (txd->txd_1 & MT_TXD1_VLAN) ? 1 : 0, ++ (txd->txd_1 & MT_TXD1_ETYP) ? 1 : 0); ++ break; ++ case TMI_HDR_FT_NOR_80211: ++ /* HEADER_LENGTH [15:11] */ ++ printk("\t\t\tHeader Len = %ld(WORD)\n", FIELD_GET(MT_TXD1_HDR_INFO, txd->txd_1)); ++ break; ++ ++ case TMI_HDR_FT_ENH_80211: ++ /* EOSP [12], AMS [13] */ ++ printk("\t\t\tEOSP = %d, AMS = %d\n", ++ (txd->txd_1 & MT_TXD1_EOSP) ? 1 : 0, ++ (txd->txd_1 & MT_TXD1_AMS) ? 1 : 0); ++ break; ++ } ++ ++ /* Header Padding [19:18] */ ++ printk("\t\tHdrPad = %ld\n", FIELD_GET(MT_TXD1_HDR_PAD, txd->txd_1)); ++ ++ /* TID [22:20] */ ++ printk("\t\tTID = %ld\n", FIELD_GET(MT_TXD1_TID, txd->txd_1)); ++ ++ ++ /* UtxB/AMSDU_C/AMSDU [23] */ ++ printk("\t\tamsdu = %d\n", ((txd->txd_1 & MT_TXD1_AMSDU) ? 1 : 0)); ++ ++ /* OM [29:24] */ ++ printk("\t\town_mac = %ld\n", FIELD_GET(MT_TXD1_OWN_MAC, txd->txd_1)); ++ ++ ++ /* TGID [30] */ ++ printk("\t\tTGID = %d\n", ((txd->txd_1 & MT_TXD1_TGID) ? 1 : 0)); ++ ++ ++ /* FT [31] */ ++ printk("\t\tTxDFormatType = %d\n", (txd->txd_1 & MT_TXD1_LONG_FORMAT) ? 1 : 0); ++ ++ printk("\tTMAC_TXD_2:\n"); ++ /* DW2 */ ++ /* Subtype [3:0] */ ++ printk("\t\tsub_type = %ld\n", FIELD_GET(MT_TXD2_SUB_TYPE, txd->txd_2)); ++ ++ /* Type[5:4] */ ++ printk("\t\tfrm_type = %ld\n", FIELD_GET(MT_TXD2_FRAME_TYPE, txd->txd_2)); ++ ++ /* NDP [6] */ ++ printk("\t\tNDP = %d\n", ((txd->txd_2 & MT_TXD2_NDP) ? 1 : 0)); ++ ++ /* NDPA [7] */ ++ printk("\t\tNDPA = %d\n", ((txd->txd_2 & MT_TXD2_NDPA) ? 1 : 0)); ++ ++ /* SD [8] */ ++ printk("\t\tSounding = %d\n", ((txd->txd_2 & MT_TXD2_SOUNDING) ? 1 : 0)); ++ ++ /* RTS [9] */ ++ printk("\t\tRTS = %d\n", ((txd->txd_2 & MT_TXD2_RTS) ? 1 : 0)); ++ ++ /* BM [10] */ ++ printk("\t\tbc_mc_pkt = %d\n", ((txd->txd_2 & MT_TXD2_MULTICAST) ? 1 : 0)); ++ ++ /* B [11] */ ++ printk("\t\tBIP = %d\n", ((txd->txd_2 & MT_TXD2_BIP) ? 1 : 0)); ++ ++ /* DU [12] */ ++ printk("\t\tDuration = %d\n", ((txd->txd_2 & MT_TXD2_DURATION) ? 1 : 0)); ++ ++ /* HE [13] */ ++ printk("\t\tHE(HTC Exist) = %d\n", ((txd->txd_2 & MT_TXD2_HTC_VLD) ? 1 : 0)); ++ ++ /* FRAG [15:14] */ ++ printk("\t\tFRAG = %ld\n", FIELD_GET(MT_TXD2_FRAG, txd->txd_2)); ++ ++ ++ /* Remaining Life Time [23:16]*/ ++ printk("\t\tReamingLife/MaxTx time = %ld (unit: 64TU)\n", ++ FIELD_GET(MT_TXD2_MAX_TX_TIME, txd->txd_2)); ++ ++ /* Power Offset [29:24] */ ++ printk("\t\tpwr_offset = %ld\n", FIELD_GET(MT_TXD2_POWER_OFFSET, txd->txd_2)); ++ ++ /* FRM [30] */ ++ printk("\t\tfix rate mode = %d\n", (txd->txd_2 & MT_TXD2_FIXED_RATE) ? 1 : 0); ++ ++ /* FR[31] */ ++ printk("\t\tfix rate = %d\n", (txd->txd_2 & MT_TXD2_FIX_RATE) ? 1 : 0); ++ ++ ++ printk("\tTMAC_TXD_3:\n"); ++ ++ /* DW3 */ ++ /* NA [0] */ ++ printk("\t\tNoAck = %d\n", (txd->txd_3 & MT_TXD3_NO_ACK) ? 1 : 0); ++ ++ /* PF [1] */ ++ printk("\t\tPF = %d\n", (txd->txd_3 & MT_TXD3_PROTECT_FRAME) ? 1 : 0); ++ ++ /* EMRD [2] */ ++ printk("\t\tEMRD = %d\n", (txd->txd_3 & MT_TXD3_EMRD) ? 1 : 0); ++ ++ /* EEOSP [3] */ ++ printk("\t\tEEOSP = %d\n", (txd->txd_3 & MT_TXD3_EEOSP) ? 1 : 0); ++ ++ /* DAS [4] */ ++ printk("\t\tda_select = %d\n", (txd->txd_3 & MT_TXD3_DAS) ? 1 : 0); ++ ++ /* TM [5] */ ++ printk("\t\ttm = %d\n", (txd->txd_3 & MT_TXD3_TIMING_MEASURE) ? 1 : 0); ++ ++ /* TX Count [10:6] */ ++ printk("\t\ttx_cnt = %ld\n", FIELD_GET(MT_TXD3_TX_COUNT, txd->txd_3)); ++ ++ /* Remaining TX Count [15:11] */ ++ printk("\t\tremain_tx_cnt = %ld\n", FIELD_GET(MT_TXD3_REM_TX_COUNT, txd->txd_3)); ++ ++ /* SN [27:16] */ ++ printk("\t\tsn = %ld\n", FIELD_GET(MT_TXD3_SEQ, txd->txd_3)); ++ ++ /* BA_DIS [28] */ ++ printk("\t\tba dis = %d\n", (txd->txd_3 & MT_TXD3_BA_DISABLE) ? 1 : 0); ++ ++ /* Power Management [29] */ ++ printk("\t\tpwr_mgmt = 0x%x\n", (txd->txd_3 & MT_TXD3_SW_POWER_MGMT) ? 1 : 0); ++ ++ /* PN_VLD [30] */ ++ printk("\t\tpn_vld = %d\n", (txd->txd_3 & MT_TXD3_PN_VALID) ? 1 : 0); ++ ++ /* SN_VLD [31] */ ++ printk("\t\tsn_vld = %d\n", (txd->txd_3 & MT_TXD3_SN_VALID) ? 1 : 0); ++ ++ ++ /* DW4 */ ++ printk("\tTMAC_TXD_4:\n"); ++ ++ /* PN_LOW [31:0] */ ++ printk("\t\tpn_low = 0x%lx\n", FIELD_GET(MT_TXD4_PN_LOW, txd->txd_4)); ++ ++ ++ /* DW5 */ ++ printk("\tTMAC_TXD_5:\n"); ++ ++ /* PID [7:0] */ ++ printk("\t\tpid = %ld\n", FIELD_GET(MT_TXD5_PID, txd->txd_5)); ++ ++ /* TXSFM [8] */ ++ printk("\t\ttx_status_fmt = %d\n", (txd->txd_5 & MT_TXD5_TX_STATUS_FMT) ? 1 : 0); ++ ++ /* TXS2M [9] */ ++ printk("\t\ttx_status_2_mcu = %d\n", (txd->txd_5 & MT_TXD5_TX_STATUS_MCU) ? 1 : 0); ++ ++ /* TXS2H [10] */ ++ printk("\t\ttx_status_2_host = %d\n", (txd->txd_5 & MT_TXD5_TX_STATUS_HOST) ? 1 : 0); ++ ++ /* ADD_BA [14] */ ++ printk("\t\tADD_BA = %d\n", (txd->txd_5 & MT_TXD5_ADD_BA) ? 1 : 0); ++ ++ /* MD [15] */ ++ printk("\t\tMD = %d\n", (txd->txd_5 & MT_TXD5_MD) ? 1 : 0); ++ ++ /* PN_HIGH [31:16] */ ++ printk("\t\tpn_high = 0x%lx\n", FIELD_GET(MT_TXD5_PN_HIGH, txd->txd_5)); ++ ++ /* DW6 */ ++ printk("\tTMAC_TXD_6:\n"); ++ ++ if (txd->txd_2 & MT_TXD2_FIX_RATE) { ++ /* Fixed BandWidth mode [2:0] */ ++ printk("\t\tbw = %ld\n", ++ FIELD_GET(MT_TXD6_BW, txd->txd_6) | (txd->txd_6 & MT_TXD6_FIXED_BW)); ++ ++ /* DYN_BW [3] */ ++ printk("\t\tdyn_bw = %d\n", (txd->txd_6 & MT_TXD6_DYN_BW) ? 1 : 0); ++ ++ /* ANT_ID [7:4] */ ++ printk("\t\tant_id = %ld\n", FIELD_GET(MT_TXD6_ANT_ID, txd->txd_6)); ++ ++ /* SPE_IDX_SEL [10] */ ++ printk("\t\tspe_idx_sel = %d\n", (txd->txd_6 & MT_TXD6_SPE_ID_IDX) ? 1 : 0); ++ ++ /* LDPC [11] */ ++ printk("\t\tldpc = %d\n", (txd->txd_6 & MT_TXD6_LDPC) ? 1 : 0); ++ ++ /* HELTF Type[13:12] */ ++ printk("\t\tHELTF Type = %ld\n", FIELD_GET(MT_TXD6_HELTF, txd->txd_6)); ++ ++ /* GI Type [15:14] */ ++ printk("\t\tGI = %ld\n", FIELD_GET(MT_TXD6_SGI, txd->txd_6)); ++ ++ /* Rate to be Fixed [29:16] */ ++ printk("\t\ttx_rate = 0x%lx\n", FIELD_GET(MT_TXD6_TX_RATE, txd->txd_6)); ++ } ++ ++ /* TXEBF [30] */ ++ printk("\t\ttxebf = %d\n", (txd->txd_6 & MT_TXD6_TX_EBF) ? 1 : 0); ++ ++ /* TXIBF [31] */ ++ printk("\t\ttxibf = %d\n", (txd->txd_6 & MT_TXD6_TX_IBF) ? 1 : 0); ++ ++ /* DW7 */ ++ printk("\tTMAC_TXD_7:\n"); ++ ++ if ((txd->txd_1 & MT_TXD1_VTA) == 0) { ++ /* SW Tx Time [9:0] */ ++ printk("\t\tsw_tx_time = %ld\n", FIELD_GET(MT_TXD7_TX_TIME, txd->txd_7)); ++ } else { ++ /* TXD Arrival Time [9:0] */ ++ printk("\t\tat = %ld\n", FIELD_GET(MT_TXD7_TAT, txd->txd_7)); ++ } ++ ++ /* HW_AMSDU_CAP [10] */ ++ printk("\t\thw amsdu cap = %d\n",(txd->txd_7 & MT_TXD7_HW_AMSDU) ? 1 : 0); ++ ++ /* SPE_IDX [15:11] */ ++ if (txd->txd_2 & MT_TXD2_FIX_RATE) { ++ printk("\t\tspe_idx = 0x%lx\n", FIELD_GET(MT_TXD7_SPE_IDX, txd->txd_7)); ++ } ++ ++ /* PSE_FID [27:16] */ ++ printk("\t\tpse_fid = 0x%lx\n", FIELD_GET(MT_TXD7_PSE_FID, txd->txd_7)); ++ ++ /* Subtype [19:16] */ ++ printk("\t\tpp_sub_type=%ld\n", FIELD_GET(MT_TXD7_SUB_TYPE, txd->txd_7)); ++ ++ /* Type [21:20] */ ++ printk("\t\tpp_type=%ld\n", FIELD_GET(MT_TXD7_TYPE, txd->txd_7)); ++ ++ /* CTXD_CNT [25:23] */ ++ printk("\t\tctxd cnt=0x%lx\n", FIELD_GET(MT_TXD7_CTXD_CNT, txd->txd_7)); ++ ++ /* CTXD [26] */ ++ printk("\t\tctxd = %d\n", (txd->txd_7 & MT_TXD7_CTXD) ? 1 : 0); ++ ++ /* I [28] */ ++ printk("\t\ti = %d\n", (txd->txd_7 & MT_TXD7_IP_SUM) ? 1 : 0); ++ ++ /* UT [29] */ ++ printk("\t\tUT = %d\n", (txd->txd_7 & MT_TXD7_UDP_TCP_SUM) ? 1 : 0); ++ ++ /* TXDLEN [31:30] */ ++ printk("\t\t txd len= %ld\n", FIELD_GET(MT_TXD7_TXD_LEN, txd->txd_7)); ++} ++ ++ ++static int mt7915_token_txd_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ struct mt76_txwi_cache *t; ++ u8* txwi; ++ ++ seq_printf(s, "\n"); ++ spin_lock_bh(&dev->mt76.token_lock); ++ ++ t = idr_find(&dev->mt76.token, dev->dbg.token_idx); ++ ++ if (t != NULL) { ++ struct mt76_dev *mdev = &dev->mt76; ++ txwi = ((u8*)(t)) - (mdev->drv->txwi_size); ++ mt7915_dump_tmac_info((u8*) txwi); ++ seq_printf(s, "\n"); ++ printk("[SKB]\n"); ++ print_hex_dump(KERN_ERR , "", DUMP_PREFIX_OFFSET, 16, 1, (u8 *)t->skb->data, t->skb->len, false); ++ seq_printf(s, "\n"); ++ } ++ spin_unlock_bh(&dev->mt76.token_lock); ++ return 0; ++} ++ ++static int mt7915_amsduinfo_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 ple_stat[8] = {0}, total_amsdu = 0; ++ u8 i; ++ ++ for (i = 0; i < 8; i++) ++ ple_stat[i] = mt76_rr(dev, MT_DBG_PLE_AMSDU_PACK_MSDU_CNT(i)); ++ ++ seq_printf(s, "TXD counter status of MSDU:\n"); ++ ++ for (i = 0; i < 8; i++) ++ total_amsdu += ple_stat[i]; ++ ++ for (i = 0; i < 8; i++) { ++ seq_printf(s, "AMSDU pack count of %d MSDU in TXD: 0x%x ", i + 1, ple_stat[i]); ++ if (total_amsdu != 0) ++ seq_printf(s, "(%d%%)\n", ple_stat[i] * 100 / total_amsdu); ++ else ++ seq_printf(s, "\n"); ++ } ++ ++ return 0; ++ ++} ++ ++static int mt7915_agginfo_read_per_band(struct seq_file *s, int band_idx) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 value, idx, agg_rang_sel[15], ampdu_cnt[11], total_ampdu = 0; ++ ++ seq_printf(s, "Band %d AGG Status\n", band_idx); ++ seq_printf(s, "===============================\n"); ++ value = mt76_rr(dev, MT_DBG_AGG_AALCR0(band_idx)); ++ seq_printf(s, "AC00 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx0_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC01 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx1_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC02 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx2_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC03 Agg limit = %ld\n", FIELD_GET(MT_DBG_AGG_AALCR_ACx3_AGG_LIMIT_MASK, value)); ++ ++ value = mt76_rr(dev, MT_DBG_AGG_AALCR1(band_idx)); ++ seq_printf(s, "AC10 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx0_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC11 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx1_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC12 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx2_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC13 Agg limit = %ld\n", FIELD_GET(MT_DBG_AGG_AALCR_ACx3_AGG_LIMIT_MASK, value)); ++ ++ value = mt76_rr(dev, MT_DBG_AGG_AALCR2(band_idx)); ++ seq_printf(s, "AC20 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx0_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC21 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx1_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC22 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx2_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC23 Agg limit = %ld\n", FIELD_GET(MT_DBG_AGG_AALCR_ACx3_AGG_LIMIT_MASK, value)); ++ ++ value = mt76_rr(dev, MT_DBG_AGG_AALCR3(band_idx)); ++ seq_printf(s, "AC30 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx0_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC31 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx1_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC32 Agg limit = %ld\t", FIELD_GET(MT_DBG_AGG_AALCR_ACx2_AGG_LIMIT_MASK, value)); ++ seq_printf(s, "AC33 Agg limit = %ld\n", FIELD_GET(MT_DBG_AGG_AALCR_ACx3_AGG_LIMIT_MASK, value)); ++ ++ value = mt76_rr(dev, MT_DBG_AGG_AALCR4(band_idx)); ++ seq_printf(s, "ALTX Agg limit = %ld\n", FIELD_GET(MT_DBG_AGG_AALCR4_ALTX0_AGG_LIMIT_MASK, value)); ++ ++ value = mt76_rr(dev, MT_DBG_AGG_AWSCR(band_idx, 0)); ++ seq_printf(s, "Winsize0 limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR0_WINSIZE0_MASK, value)); ++ seq_printf(s, "Winsize1 limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR0_WINSIZE1_MASK, value)); ++ seq_printf(s, "Winsize2 limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR0_WINSIZE2_MASK, value)); ++ seq_printf(s, "Winsize3 limit = %ld\n", FIELD_GET(MT_DBG_AGG_AWSCR0_WINSIZE3_MASK, value)); ++ ++ value = mt76_rr(dev, MT_DBG_AGG_AWSCR(band_idx, 1)); ++ seq_printf(s, "Winsize4 limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR1_WINSIZE4_MASK, value)); ++ seq_printf(s, "Winsize5 limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR1_WINSIZE5_MASK, value)); ++ seq_printf(s, "Winsize6 limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR1_WINSIZE6_MASK, value)); ++ seq_printf(s, "Winsize7 limit = %ld\n", FIELD_GET(MT_DBG_AGG_AWSCR1_WINSIZE7_MASK, value)); ++ ++ value = mt76_rr(dev, MT_DBG_AGG_AWSCR(band_idx, 2)); ++ seq_printf(s, "Winsize8 limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR2_WINSIZE8_MASK, value)); ++ seq_printf(s, "Winsize9 limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR2_WINSIZE9_MASK, value)); ++ seq_printf(s, "WinsizeA limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR2_WINSIZEA_MASK, value)); ++ seq_printf(s, "WinsizeB limit = %ld\n", FIELD_GET(MT_DBG_AGG_AWSCR2_WINSIZEB_MASK, value)); ++ ++ ++ value = mt76_rr(dev, MT_DBG_AGG_AWSCR(band_idx, 3)); ++ seq_printf(s, "WinsizeC limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR3_WINSIZEC_MASK, value)); ++ seq_printf(s, "WinsizeD limit = %ld\t", FIELD_GET(MT_DBG_AGG_AWSCR3_WINSIZED_MASK, value)); ++ seq_printf(s, "WinsizeE limit = %ld\n", FIELD_GET(MT_DBG_AGG_AWSCR3_WINSIZEE_MASK, value)); ++ ++ seq_printf(s, "===AMPDU Related Counters===\n"); ++ ++ value = mt76_rr(dev, MT_DBG_MIB_M0ARNG(band_idx, 0)); ++ agg_rang_sel[0] = FIELD_GET(MT_DBG_MIB_M0ARNG0_AGG_RANG_SEL0_MASK, value); ++ agg_rang_sel[1] = FIELD_GET(MT_DBG_MIB_M0ARNG0_AGG_RANG_SEL1_MASK, value); ++ agg_rang_sel[2] = FIELD_GET(MT_DBG_MIB_M0ARNG0_AGG_RANG_SEL2_MASK, value); ++ agg_rang_sel[3] = FIELD_GET(MT_DBG_MIB_M0ARNG0_AGG_RANG_SEL3_MASK, value); ++ ++ value = mt76_rr(dev, MT_DBG_MIB_M0ARNG(band_idx, 1)); ++ agg_rang_sel[4] = FIELD_GET(MT_DBG_MIB_M0ARNG1_AGG_RANG_SEL4_MASK, value); ++ agg_rang_sel[5] = FIELD_GET(MT_DBG_MIB_M0ARNG1_AGG_RANG_SEL5_MASK, value); ++ agg_rang_sel[6] = FIELD_GET(MT_DBG_MIB_M0ARNG1_AGG_RANG_SEL6_MASK, value); ++ agg_rang_sel[7] = FIELD_GET(MT_DBG_MIB_M0ARNG1_AGG_RANG_SEL7_MASK, value); ++ ++ value = mt76_rr(dev, MT_DBG_MIB_M0ARNG(band_idx, 2)); ++ agg_rang_sel[8] = FIELD_GET(MT_DBG_MIB_M0ARNG2_AGG_RANG_SEL8_MASK, value); ++ agg_rang_sel[9] = FIELD_GET(MT_DBG_MIB_M0ARNG2_AGG_RANG_SEL9_MASK, value); ++ agg_rang_sel[10] = FIELD_GET(MT_DBG_MIB_M0ARNG2_AGG_RANG_SEL10_MASK, value); ++ agg_rang_sel[11] = FIELD_GET(MT_DBG_MIB_M0ARNG2_AGG_RANG_SEL11_MASK, value); ++ ++ value = mt76_rr(dev, MT_DBG_MIB_M0ARNG(band_idx, 3)); ++ agg_rang_sel[12] = FIELD_GET(MT_DBG_MIB_M0ARNG3_AGG_RANG_SEL12_MASK, value); ++ agg_rang_sel[13] = FIELD_GET(MT_DBG_MIB_M0ARNG3_AGG_RANG_SEL13_MASK, value); ++ agg_rang_sel[14] = FIELD_GET(MT_DBG_MIB_M0ARNG3_AGG_RANG_SEL14_MASK, value); ++ ++ /* Need to add 1 after read from AGG_RANG_SEL CR */ ++ for (idx = 0; idx < 15; idx++) ++ agg_rang_sel[idx]++; ++ ++ ampdu_cnt[3] = mt76_rr(dev, MT_DBG_MIB_M0DR2(band_idx, 0)); ++ ampdu_cnt[4] = mt76_rr(dev, MT_DBG_MIB_M0DR2(band_idx, 1)); ++ ampdu_cnt[5] = mt76_rr(dev, MT_DBG_MIB_M0DR2(band_idx, 2)); ++ ampdu_cnt[6] = mt76_rr(dev, MT_DBG_MIB_M0DR2(band_idx, 3)); ++ ampdu_cnt[7] = mt76_rr(dev, MT_DBG_MIB_M0DR13(band_idx, 0)); ++ ampdu_cnt[8] = mt76_rr(dev, MT_DBG_MIB_M0DR13(band_idx, 1)); ++ ampdu_cnt[9] = mt76_rr(dev, MT_DBG_MIB_M0DR13(band_idx, 2)); ++ ampdu_cnt[10] = mt76_rr(dev, MT_DBG_MIB_M0DR13(band_idx, 3)); ++ ++ seq_printf(s, "\tTx Agg Range: \t%d \t%d~%d \t%d~%d \t%d~%d \t%d~%d \t%d~%d \t%d~%d \t%d~%d\n", ++ agg_rang_sel[0], ++ agg_rang_sel[0] + 1, agg_rang_sel[1], ++ agg_rang_sel[1] + 1, agg_rang_sel[2], ++ agg_rang_sel[2] + 1, agg_rang_sel[3], ++ agg_rang_sel[3] + 1, agg_rang_sel[4], ++ agg_rang_sel[4] + 1, agg_rang_sel[5], ++ agg_rang_sel[5] + 1, agg_rang_sel[6], ++ agg_rang_sel[6] + 1, agg_rang_sel[7]); ++ ++#define BIT_0_to_15_MASK 0x0000FFFF ++#define BIT_15_to_31_MASK 0xFFFF0000 ++#define SHFIT_16_BIT 16 ++ ++ for (idx = 3; idx < 11; idx++) ++ total_ampdu = total_ampdu + (ampdu_cnt[idx] & BIT_0_to_15_MASK) + ((ampdu_cnt[idx] & BIT_15_to_31_MASK) >> SHFIT_16_BIT); ++ ++ seq_printf(s, "\t\t\t0x%lx \t0x%lx \t0x%lx \t0x%lx \t0x%lx \t0x%lx \t0x%lx \t0x%lx\n", ++ (ampdu_cnt[3]) & MT_DBG_MIB_M0DR2_TRX_AGG_RANGE0_CNT_MASK, ++ FIELD_GET(MT_DBG_MIB_M0DR2_TRX_AGG_RANGE1_CNT_MASK, ampdu_cnt[3]), ++ (ampdu_cnt[4]) & MT_DBG_MIB_M0DR3_TRX_AGG_RANGE2_CNT_MASK, ++ FIELD_GET(MT_DBG_MIB_M0DR3_TRX_AGG_RANGE3_CNT_MASK, ampdu_cnt[4]), ++ (ampdu_cnt[5]) & MT_DBG_MIB_M0DR4_TRX_AGG_RANGE4_CNT_MASK, ++ FIELD_GET(MT_DBG_MIB_M0DR4_TRX_AGG_RANGE5_CNT_MASK, ampdu_cnt[5]), ++ (ampdu_cnt[6]) & MT_DBG_MIB_M0DR5_TRX_AGG_RANGE6_CNT_MASK, ++ FIELD_GET(MT_DBG_MIB_M0DR5_TRX_AGG_RANGE7_CNT_MASK, ampdu_cnt[6])); ++ ++ if (total_ampdu != 0) { ++ seq_printf(s, "\t\t\t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%)\n", ++ ((ampdu_cnt[3]) & MT_DBG_MIB_M0DR2_TRX_AGG_RANGE0_CNT_MASK) * 100 / total_ampdu, ++ FIELD_GET(MT_DBG_MIB_M0DR2_TRX_AGG_RANGE1_CNT_MASK, ampdu_cnt[3]) * 100 / total_ampdu, ++ ((ampdu_cnt[4]) & MT_DBG_MIB_M0DR3_TRX_AGG_RANGE2_CNT_MASK) * 100 / total_ampdu, ++ FIELD_GET(MT_DBG_MIB_M0DR3_TRX_AGG_RANGE3_CNT_MASK, ampdu_cnt[4]) * 100 / total_ampdu, ++ ((ampdu_cnt[5]) & MT_DBG_MIB_M0DR4_TRX_AGG_RANGE4_CNT_MASK) * 100 / total_ampdu, ++ FIELD_GET(MT_DBG_MIB_M0DR4_TRX_AGG_RANGE5_CNT_MASK, ampdu_cnt[5]) * 100 / total_ampdu, ++ ((ampdu_cnt[6]) & MT_DBG_MIB_M0DR5_TRX_AGG_RANGE6_CNT_MASK) * 100 / total_ampdu, ++ FIELD_GET(MT_DBG_MIB_M0DR5_TRX_AGG_RANGE7_CNT_MASK, ampdu_cnt[6]) * 100 / total_ampdu); ++ } ++ ++ seq_printf(s, "\t\t\t%d~%d\t%d~%d\t%d~%d\t%d~%d\t%d~%d\t%d~%d\t%d~%d\t%d~256\n", ++ agg_rang_sel[7] + 1, agg_rang_sel[8], ++ agg_rang_sel[8] + 1, agg_rang_sel[9], ++ agg_rang_sel[9] + 1, agg_rang_sel[10], ++ agg_rang_sel[10] + 1, agg_rang_sel[11], ++ agg_rang_sel[11] + 1, agg_rang_sel[12], ++ agg_rang_sel[12] + 1, agg_rang_sel[13], ++ agg_rang_sel[13] + 1, agg_rang_sel[14], ++ agg_rang_sel[14] + 1); ++ ++ seq_printf(s, "\t\t\t0x%lx \t0x%lx \t0x%lx \t0x%lx \t0x%lx \t0x%lx \t0x%lx \t0x%lx\n", ++ (ampdu_cnt[7]) & MT_DBG_MIB_M0DR13_TRX_AGG_RANGE8_CNT_MASK, ++ FIELD_GET(MT_DBG_MIB_M0DR13_TRX_AGG_RANGE9_CNT_MASK, ampdu_cnt[7]), ++ (ampdu_cnt[8]) & MT_DBG_MIB_M0DR14_TRX_AGG_RANGE10_CNT_MASK, ++ FIELD_GET(MT_DBG_MIB_M0DR14_TRX_AGG_RANGE11_CNT_MASK, ampdu_cnt[8]), ++ (ampdu_cnt[9]) & MT_DBG_MIB_M0DR15_TRX_AGG_RANGE12_CNT_MASK, ++ FIELD_GET(MT_DBG_MIB_M0DR15_TRX_AGG_RANGE13_CNT_MASK, ampdu_cnt[9]), ++ (ampdu_cnt[10]) & MT_DBG_MIB_M0DR16_TRX_AGG_RANGE14_CNT_MASK, ++ FIELD_GET(MT_DBG_MIB_M0DR16_TRX_AGG_RANGE15_CNT_MASK, ampdu_cnt[10])); ++ ++ if (total_ampdu != 0) { ++ seq_printf(s, "\t\t\t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%) \t(%ld%%)\n", ++ ((ampdu_cnt[7]) & MT_DBG_MIB_M0DR2_TRX_AGG_RANGE0_CNT_MASK) * 100 / total_ampdu, ++ FIELD_GET(MT_DBG_MIB_M0DR2_TRX_AGG_RANGE1_CNT_MASK, ampdu_cnt[7]) * 100 / total_ampdu, ++ ((ampdu_cnt[8]) & MT_DBG_MIB_M0DR3_TRX_AGG_RANGE2_CNT_MASK) * 100 / total_ampdu, ++ FIELD_GET(MT_DBG_MIB_M0DR3_TRX_AGG_RANGE3_CNT_MASK, ampdu_cnt[8]) * 100 / total_ampdu, ++ ((ampdu_cnt[9]) & MT_DBG_MIB_M0DR4_TRX_AGG_RANGE4_CNT_MASK) * 100 / total_ampdu, ++ FIELD_GET(MT_DBG_MIB_M0DR4_TRX_AGG_RANGE5_CNT_MASK, ampdu_cnt[9]) * 100 / total_ampdu, ++ ((ampdu_cnt[10]) & MT_DBG_MIB_M0DR5_TRX_AGG_RANGE6_CNT_MASK) * 100 / total_ampdu, ++ FIELD_GET(MT_DBG_MIB_M0DR5_TRX_AGG_RANGE7_CNT_MASK, ampdu_cnt[10]) * 100 / total_ampdu); ++ } ++ ++ return 0; ++} ++ ++static int mt7915_agginfo_read_band0(struct seq_file *s, void *data) ++{ ++ mt7915_agginfo_read_per_band(s, 0); ++ return 0; ++} ++ ++static int mt7915_agginfo_read_band1(struct seq_file *s, void *data) ++{ ++ mt7915_agginfo_read_per_band(s, 1); ++ return 0; ++} ++ ++/*usage: ++ en: BIT(16) 0: sw amsdu 1: hw amsdu ++ num: GENMASK(15, 8) range 1-8 ++ len: GENMASK(7, 0) unit: 256 bytes */ ++static int mt7915_sta_tx_amsdu_set(void *data, u64 tx_amsdu) ++{ ++/* UWTBL DW 6 */ ++#define WTBL_AMSDU_LEN_MASK GENMASK(5, 0) ++#define WTBL_AMSDU_NUM_MASK GENMASK(8, 6) ++#define WTBL_AMSDU_EN_MASK BIT(9) ++#define UWTBL_HW_AMSDU_DW 6 ++ ++ struct mt7915_dev *dev = data; ++ u32 len = FIELD_GET(GENMASK(7, 0), tx_amsdu); ++ u32 num = FIELD_GET(GENMASK(15, 8), tx_amsdu); ++ u32 uwtbl; ++ ++ mt7915_mcu_set_amsdu_algo(dev, dev->wlan_idx, 0); ++ ++ mt7915_wtbl_read_raw(dev, dev->wlan_idx, WTBL_TYPE_UMAC, ++ UWTBL_HW_AMSDU_DW, 1, &uwtbl); ++ ++ if (len) { ++ uwtbl &= ~WTBL_AMSDU_LEN_MASK; ++ uwtbl |= FIELD_PREP(WTBL_AMSDU_LEN_MASK, len); ++ } ++ ++ uwtbl &= ~WTBL_AMSDU_NUM_MASK; ++ uwtbl |= FIELD_PREP(WTBL_AMSDU_NUM_MASK, num); ++ ++ if (tx_amsdu & BIT(16)) ++ uwtbl |= WTBL_AMSDU_EN_MASK; ++ ++ mt7915_wtbl_write_raw(dev, dev->wlan_idx, WTBL_TYPE_UMAC, ++ UWTBL_HW_AMSDU_DW, uwtbl); ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_tx_amsdu, NULL, ++ mt7915_sta_tx_amsdu_set, "%llx\n"); ++ ++static int mt7915_red_enable_set(void *data, u64 en) ++{ ++ struct mt7915_dev *dev = data; ++ ++ return mt7915_mcu_set_red(dev, en); ++} ++DEFINE_DEBUGFS_ATTRIBUTE(fops_red_en, NULL, ++ mt7915_red_enable_set, "%llx\n"); ++ ++static int mt7915_red_show_sta_set(void *data, u64 wlan_idx) ++{ ++ struct mt7915_dev *dev = data; ++ ++ mt7915_dbg_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), ++ MCU_WA_PARAM_RED_SHOW_STA, ++ wlan_idx, 0, true); ++ ++ return 0; ++} ++DEFINE_DEBUGFS_ATTRIBUTE(fops_red_show_sta, NULL, ++ mt7915_red_show_sta_set, "%llx\n"); ++ ++static int mt7915_red_target_dly_set(void *data, u64 delay) ++{ ++ struct mt7915_dev *dev = data; ++ ++ if (delay > 0 && delay <= 32767) ++ mt7915_dbg_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), ++ MCU_WA_PARAM_RED_TARGET_DELAY, ++ delay, 0, true); ++ ++ return 0; ++} ++DEFINE_DEBUGFS_ATTRIBUTE(fops_red_target_dly, NULL, ++ mt7915_red_target_dly_set, "%llx\n"); ++ ++static int ++mt7915_txpower_level_set(void *data, u64 val) ++{ ++ struct mt7915_dev *dev = data; ++ struct mt7915_phy *ext_phy = mt7915_ext_phy(dev); ++ mt7915_mcu_set_txpower_level(&dev->phy, val); ++ if (ext_phy) ++ mt7915_mcu_set_txpower_level(ext_phy, val); ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_txpower_level, NULL, ++ mt7915_txpower_level_set, "%lld\n"); ++ ++/* usage: echo 0x[arg3][arg2][arg1] > fw_wa_set */ ++static int ++mt7915_wa_set(void *data, u64 val) ++{ ++ struct mt7915_dev *dev = data; ++ u32 arg1, arg2, arg3; ++ ++ arg1 = FIELD_GET(GENMASK_ULL(7, 0), val); ++ arg2 = FIELD_GET(GENMASK_ULL(15, 8), val); ++ arg3 = FIELD_GET(GENMASK_ULL(23, 16), val); ++ ++ mt7915_dbg_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), arg1, arg2, arg3, false); ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_wa_set, NULL, mt7915_wa_set, ++ "0x%llx\n"); ++/* usage: echo 0x[arg3][arg2][arg1] > fw_wa_query */ ++static int ++mt7915_wa_query(void *data, u64 val) ++{ ++ struct mt7915_dev *dev = data; ++ u32 arg1, arg2, arg3; ++ ++ arg1 = FIELD_GET(GENMASK_ULL(7, 0), val); ++ arg2 = FIELD_GET(GENMASK_ULL(15, 8), val); ++ arg3 = FIELD_GET(GENMASK_ULL(23, 16), val); ++ ++ mt7915_dbg_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY), arg1, arg2, arg3, false); ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_wa_query, NULL, mt7915_wa_query, ++ "0x%llx\n"); ++/* set wa debug level ++ usage: ++ echo 0x[arg] > fw_wa_debug ++ bit0 : DEBUG_WIFI_TX ++ bit1 : DEBUG_CMD_EVENT ++ bit2 : DEBUG_RED ++ bit3 : DEBUG_WARN ++ bit4 : DEBUG_WIFI_RX ++ bit5 : DEBUG_TIME_STAMP ++ bit6 : DEBUG_TX_FREE_DONE_EVENT ++ bit12 : DEBUG_WIFI_TXD */ ++static int ++mt7915_wa_debug(void *data, u64 val) ++{ ++ struct mt7915_dev *dev = data; ++ u32 arg; ++ ++ arg = FIELD_GET(GENMASK_ULL(15, 0), val); ++ ++ mt7915_dbg_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(DEBUG), arg, 0, 0, false); ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_wa_debug, NULL, mt7915_wa_debug, ++ "0x%llx\n"); ++ ++static int mt7915_dump_version(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ struct mt76_dev *mdev = NULL; ++ int i; ++ ++ seq_printf(s, "Version: 2.2.24.3\n"); ++ ++ if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) ++ return 0; ++ ++ mdev = &dev->mt76; ++ seq_printf(s, "Rom Patch Build Time: %.16s\n", mdev->patch_hdr->build_date); ++ seq_printf(s, "WM Patch Build Time: %.16s\n", mdev->wm_hdr->build_date); ++ seq_printf(s, "WA Patch Build Time: %.16s\n", mdev->wa_hdr->build_date); ++ ++ for (i = 0; i < ADIE_MAX_CNT; i++) { ++ seq_printf(s, "adie[%d]: id=0x%04x version=0x%04x\n", ++ i, dev->adie[i].id, dev->adie[i].version); ++ } ++ return 0; ++} ++ ++static void mt7915_show_lp_history(struct seq_file *s, bool fgIsExp) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 macVal, gpr_log_idx, oldest_idx; ++ u32 idx, i; ++ ++ if (!fgIsExp) { ++ /* disable LP recored */ ++ macVal = mt76_rr(dev, 0x89050200); ++ macVal &= (~0x1); ++ mt76_wr(dev, 0x89050200, macVal); ++ udelay(100); ++ } ++ ++ macVal = mt76_rr(dev, 0x89050200); ++ gpr_log_idx = ((macVal >> 16) & 0x1f); ++ oldest_idx = gpr_log_idx + 2; ++ ++ seq_printf(s, " lp history (from old to new):\n"); ++ for (i = 0; i < 16; i++) { ++ idx = ((oldest_idx + 2*i + 1)%32); ++ macVal = mt76_rr(dev, (0x89050204 + idx*4)); ++ seq_printf(s, " %d: 0x%x\n", i, macVal); ++ } ++ ++ if (!fgIsExp) { ++ /* enable LP recored */ ++ macVal = mt76_rr(dev, 0x89050200); ++ macVal |= 0x1; ++ mt76_wr(dev, 0x89050200, macVal); ++ } ++} ++ ++static void mt7915_show_irq_history(struct seq_file *s) ++{ ++#define SYSIRQ_INTERRUPT_HISTORY_NUM 10 ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 macVal, i, start, idx; ++ u8 ucIrqDisIdx, ucIrqResIdx; ++ u32 irq_dis_time[SYSIRQ_INTERRUPT_HISTORY_NUM], irq_dis_lp[SYSIRQ_INTERRUPT_HISTORY_NUM]; ++ u32 irq_res_time[SYSIRQ_INTERRUPT_HISTORY_NUM], irq_res_lp[SYSIRQ_INTERRUPT_HISTORY_NUM]; ++ u32 irq_idx_addr, irq_dis_addr, irq_res_addr; ++ ++ switch (mt76_chip(&dev->mt76)) { ++ case 0x7915: ++ irq_idx_addr = 0x2170BC; ++ irq_dis_addr = 0x2170B8; ++ irq_res_addr = 0x2170B4; ++ break; ++ case 0x7981: ++ irq_idx_addr = 0x02205138; ++ irq_dis_addr = 0x02205140; ++ irq_res_addr = 0x0220513C; ++ break; ++ case 0x7906: ++ irq_idx_addr = 0x02205288; ++ irq_dis_addr = 0x02205290; ++ irq_res_addr = 0x0220528C; ++ break; ++ case 0x7986: ++ default: ++ irq_idx_addr = 0x022051C0; ++ irq_dis_addr = 0x022051C8; ++ irq_res_addr = 0x022051C4; ++ break; ++ } ++ ++ macVal = mt76_rr(dev, irq_idx_addr); ++ ucIrqResIdx = (macVal & 0xff); ++ ucIrqDisIdx = ((macVal >> 8) & 0xff); ++ ++ seq_printf(s, "\n\n\n Irq Idx (Dis=%d Res=%d):\n", ++ ucIrqDisIdx, ucIrqResIdx); ++ ++ start = mt76_rr(dev, irq_dis_addr); ++ for (i = 0; i < SYSIRQ_INTERRUPT_HISTORY_NUM; i++) { ++ macVal = mt76_rr(dev, (start + (i * 8))); ++ irq_dis_time[i] = macVal; ++ macVal = mt76_rr(dev, (start + (i * 8) + 4)); ++ irq_dis_lp[i] = macVal; ++ } ++ ++ start = mt76_rr(dev, irq_res_addr); ++ for (i = 0; i < SYSIRQ_INTERRUPT_HISTORY_NUM; i++) { ++ macVal = mt76_rr(dev, (start + (i * 8))); ++ irq_res_time[i] = macVal; ++ macVal = mt76_rr(dev, (start + (i * 8) + 4)); ++ irq_res_lp[i] = macVal; ++ } ++ ++ seq_printf(s, "\n Dis Irq history (from old to new):\n"); ++ for (i = 0; i < SYSIRQ_INTERRUPT_HISTORY_NUM; i++) { ++ idx = (i + ucIrqDisIdx) % SYSIRQ_INTERRUPT_HISTORY_NUM; ++ seq_printf(s, " [%d].LP = 0x%x time=%u\n", ++ idx, irq_dis_lp[idx], irq_dis_time[idx]); ++ } ++ ++ seq_printf(s, "\n Restore Irq history (from old to new):\n"); ++ for (i = 0; i < SYSIRQ_INTERRUPT_HISTORY_NUM; i++) { ++ idx = (i + ucIrqResIdx) % SYSIRQ_INTERRUPT_HISTORY_NUM; ++ seq_printf(s, " [%d].LP = 0x%x time=%u\n", ++ idx, irq_res_lp[idx], irq_res_time[idx]); ++ } ++} ++ ++static void MemSectionRead(struct mt7915_dev *dev, char *buf, u32 length, u32 addr) ++{ ++ int idx = 0; ++ u32 *ptr =(u32 *)buf; ++ ++ while (idx < length) { ++ *ptr = mt76_rr(dev, (addr + idx)); ++ idx += 4; ++ ptr++; ++ } ++} ++ ++static int MemReadOneByte(struct mt7915_dev *dev, u32 addr) ++{ ++ u32 val, tmpval; ++ ++ val = mt76_rr(dev, (addr & ~(0x3))); ++ tmpval = (val >> (8 * (addr & (0x3)))) & 0xff; ++ return tmpval; ++} ++ ++static void mt7915_show_msg_trace(struct seq_file *s) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ struct cos_msg_trace_t *msg_trace = NULL; ++ u32 ptr_addr, length; ++ u32 idx = 0, cnt = 0; ++ u32 msg_history_num, num_addr; ++ u32 trace_ptr_addr, trace_num_addr; ++ ++ switch (mt76_chip(&dev->mt76)) { ++ case 0x7915: ++ trace_ptr_addr = 0x41F054; ++ trace_num_addr = 0x41F058; ++ num_addr = mt76_rr(dev, 0x41F05C); ++ break; ++ case 0x7981: ++ trace_ptr_addr = 0x02205100; ++ trace_num_addr = 0x02205104; ++ break; ++ case 0x7906: ++ trace_ptr_addr = 0x02205250; ++ trace_num_addr = 0x02205254; ++ break; ++ case 0x7986: ++ default: ++ trace_ptr_addr = 0x02205188; ++ trace_num_addr = 0x0220518C; ++ break; ++ } ++ ++ ++ ++ ptr_addr = mt76_rr(dev, trace_ptr_addr); ++ msg_history_num = mt76_rr(dev, trace_num_addr); ++ idx = (is_mt7915(&dev->mt76) ? MemReadOneByte(dev, num_addr) : (msg_history_num >> 8)) & 0xff; ++ msg_history_num = msg_history_num & 0xff; ++ msg_trace = kzalloc(msg_history_num * sizeof(struct cos_msg_trace_t), GFP_KERNEL); ++ ++ if (!msg_trace) { ++ seq_printf(s, "can not allocate cmd msg_trace\n"); ++ return; ++ } ++ ++ if (idx >= msg_history_num) { ++ kfree(msg_trace); ++ return; ++ } ++ ++ length = msg_history_num * sizeof(struct cos_msg_trace_t); ++ MemSectionRead(dev, (char *)&(msg_trace[0]), length, ptr_addr); ++ seq_printf(s, "\n"); ++ seq_printf(s, " msg trace:\n"); ++ seq_printf(s, " format: t_id=task_id/task_prempt_cnt/msg_read_idx\n"); ++ ++ while (1) { ++ seq_printf(s, " (m_%d)t_id=%x/%d/%d, m_id=%d, ts_en=%u, ts_de = %u, ts_fin=%u, wait=%d, exe=%d\n", ++ idx, ++ msg_trace[idx].dest_id, ++ msg_trace[idx].pcount, ++ msg_trace[idx].qread, ++ msg_trace[idx].msg_id, ++ msg_trace[idx].ts_enq, ++ msg_trace[idx].ts_deq, ++ msg_trace[idx].ts_finshq, ++ (msg_trace[idx].ts_deq - msg_trace[idx].ts_enq), ++ (msg_trace[idx].ts_finshq - msg_trace[idx].ts_deq)); ++ ++ if (++idx >= msg_history_num) ++ idx = 0; ++ ++ if (++cnt >= msg_history_num) ++ break; ++ } ++ if (msg_trace) ++ kfree(msg_trace); ++} ++ ++static int mt7915_show_assert_line(struct seq_file *s) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ char *msg; ++ u32 addr; ++ u32 macVal = 0; ++ char *ptr; ++ char idx; ++ ++ msg = kmalloc(256, GFP_KERNEL); ++ if (!msg) ++ return 0; ++ ++ memset(msg, 0, 256); ++ addr = 0x00400000; ++ ptr = msg; ++ for (idx = 0 ; idx < 32; idx++) { ++ macVal = 0; ++ macVal = mt76_rr(dev, addr); ++ memcpy(ptr, &macVal, 4); ++ addr += 4; ++ ptr += 4; ++ } ++ ++ *ptr = 0; ++ seq_printf(s, "\n\n"); ++ seq_printf(s, " Assert line\n"); ++ seq_printf(s, " %s\n", msg); ++ if (msg) ++ kfree(msg); ++ ++ return 0; ++} ++ ++ ++static void mt7915_show_sech_trace(struct seq_file *s) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ struct cos_task_info_struct task_info_g[2]; ++ u32 length, idx; ++ u32 addr, km_total_time; ++ u32 task_info_addr, km_total_time_addr; ++ struct cos_task_type tcb; ++ struct cos_task_type *tcb_ptr; ++ char name[2][15] = { ++ "WIFI ", "WIFI2 " ++ }; ++ ++ switch (mt76_chip(&dev->mt76)) { ++ case 0x7915: ++ task_info_addr = 0x215400; ++ km_total_time_addr = 0x219838; ++ break; ++ case 0x7981: ++ task_info_addr = 0x02202978; ++ km_total_time_addr = 0x0220512C; ++ break; ++ case 0x7906: ++ task_info_addr = 0x02202ACC; ++ km_total_time_addr = 0x0220527C; ++ break; ++ case 0x7986: ++ default: ++ task_info_addr = 0x02202A18; ++ km_total_time_addr = 0x022051B4; ++ break; ++ } ++ ++ length = 2 * sizeof(struct cos_task_info_struct); ++ MemSectionRead(dev, (char *)&(task_info_g[0]), length, task_info_addr); ++ ++ km_total_time = mt76_rr(dev, km_total_time_addr); ++ if (km_total_time == 0) { ++ seq_printf(s, "km_total_time zero!\n"); ++ return; ++ } ++ ++ seq_printf(s, "\n\n\n TASK XTIME RATIO PREMPT CNT\n"); ++ for (idx = 0 ; idx < 2 ; idx++) { ++ addr = task_info_g[idx].task_id; ++ MemSectionRead(dev, (char *)&(tcb), sizeof(struct cos_task_type), addr); ++ ++ length = sizeof(struct cos_task_type); ++ ++ tcb_ptr = &(tcb); ++ ++ if (tcb_ptr) { ++ seq_printf(s, " %s %d %d %d\n", ++ name[idx], ++ tcb_ptr->tc_exe_time, ++ (tcb_ptr->tc_exe_time*100/km_total_time), ++ tcb_ptr->tc_pcount); ++ } ++ } ++ ++} ++ ++static void mt7915_show_prog_trace(struct seq_file *s) ++{ ++#define mt7915_cos_access_ptr(_idx, _member) (is_mt7915(&dev->mt76) ? \ ++ mt7915_cos_program_trace_ptr[_idx]._##_member : \ ++ cos_program_trace_ptr[_idx]._##_member) ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ struct cos_program_trace_t *cos_program_trace_ptr = NULL; ++ struct mt7915_cos_program_trace_t *mt7915_cos_program_trace_ptr = NULL; ++ char *buf; ++ u32 trace_ptr; ++ u32 idx; ++ u32 old_idx; ++ u32 old_idx_addr; ++ u32 prev_idx, diff; ++ u32 prev_time, prev_dest_id, prev_msg_sn; ++ u32 old_time, old_dest_id, old_msg_sn; ++ u32 trace_ptr_addr, trace_idx_addr, trace_num_addr, trace_num; ++ int size; ++ ++ switch (mt76_chip(&dev->mt76)) { ++ case 0x7915: ++ trace_ptr_addr = 0x41F0E0; ++ trace_idx_addr = 0x41F0E8; ++ trace_num_addr = mt76_rr(dev, 0x41F0E4); ++ break; ++ case 0x7981: ++ trace_ptr_addr = 0x022050C4; ++ trace_idx_addr = 0x022050C0; ++ break; ++ case 0x7906: ++ trace_ptr_addr = 0x02205214; ++ trace_idx_addr = 0x02205210; ++ break; ++ case 0x7986: ++ default: ++ trace_ptr_addr = 0x0220514C; ++ trace_idx_addr = 0x02205148; ++ break; ++ } ++ ++ size = is_mt7915(&dev->mt76) ? sizeof(struct mt7915_cos_program_trace_t) : sizeof(struct cos_program_trace_t); ++ trace_num = is_mt7915(&dev->mt76) ? MemReadOneByte(dev, trace_num_addr) & 0xff : 32; ++ buf = kzalloc(trace_num * size, GFP_KERNEL); ++ if (!buf) { ++ seq_printf(s, "can not allocate cos_program_trace_ptr memory\n"); ++ return; ++ } ++ ++ trace_ptr = mt76_rr(dev, trace_ptr_addr); ++ old_idx_addr = mt76_rr(dev, trace_idx_addr); ++ old_idx = (is_mt7915(&dev->mt76) ? MemReadOneByte(dev, old_idx_addr) : (old_idx_addr >> 8)) & 0xff; ++ ++ MemSectionRead(dev, &buf[0], trace_num * size, trace_ptr); ++ ++ if (is_mt7915(&dev->mt76)) ++ mt7915_cos_program_trace_ptr = (struct mt7915_cos_program_trace_t *)buf; ++ else ++ cos_program_trace_ptr = (struct cos_program_trace_t *)buf; ++ ++ seq_printf(s, "\n"); ++ seq_printf(s, " program trace:\n"); ++ for (idx = 0 ; idx < trace_num ; idx++) { ++ prev_idx = ((old_idx + trace_num - 1) % trace_num); ++ ++ prev_time = mt7915_cos_access_ptr(prev_idx, ts_gpt2); ++ old_time = mt7915_cos_access_ptr(old_idx, ts_gpt2); ++ prev_dest_id = mt7915_cos_access_ptr(prev_idx, dest_id); ++ old_dest_id = mt7915_cos_access_ptr(old_idx, dest_id); ++ prev_msg_sn = mt7915_cos_access_ptr(prev_idx, msg_sn); ++ old_msg_sn = mt7915_cos_access_ptr(old_idx, msg_sn); ++ ++ seq_printf(s, " (p_%d)t_id=%x/%d, m_id=%d, LP=0x%x, name=%s, ts2=%d, ", ++ old_idx, ++ old_dest_id, ++ old_msg_sn, ++ mt7915_cos_access_ptr(old_idx, msg_id), ++ mt7915_cos_access_ptr(old_idx, LP), ++ mt7915_cos_access_ptr(old_idx, name), ++ old_time); ++ ++ /* diff for gpt2 */ ++ ++ diff = 0xFFFFFFFF; ++ ++ if (prev_time) { ++ if ((prev_dest_id == old_dest_id) && (prev_msg_sn == old_msg_sn)) { ++ if (old_time > prev_time) ++ diff = old_time - prev_time; ++ else ++ diff = 0xFFFFFFFF - prev_time + old_time + 1; ++ } ++ } ++ ++ if (diff == 0xFFFFFFFF) ++ seq_printf(s, "diff2=NA, \n"); ++ else ++ seq_printf(s, "diff2=%8d\n", diff); ++ ++ old_idx++; ++ if (old_idx >= trace_num) ++ old_idx = 0; ++ } ++ if (buf) ++ kfree(buf); ++} ++ ++static int mt7915_fw_wm_info_read(struct seq_file *s, void *data) ++{ ++ struct mt7915_dev *dev = dev_get_drvdata(s->private); ++ u32 macVal, g_exp_type, COS_Interrupt_Count; ++ u8 exp_assert_proc_entry_cnt, exp_assert_state, g_irq_history_num; ++ u16 processing_irqx; ++ u32 processing_lisr, Current_Task_Id, Current_Task_Indx; ++ u8 km_irq_info_idx, km_eint_info_idx, km_sched_info_idx, g_sched_history_num; ++ u32 km_sched_trace_ptr, km_irq_trace_ptr, km_total_time; ++ bool fgIsExp = false, fgIsAssert = false; ++ u32 TaskStart[2], TaskEnd[2]; ++ u32 exp_assert_state_addr, g1_exp_counter_addr; ++ u32 g_exp_type_addr, cos_interrupt_count_addr; ++ u32 processing_irqx_addr, processing_lisr_addr; ++ u32 Current_Task_Id_addr, Current_Task_Indx_addr, last_dequeued_msg_id_addr; ++ u32 km_irq_info_idx_addr, km_eint_info_idx_addr, km_sched_info_idx_addr; ++ u32 g_sched_history_num_addr, km_sched_trace_ptr_addr; ++ u32 km_irq_trace_ptr_addr, km_total_time_addr, last_dequeued_msg_id; ++ u32 TaskStart_0, TaskEnd_0, TaskStart_1, TaskEnd_1; ++ u32 t1_base_addr, t2_base_addr, t3_base_addr, t_addr_ofs; ++ u32 cpu_itype_addr, cpu_eva_addr, cpu_ipc_addr, pc_addr; ++ u32 busy_addr, peak_addr; ++ u32 i, t1, t2, t3; ++ u8 idx, exp_type[64]; ++ ++ switch (mt76_chip(&dev->mt76)) { ++ case 0x7915: ++ g_exp_type_addr = 0x21987C; ++ exp_assert_state_addr = 0x219848; ++ g1_exp_counter_addr = 0x219848; ++ cos_interrupt_count_addr = 0x216F94; ++ processing_irqx_addr = 0x216EF8; ++ processing_lisr_addr = 0x2170AC; ++ Current_Task_Id_addr = 0x216F90; ++ Current_Task_Indx_addr = 0x216F9C; ++ last_dequeued_msg_id_addr = 0x216F70; ++ km_irq_info_idx_addr = 0x219820; ++ km_eint_info_idx_addr = 0x219818; ++ km_sched_info_idx_addr = 0x219828; ++ g_sched_history_num_addr = 0x219828; ++ km_sched_trace_ptr_addr = 0x219824; ++ km_irq_trace_ptr_addr = 0x21981C; ++ km_total_time_addr = 0x219838; ++ TaskStart_0 = 0x2195A0; ++ TaskEnd_0 = 0x21959C; ++ TaskStart_1 = 0x219680; ++ TaskEnd_1 = 0x21967C; ++ t1_base_addr = 0x219558; ++ t2_base_addr = 0x219554; ++ t3_base_addr = 0x219560; ++ cpu_itype_addr = 0x41F088; ++ cpu_eva_addr = 0x41F08C; ++ cpu_ipc_addr = 0x41F094; ++ pc_addr = 0x7C060204; ++ busy_addr = 0x41F030; ++ peak_addr = 0x41F034; ++ break; ++ case 0x7981: ++ g_exp_type_addr = 0x02205054; ++ exp_assert_state_addr = 0x02204AC0; ++ g1_exp_counter_addr = 0x02204F68; ++ cos_interrupt_count_addr = 0x02204FFC; ++ processing_irqx_addr = 0x02204E30; ++ processing_lisr_addr = 0x02204F7C; ++ Current_Task_Id_addr = 0x02204F18; ++ Current_Task_Indx_addr = 0x02204F18; ++ last_dequeued_msg_id_addr = 0x02204E94; ++ km_irq_info_idx_addr = 0x02205114; ++ km_eint_info_idx_addr = 0x0220510C; ++ km_sched_info_idx_addr = 0x0220511C; ++ g_sched_history_num_addr = 0x0220511C; ++ km_sched_trace_ptr_addr = 0x02205118; ++ km_irq_trace_ptr_addr = 0x02205110; ++ km_total_time_addr = 0x0220512C; ++ TaskStart_0 = 0x022028B4; ++ TaskEnd_0 = 0x022028C0; ++ TaskStart_1 = 0x02202A38; ++ TaskEnd_1 = 0x02202934; ++ t1_base_addr = 0x02202718; ++ t2_base_addr = 0x0220287C; ++ t3_base_addr = 0x02202884; ++ cpu_itype_addr = 0x02205058; ++ cpu_eva_addr = 0x02205060; ++ cpu_ipc_addr = 0x0220505C; ++ pc_addr = 0x7C060204; ++ busy_addr = 0x7C053B20; ++ peak_addr = 0x7C053B24; ++ break; ++ case 0x7906: ++ g_exp_type_addr = 0x022051A4; ++ exp_assert_state_addr = 0x02204C14; ++ g1_exp_counter_addr = 0x022050BC; ++ cos_interrupt_count_addr = 0x022001AC; ++ processing_irqx_addr = 0x02204F84; ++ processing_lisr_addr = 0x022050D0; ++ Current_Task_Id_addr = 0x0220406C; ++ Current_Task_Indx_addr = 0x0220500C; ++ last_dequeued_msg_id_addr = 0x02204FE8; ++ km_irq_info_idx_addr = 0x02205264; ++ km_eint_info_idx_addr = 0x0220525C; ++ km_sched_info_idx_addr = 0x0220526C; ++ g_sched_history_num_addr = 0x0220516C; ++ km_sched_trace_ptr_addr = 0x02205268; ++ km_irq_trace_ptr_addr = 0x02205260; ++ km_total_time_addr = 0x0220517C; ++ TaskStart_0 = 0x022028C8; ++ TaskEnd_0 = 0x022028C4; ++ TaskStart_1 = 0x02202A38; ++ TaskEnd_1 = 0x02202934; ++ t1_base_addr = 0x0220286C; ++ t2_base_addr = 0x02202870; ++ t3_base_addr = 0x02202878; ++ cpu_itype_addr = 0x022051A8; ++ cpu_eva_addr = 0x022051B0; ++ cpu_ipc_addr = 0x022051AC; ++ pc_addr = 0x7C060204; ++ busy_addr = 0x7C053B20; ++ peak_addr = 0x7C053B24; ++ break; ++ case 0x7986: ++ default: ++ g_exp_type_addr = 0x022050DC; ++ exp_assert_state_addr = 0x02204B54; ++ g1_exp_counter_addr = 0x02204FFC; ++ cos_interrupt_count_addr = 0x022001AC; ++ processing_irqx_addr = 0x02204EC4; ++ processing_lisr_addr = 0x02205010; ++ Current_Task_Id_addr = 0x02204FAC; ++ Current_Task_Indx_addr = 0x02204F4C; ++ last_dequeued_msg_id_addr = 0x02204F28; ++ km_irq_info_idx_addr = 0x0220519C; ++ km_eint_info_idx_addr = 0x02205194; ++ km_sched_info_idx_addr = 0x022051A4; ++ g_sched_history_num_addr = 0x022051A4; ++ km_sched_trace_ptr_addr = 0x022051A0; ++ km_irq_trace_ptr_addr = 0x02205198; ++ km_total_time_addr = 0x022051B4; ++ TaskStart_0 = 0x02202814; ++ TaskEnd_0 = 0x02202810; ++ TaskStart_1 = 0x02202984; ++ TaskEnd_1 = 0x02202980; ++ t1_base_addr = 0x022027B8; ++ t2_base_addr = 0x022027BC; ++ t3_base_addr = 0x022027C4; ++ cpu_itype_addr = 0x022050E0; ++ cpu_eva_addr = 0x022050E8; ++ cpu_ipc_addr = 0x022050E4; ++ pc_addr = 0x7C060204; ++ busy_addr = 0x7C053B20; ++ peak_addr = 0x7C053B24; ++ break; ++ } ++ ++ macVal = mt76_rr(dev, exp_assert_state_addr); ++ exp_assert_state = (macVal & 0xff); ++ ++ macVal = mt76_rr(dev, g1_exp_counter_addr); ++ exp_assert_proc_entry_cnt = (is_mt7915(&dev->mt76) ? (macVal >> 8) : macVal) & 0xff; ++ ++ macVal = mt76_rr(dev, g_exp_type_addr); ++ g_exp_type = is_mt7915(&dev->mt76) ? ((macVal >> 8) & 0xff) : macVal; ++ ++ COS_Interrupt_Count = mt76_rr(dev, cos_interrupt_count_addr); ++ ++ macVal = mt76_rr(dev, processing_irqx_addr); ++ processing_irqx = (is_mt7915(&dev->mt76) ? (macVal >> 16) : macVal) & 0xffff; ++ ++ processing_lisr = mt76_rr(dev, processing_lisr_addr); ++ Current_Task_Id = mt76_rr(dev, Current_Task_Id_addr); ++ Current_Task_Indx = mt76_rr(dev, Current_Task_Indx_addr); ++ last_dequeued_msg_id = mt76_rr(dev, last_dequeued_msg_id_addr); ++ ++ macVal = mt76_rr(dev, km_eint_info_idx_addr); ++ km_eint_info_idx = (is_mt7915(&dev->mt76) ? macVal : (macVal >> 8)) & 0xff; ++ ++ macVal = mt76_rr(dev, g_sched_history_num_addr); ++ g_sched_history_num = (is_mt7915(&dev->mt76) ? (macVal >> 8) : macVal) & 0xff; ++ km_sched_info_idx = (is_mt7915(&dev->mt76) ? macVal : (macVal >> 8)) & 0xff; ++ ++ km_sched_trace_ptr = mt76_rr(dev, km_sched_trace_ptr_addr); ++ ++ macVal = mt76_rr(dev, km_irq_info_idx_addr); ++ g_irq_history_num = (is_mt7915(&dev->mt76) ? (macVal >> 8) : macVal) & 0xff; ++ km_irq_info_idx = (is_mt7915(&dev->mt76) ? macVal : (macVal >> 16)) & 0xff; ++ ++ km_irq_trace_ptr = mt76_rr(dev, km_irq_trace_ptr_addr); ++ km_total_time = mt76_rr(dev, km_total_time_addr); ++ ++ TaskStart[0] = mt76_rr(dev, TaskStart_0); ++ TaskEnd[0] = mt76_rr(dev, TaskEnd_0); ++ TaskStart[1] = mt76_rr(dev, TaskStart_1); ++ TaskEnd[1] = mt76_rr(dev, TaskEnd_1); ++ ++ seq_printf(s, "================FW DBG INFO===================\n"); ++ seq_printf(s, " exp_assert_proc_entry_cnt = 0x%x\n", ++ exp_assert_proc_entry_cnt); ++ seq_printf(s, " exp_assert_state = 0x%x\n", ++ exp_assert_state); ++ ++ if (exp_assert_proc_entry_cnt == 0) { ++ snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Normal"); ++ } else if (exp_assert_proc_entry_cnt == 1 && exp_assert_state > 1 && g_exp_type == 5) { ++ snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Assert"); ++ fgIsExp = true; ++ fgIsAssert = true; ++ } else if (exp_assert_proc_entry_cnt == 1 && exp_assert_state > 1) { ++ snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Exception"); ++ fgIsExp = true; ++ } else if (exp_assert_proc_entry_cnt > 1) { ++ snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Exception re-entry"); ++ fgIsExp = true; ++ } else { ++ snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Unknown?"); ++ } ++ ++ seq_printf(s, " COS_Interrupt_Count = 0x%x\n", COS_Interrupt_Count); ++ seq_printf(s, " processing_irqx = 0x%x\n", processing_irqx); ++ seq_printf(s, " processing_lisr = 0x%x\n", processing_lisr); ++ seq_printf(s, " Current_Task_Id = 0x%x\n", Current_Task_Id); ++ seq_printf(s, " Current_Task_Indx = 0x%x\n", Current_Task_Indx); ++ seq_printf(s, " last_dequeued_msg_id = %d\n", last_dequeued_msg_id); ++ ++ seq_printf(s, " km_irq_info_idx = 0x%x\n", km_irq_info_idx); ++ seq_printf(s, " km_eint_info_idx = 0x%x\n", km_eint_info_idx); ++ seq_printf(s, " km_sched_info_idx = 0x%x\n", km_sched_info_idx); ++ seq_printf(s, " g_sched_history_num = %d\n", g_sched_history_num); ++ seq_printf(s, " km_sched_trace_ptr = 0x%x\n", km_sched_trace_ptr); ++ ++ if (fgIsExp) { ++ seq_printf(s, "\n <1>print sched trace\n"); ++ if (g_sched_history_num > 60) ++ g_sched_history_num = 60; ++ ++ idx = km_sched_info_idx; ++ for (i = 0 ; i < g_sched_history_num ; i++) { ++ t1 = mt76_rr(dev, (km_sched_trace_ptr+(idx*12))); ++ t2 = mt76_rr(dev, (km_sched_trace_ptr+(idx*12)+4)); ++ t3 = mt76_rr(dev, (km_sched_trace_ptr+(idx*12)+8)); ++ seq_printf(s, " (sched_info_%d)sched_t=0x%x, sched_start=%d, PC=0x%x\n", ++ idx, t1, t2, t3); ++ idx++; ++ if (idx >= g_sched_history_num) ++ idx = 0; ++ } ++ ++ seq_printf(s, "\n <2>print irq trace\n"); ++ if (g_irq_history_num > 60) ++ g_irq_history_num = 60; ++ ++ idx = km_irq_info_idx; ++ for (i = 0 ; i < g_irq_history_num ; i++) { ++ t1 = mt76_rr(dev, (km_irq_trace_ptr+(idx*16))); ++ t2 = mt76_rr(dev, (km_irq_trace_ptr+(idx*16) + 4)); ++ seq_printf(s, " (irq_info_%d)irq_t=%x, sched_start=%d\n", ++ idx, t1, t2); ++ idx++; ++ if (idx >= g_irq_history_num) ++ idx = 0; ++ } ++ } ++ ++ seq_printf(s, "\n <3>task q_id.read q_id.write\n"); ++ seq_printf(s, " (WIFI )1 0x%x 0x%x\n", TaskStart[0], TaskEnd[0]); ++ seq_printf(s, " (WIFI2 )2 0x%x 0x%x\n", TaskStart[1], TaskEnd[1]); ++ seq_printf(s, "\n <4>TASK STACK INFO (size in byte)\n"); ++ seq_printf(s, " TASK START END SIZE PEAK INTEGRITY\n"); ++ ++ t_addr_ofs = is_mt7915(&dev->mt76) ? 224 : 368; ++ for (i = 0 ; i < 2 ; i++) { ++ t1 = mt76_rr(dev, t1_base_addr + (i*t_addr_ofs)); ++ t2 = mt76_rr(dev, t2_base_addr + (i*t_addr_ofs)); ++ t3 = mt76_rr(dev, t3_base_addr + (i*t_addr_ofs)); ++ ++ seq_printf(s, " %s 0x%x 0x%x %d\n", ++ i == 0 ? "WIFI" : "WIFI2", t1, t2, t3); ++ } ++ ++ seq_printf(s, "\n <5>fw state\n"); ++ seq_printf(s, " %s\n", exp_type); ++ if (COS_Interrupt_Count > 0) ++ seq_printf(s, " FW in Interrupt CIRQ index (0x%x) CIRQ handler(0x%x)\n" ++ , processing_irqx, processing_lisr); ++ else { ++ if (Current_Task_Id == 0 && Current_Task_Indx == 3) ++ seq_printf(s, " FW in IDLE\n"); ++ ++ if (Current_Task_Id != 0 && Current_Task_Indx != 3) ++ seq_printf(s, " FW in Task , Task id(0x%x) Task index(0x%x)\n", ++ Current_Task_Id, Current_Task_Indx); ++ } ++ ++ macVal = mt76_rr(dev, is_mt7915(&dev->mt76) ? 0x41F080 : g1_exp_counter_addr); ++ seq_printf(s, " EXCP_CNT = 0x%x\n", macVal); ++ ++ seq_printf(s, " EXCP_TYPE = 0x%x\n", g_exp_type); ++ seq_printf(s, " CPU_ITYPE = 0x%x\n", mt76_rr(dev, cpu_itype_addr)); ++ seq_printf(s, " CPU_EVA = 0x%x\n", mt76_rr(dev, cpu_eva_addr)); ++ seq_printf(s, " CPU_IPC = 0x%x\n", mt76_rr(dev, cpu_ipc_addr)); ++ seq_printf(s, " PC = 0x%x\n\n\n", mt76_rr(dev, pc_addr)); ++ ++ mt7915_show_lp_history(s, fgIsExp); ++ mt7915_show_irq_history(s); ++ ++ seq_printf(s, "\n\n cpu utility\n"); ++ seq_printf(s, " Busy:%d%% Peak:%d%%\n\n", ++ mt76_rr(dev, busy_addr), mt76_rr(dev, peak_addr)); ++ ++ mt7915_show_msg_trace(s); ++ mt7915_show_sech_trace(s); ++ mt7915_show_prog_trace(s); ++ ++ if (fgIsAssert) ++ mt7915_show_assert_line(s); ++ ++ seq_printf(s, "============================================\n"); ++ return 0; ++} ++ ++int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ u32 device_id = (dev->mt76.rev) >> 16; ++ int i = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(dbg_reg_s); i++) { ++ if (device_id == dbg_reg_s[i].id) { ++ dev->dbg_reg = &dbg_reg_s[i]; ++ break; ++ } ++ } ++ ++ mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, 0); ++ ++ debugfs_create_file("fw_debug_module", 0600, dir, dev, ++ &fops_fw_debug_module); ++ debugfs_create_file("fw_debug_level", 0600, dir, dev, ++ &fops_fw_debug_level); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "sta_info", dir, ++ mt7915_sta_info); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir, ++ mt7915_wtbl_read); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "uwtbl_info", dir, ++ mt7915_uwtbl_read); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir, ++ mt7915_trinfo_read); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "drr_info", dir, ++ mt7915_drr_info); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "ple_info", dir, ++ mt7915_pleinfo_read); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "pse_info", dir, ++ mt7915_pseinfo_read); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "mib_info0", dir, ++ mt7915_mibinfo_band0); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "mib_info1", dir, ++ mt7915_mibinfo_band1); ++ ++ debugfs_create_u32("token_idx", 0600, dir, &dev->dbg.token_idx); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "token", dir, ++ mt7915_token_read); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "token_txd", dir, ++ mt7915_token_txd_read); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "amsdu_info", dir, ++ mt7915_amsduinfo_read); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "agg_info0", dir, ++ mt7915_agginfo_read_band0); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "agg_info1", dir, ++ mt7915_agginfo_read_band1); ++ ++ debugfs_create_file("tx_amsdu", 0600, dir, dev, &fops_tx_amsdu); ++ ++ debugfs_create_file("fw_wa_query", 0600, dir, dev, &fops_wa_query); ++ debugfs_create_file("fw_wa_set", 0600, dir, dev, &fops_wa_set); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "fw_version", dir, ++ mt7915_dump_version); ++ debugfs_create_file("fw_wa_debug", 0600, dir, dev, &fops_wa_debug); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "fw_wm_info", dir, ++ mt7915_fw_wm_info_read); ++ ++ debugfs_create_file("red_en", 0600, dir, dev, ++ &fops_red_en); ++ debugfs_create_file("red_show_sta", 0600, dir, dev, ++ &fops_red_show_sta); ++ debugfs_create_file("red_target_dly", 0600, dir, dev, ++ &fops_red_target_dly); ++ ++ debugfs_create_file("txpower_level", 0400, dir, dev, ++ &fops_txpower_level); ++ ++ debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable); ++ ++ return 0; ++} ++#endif +diff --git a/mt7915/mtk_mcu.c b/mt7915/mtk_mcu.c +new file mode 100644 +index 0000000..143dae2 +--- /dev/null ++++ b/mt7915/mtk_mcu.c +@@ -0,0 +1,51 @@ ++#include ++#include ++#include ++#include "mt7915.h" ++#include "mcu.h" ++#include "mac.h" ++ ++int mt7915_mcu_set_txpower_level(struct mt7915_phy *phy, u8 drop_level) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct mt7915_sku_val { ++ u8 format_id; ++ u8 val; ++ u8 band; ++ u8 _rsv; ++ } __packed req = { ++ .format_id = 1, ++ .band = phy->mt76->band_idx, ++ .val = !!drop_level, ++ }; ++ int ret; ++ ++ ret = mt76_mcu_send_msg(&dev->mt76, ++ MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, ++ sizeof(req), true); ++ if (ret) ++ return ret; ++ ++ req.format_id = 2; ++ if ((drop_level > 90 && drop_level < 100) || !drop_level) ++ req.val = 0; ++ else if (drop_level > 60 && drop_level <= 90) ++ /* reduce Pwr for 1 dB. */ ++ req.val = 2; ++ else if (drop_level > 30 && drop_level <= 60) ++ /* reduce Pwr for 3 dB. */ ++ req.val = 6; ++ else if (drop_level > 15 && drop_level <= 30) ++ /* reduce Pwr for 6 dB. */ ++ req.val = 12; ++ else if (drop_level > 9 && drop_level <= 15) ++ /* reduce Pwr for 9 dB. */ ++ req.val = 18; ++ else if (drop_level > 0 && drop_level <= 9) ++ /* reduce Pwr for 12 dB. */ ++ req.val = 24; ++ ++ return mt76_mcu_send_msg(&dev->mt76, ++ MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, ++ sizeof(req), true); ++} +diff --git a/mt7915/soc.c b/mt7915/soc.c +index bb3468a..b941a49 100644 +--- a/mt7915/soc.c ++++ b/mt7915/soc.c +@@ -360,6 +360,13 @@ static int mt798x_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) + *adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) | + (MT_ADIE_CHIP_ID_MASK & adie_ext); + ++#ifdef MTK_DEBUG ++ dev->adie[ADIE0].id = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main); ++ dev->adie[ADIE0].version = FIELD_GET(MT_ADIE_VERSION_MASK, adie_main); ++ dev->adie[ADIE1].id = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_ext); ++ dev->adie[ADIE1].version = FIELD_GET(MT_ADIE_VERSION_MASK, adie_ext); ++#endif ++ + out: + mt76_wmac_spi_unlock(dev); + +diff --git a/tools/fwlog.c b/tools/fwlog.c +index e5d4a10..3d51d9e 100644 +--- a/tools/fwlog.c ++++ b/tools/fwlog.c +@@ -26,7 +26,7 @@ static const char *debugfs_path(const char *phyname, const char *file) + return path; + } + +-static int mt76_set_fwlog_en(const char *phyname, bool en) ++static int mt76_set_fwlog_en(const char *phyname, bool en, char *val) + { + FILE *f = fopen(debugfs_path(phyname, "fw_debug_bin"), "w"); + +@@ -35,7 +35,13 @@ static int mt76_set_fwlog_en(const char *phyname, bool en) + return 1; + } + +- fprintf(f, "7"); ++ if (en && val) ++ fprintf(f, "%s", val); ++ else if (en) ++ fprintf(f, "7"); ++ else ++ fprintf(f, "0"); ++ + fclose(f); + + return 0; +@@ -76,6 +82,7 @@ static void handle_signal(int sig) + + int mt76_fwlog(const char *phyname, int argc, char **argv) + { ++#define BUF_SIZE 1504 + struct sockaddr_in local = { + .sin_family = AF_INET, + .sin_addr.s_addr = INADDR_ANY, +@@ -84,9 +91,10 @@ int mt76_fwlog(const char *phyname, int argc, char **argv) + .sin_family = AF_INET, + .sin_port = htons(55688), + }; +- char buf[1504]; ++ char *buf = calloc(BUF_SIZE, sizeof(char)); ++ FILE *logfile = NULL; + int ret = 0; +- int yes = 1; ++ /* int yes = 1; */ + int s, fd; + + if (argc < 1) { +@@ -99,19 +107,28 @@ int mt76_fwlog(const char *phyname, int argc, char **argv) + return 1; + } + ++ if (argc == 3) { ++ fprintf(stdout, "start logging to file %s\n", argv[2]); ++ logfile = fopen(argv[2], "wb"); ++ if (!logfile) { ++ perror("fopen"); ++ return 1; ++ } ++ } ++ + s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (s < 0) { + perror("socket"); + return 1; + } + +- setsockopt(s, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes)); ++ /* setsockopt(s, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes)); */ + if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0) { + perror("bind"); + return 1; + } + +- if (mt76_set_fwlog_en(phyname, true)) ++ if (mt76_set_fwlog_en(phyname, true, argv[1])) + return 1; + + fd = open(debugfs_path(phyname, "fwlog_data"), O_RDONLY); +@@ -145,8 +162,8 @@ int mt76_fwlog(const char *phyname, int argc, char **argv) + if (!r) + continue; + +- if (len > sizeof(buf)) { +- fprintf(stderr, "Length error: %d > %d\n", len, (int)sizeof(buf)); ++ if (len > BUF_SIZE) { ++ fprintf(stderr, "Length error: %d > %d\n", len, BUF_SIZE); + ret = 1; + break; + } +@@ -164,14 +181,19 @@ int mt76_fwlog(const char *phyname, int argc, char **argv) + break; + } + +- /* send buf */ +- sendto(s, buf, len, 0, (struct sockaddr *)&remote, sizeof(remote)); ++ if (logfile) ++ fwrite(buf, 1, len, logfile); ++ else ++ /* send buf */ ++ sendto(s, buf, len, 0, (struct sockaddr *)&remote, sizeof(remote)); + } + + close(fd); + + out: +- mt76_set_fwlog_en(phyname, false); ++ mt76_set_fwlog_en(phyname, false, NULL); ++ free(buf); ++ fclose(logfile); + + return ret; + } +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1001-wifi-mt76-mt7915-csi-implement-csi-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1001-wifi-mt76-mt7915-csi-implement-csi-support.patch new file mode 100644 index 000000000..75db3ee6e --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1001-wifi-mt76-mt7915-csi-implement-csi-support.patch @@ -0,0 +1,1092 @@ +From b50df1502bddba9963eadba8d69e6b95a9b87337 Mon Sep 17 00:00:00 2001 +From: Bo Jiao +Date: Mon, 6 Jun 2022 20:13:02 +0800 +Subject: [PATCH] wifi: mt76: mt7915: csi: implement csi support + +--- + mt76_connac_mcu.h | 2 + + mt7915/Makefile | 4 +- + mt7915/init.c | 38 ++++ + mt7915/main.c | 4 + + mt7915/mcu.c | 203 ++++++++++++++++++++ + mt7915/mcu.h | 74 ++++++++ + mt7915/mt7915.h | 60 ++++++ + mt7915/vendor.c | 470 ++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/vendor.h | 63 +++++++ + 9 files changed, 916 insertions(+), 2 deletions(-) + create mode 100644 mt7915/vendor.c + create mode 100644 mt7915/vendor.h + +diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h +index a8690cd..cda7559 100644 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1029,6 +1029,7 @@ enum { + MCU_EXT_EVENT_WA_TX_STAT = 0x74, + MCU_EXT_EVENT_BCC_NOTIFY = 0x75, + MCU_EXT_EVENT_MURU_CTRL = 0x9f, ++ MCU_EXT_EVENT_CSI_REPORT = 0xc2, + }; + + /* unified event table */ +@@ -1243,6 +1244,7 @@ enum { + MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, + MCU_EXT_CMD_PHY_STAT_INFO = 0xad, + MCU_EXT_CMD_SET_QOS_MAP = 0xb4, ++ MCU_EXT_CMD_CSI_CTRL = 0xc2, + }; + + enum { +diff --git a/mt7915/Makefile b/mt7915/Makefile +index fd71141..65129b4 100644 +--- a/mt7915/Makefile ++++ b/mt7915/Makefile +@@ -1,10 +1,10 @@ + # SPDX-License-Identifier: ISC + +-EXTRA_CFLAGS += -DCONFIG_MT76_LEDS ++EXTRA_CFLAGS += -DCONFIG_MT76_LEDS -DCONFIG_MTK_VENDOR + obj-$(CONFIG_MT7915E) += mt7915e.o + + mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ +- debugfs.o mmio.o mtk_debugfs.o mtk_mcu.o ++ debugfs.o mmio.o mtk_debugfs.o mtk_mcu.o vendor.o + + mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o + mt7915e-$(CONFIG_MT798X_WMAC) += soc.o +diff --git a/mt7915/init.c b/mt7915/init.c +index 19a68c5..c504ebf 100644 +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -697,6 +697,12 @@ mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy) + /* init wiphy according to mphy and phy */ + mt7915_init_wiphy(phy); + ++#ifdef CONFIG_MTK_VENDOR ++ INIT_LIST_HEAD(&phy->csi.csi_list); ++ spin_lock_init(&phy->csi.csi_lock); ++ mt7915_vendor_register(phy); ++#endif ++ + ret = mt76_register_phy(mphy, true, mt76_rates, + ARRAY_SIZE(mt76_rates)); + if (ret) +@@ -1178,6 +1184,24 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy) + } + } + ++#ifdef CONFIG_MTK_VENDOR ++static int mt7915_unregister_features(struct mt7915_phy *phy) ++{ ++ struct csi_data *c, *tmp_c; ++ ++ spin_lock_bh(&phy->csi.csi_lock); ++ phy->csi.enable = 0; ++ ++ list_for_each_entry_safe(c, tmp_c, &phy->csi.csi_list, node) { ++ list_del(&c->node); ++ kfree(c); ++ } ++ spin_unlock_bh(&phy->csi.csi_lock); ++ ++ return 0; ++} ++#endif ++ + static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) + { + struct mt7915_phy *phy = mt7915_ext_phy(dev); +@@ -1186,6 +1210,10 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) + if (!phy) + return; + ++#ifdef CONFIG_MTK_VENDOR ++ mt7915_unregister_features(phy); ++#endif ++ + mt7915_unregister_thermal(phy); + mt76_unregister_phy(mphy); + ieee80211_free_hw(mphy->hw); +@@ -1198,6 +1226,10 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev) + mt7915_dma_cleanup(dev); + tasklet_disable(&dev->mt76.irq_tasklet); + ++#ifdef CONFIG_MTK_VENDOR ++ mt7915_unregister_features(&dev->phy); ++#endif ++ + if (is_mt798x(&dev->mt76)) + mt7986_wmac_disable(dev); + } +@@ -1242,6 +1274,12 @@ int mt7915_register_device(struct mt7915_dev *dev) + dev->mt76.test_ops = &mt7915_testmode_ops; + #endif + ++#ifdef CONFIG_MTK_VENDOR ++ INIT_LIST_HEAD(&dev->phy.csi.csi_list); ++ spin_lock_init(&dev->phy.csi.csi_lock); ++ mt7915_vendor_register(&dev->phy); ++#endif ++ + ret = mt76_register_device(&dev->mt76, true, mt76_rates, + ARRAY_SIZE(mt76_rates)); + if (ret) +diff --git a/mt7915/main.c b/mt7915/main.c +index 3ac3df3..4edb11a 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -811,6 +811,10 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct mt7915_phy *phy = msta->vif->phy; + int i; + ++#ifdef CONFIG_MTK_VENDOR ++ mt7915_mcu_set_csi(&dev->phy, 2, 8, 1, 0, sta->addr, 0); ++#endif ++ + mt7915_mcu_add_sta(dev, vif, sta, false); + + mt7915_mac_wtbl_update(dev, msta->wcid.idx, +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index 1a3647a..65609b4 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -40,6 +40,10 @@ static bool sr_scene_detect = true; + module_param(sr_scene_detect, bool, 0644); + MODULE_PARM_DESC(sr_scene_detect, "Enable firmware scene detection algorithm"); + ++#ifdef CONFIG_MTK_VENDOR ++static int mt7915_mcu_report_csi(struct mt7915_dev *dev, struct sk_buff *skb); ++#endif ++ + static u8 + mt7915_mcu_get_sta_nss(u16 mcs_map) + { +@@ -466,6 +470,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) + case MCU_EXT_EVENT_FW_LOG_2_HOST: + mt7915_mcu_rx_log_message(dev, skb); + break; ++#ifdef CONFIG_MTK_VENDOR ++ case MCU_EXT_EVENT_CSI_REPORT: ++ mt7915_mcu_report_csi(dev, skb); ++ break; ++#endif + case MCU_EXT_EVENT_BCC_NOTIFY: + mt7915_mcu_rx_bcc_notify(dev, skb); + break; +@@ -4195,6 +4204,200 @@ out: + return ret; + } + ++#ifdef CONFIG_MTK_VENDOR ++int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode, ++ u8 cfg, u8 v1, u32 v2, u8 *mac_addr, u32 sta_interval) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct mt7915_mcu_csi req = { ++ .band = phy != &dev->phy, ++ .mode = mode, ++ .cfg = cfg, ++ .v1 = v1, ++ .v2 = cpu_to_le32(v2), ++ }; ++ ++ if (is_valid_ether_addr(mac_addr)) { ++ ether_addr_copy(req.mac_addr, mac_addr); ++ ++ if (req.v2 == 1 && sta_interval) ++ req.sta_interval = sta_interval; ++ } ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(CSI_CTRL), &req, ++ sizeof(req), true); ++} ++ ++static int csi_integret_segment_data(struct mt7915_phy *phy, struct csi_data *csi) ++{ ++ struct csi_data *csi_temp = NULL; ++ ++ if (csi->segment_num == 0 && ++ csi->remain_last == 0) ++ return CSI_CHAIN_COMPLETE; ++ else if (csi->segment_num == 0 && ++ csi->remain_last == 1) { ++ memcpy(&phy->csi.buffered_csi, ++ csi, sizeof(struct csi_data)); ++ ++ return CSI_CHAIN_SEGMENT_FIRST; ++ } else if (csi->segment_num != 0) { ++ csi_temp = &phy->csi.buffered_csi; ++ if (csi->chain_info != ++ csi_temp->chain_info || ++ csi->segment_num != ++ (csi_temp->segment_num + 1)) ++ return CSI_CHAIN_SEGMENT_ERR; ++ ++ memcpy(&csi_temp->data_i[csi_temp->data_num], ++ csi->data_i, csi->data_num * sizeof(s16)); ++ ++ memcpy(&csi_temp->data_q[csi_temp->data_num], ++ csi->data_q, csi->data_num * sizeof(s16)); ++ ++ csi_temp->data_num += csi->data_num; ++ csi_temp->segment_num = csi->segment_num; ++ csi_temp->remain_last = csi->remain_last; ++ ++ if (csi->remain_last == 0) ++ return CSI_CHAIN_SEGMENT_LAST; ++ else if (csi->remain_last == 1) ++ return CSI_CHAIN_SEGMENT_MIDDLE; ++ } ++ ++ return CSI_CHAIN_ERR; ++} ++ ++static int ++mt7915_mcu_report_csi(struct mt7915_dev *dev, struct sk_buff *skb) ++{ ++ struct mt76_connac2_mcu_rxd *rxd = (struct mt76_connac2_mcu_rxd *)skb->data; ++ struct mt7915_phy *phy = &dev->phy; ++ int len, i; ++ struct mt7915_mcu_csi_report *cr; ++ int ret; ++ struct csi_data *current_csi = NULL; ++ struct csi_data *target_csi = NULL; ++ ++ skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd)); ++ ++ len = le16_to_cpu(rxd->len) - sizeof(struct mt76_connac2_mcu_rxd) + 24; ++ ++ cr = (struct mt7915_mcu_csi_report *)skb->data; ++ ++ if (phy->csi.interval && ++ le32_to_cpu(cr->ts) < phy->csi.last_record + phy->csi.interval) ++ return 0; ++ ++ current_csi = kzalloc(sizeof(*current_csi), GFP_KERNEL); ++ ++ if (!current_csi) ++ return -ENOMEM; ++ ++ memset(current_csi, 0, sizeof(struct csi_data)); ++ ++#define SET_CSI_DATA(_field) (current_csi->_field = le32_to_cpu((cr->_field))) ++ SET_CSI_DATA(ch_bw); ++ SET_CSI_DATA(rssi); ++ SET_CSI_DATA(snr); ++ SET_CSI_DATA(data_num); ++ SET_CSI_DATA(data_bw); ++ SET_CSI_DATA(pri_ch_idx); ++ SET_CSI_DATA(ext_info); ++ SET_CSI_DATA(rx_mode); ++ SET_CSI_DATA(chain_info); ++ SET_CSI_DATA(ts); ++ ++ if (is_mt798x(&dev->mt76) || is_mt7916(&dev->mt76)) { ++ SET_CSI_DATA(segment_num); ++ SET_CSI_DATA(remain_last); ++ SET_CSI_DATA(pkt_sn); ++ SET_CSI_DATA(tr_stream); ++ } ++ ++ SET_CSI_DATA(band); ++ if (current_csi->band && !phy->mt76->band_idx) ++ phy = mt7915_ext_phy(dev); ++#undef SET_CSI_DATA ++ ++ switch (current_csi->ch_bw) { ++ case CSI_BW20: ++ if (is_mt798x(&dev->mt76) || is_mt7916(&dev->mt76)) ++ current_csi->data_num = CSI_BW20_DATA_COUNT; ++ break; ++ case CSI_BW40: ++ if (is_mt798x(&dev->mt76) || is_mt7916(&dev->mt76)) ++ current_csi->data_num = CSI_BW40_DATA_COUNT; ++ break; ++ default: ++ break; ++ } ++ ++ for (i = 0; i < current_csi->data_num; i++) { ++ current_csi->data_i[i] = le16_to_cpu(cr->data_i[i]); ++ current_csi->data_q[i] = le16_to_cpu(cr->data_q[i]); ++ } ++ ++ memcpy(current_csi->ta, cr->ta, ETH_ALEN); ++ current_csi->tx_idx = le32_get_bits(cr->trx_idx, GENMASK(31, 16)); ++ current_csi->rx_idx = le32_get_bits(cr->trx_idx, GENMASK(15, 0)); ++ ++ /* integret the bw80 segment */ ++ if ((is_mt798x(&dev->mt76) || is_mt7916(&dev->mt76)) && current_csi->ch_bw >= CSI_BW80) { ++ ret = csi_integret_segment_data(phy, current_csi); ++ ++ /* event data error or event drop */ ++ if (ret == CSI_CHAIN_ERR || ret == CSI_CHAIN_SEGMENT_ERR) { ++ kfree(current_csi); ++ return -EINVAL; ++ } ++ ++ if (ret == CSI_CHAIN_SEGMENT_FIRST || ret == CSI_CHAIN_SEGMENT_MIDDLE) { ++ kfree(current_csi); ++ return 0; ++ } else if (ret == CSI_CHAIN_COMPLETE) { ++ target_csi = current_csi; ++ } else if (ret == CSI_CHAIN_SEGMENT_LAST) { ++ target_csi = current_csi; ++ memcpy(target_csi, &phy->csi.buffered_csi, sizeof(struct csi_data)); ++ memset(&phy->csi.buffered_csi, 0, sizeof(struct csi_data)); ++ } ++ } else { ++ target_csi = current_csi; ++ } ++ ++ /* put the csi data into list */ ++ INIT_LIST_HEAD(&target_csi->node); ++ spin_lock_bh(&phy->csi.csi_lock); ++ ++ if (!phy->csi.enable) { ++ kfree(target_csi); ++ spin_unlock_bh(&phy->csi.csi_lock); ++ return 0; ++ } ++ ++ list_add_tail(&target_csi->node, &phy->csi.csi_list); ++ phy->csi.count++; ++ ++ if (phy->csi.count > CSI_MAX_BUF_NUM) { ++ struct csi_data *old; ++ ++ old = list_first_entry(&phy->csi.csi_list, ++ struct csi_data, node); ++ ++ list_del(&old->node); ++ kfree(old); ++ phy->csi.count--; ++ } ++ ++ if (target_csi->chain_info & BIT(15)) /* last chain */ ++ phy->csi.last_record = target_csi->ts; ++ spin_unlock_bh(&phy->csi.csi_lock); ++ ++ return 0; ++} ++#endif ++ + #ifdef MTK_DEBUG + int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp) + { +diff --git a/mt7915/mcu.h b/mt7915/mcu.h +index 9ae0f07..f32d525 100644 +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -604,4 +604,78 @@ mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower) + enum { + MCU_GET_TX_RATE = 4 + }; ++ ++#ifdef CONFIG_MTK_VENDOR ++struct mt7915_mcu_csi { ++ u8 band; ++ u8 mode; ++ u8 cfg; ++ u8 v1; ++ __le32 v2; ++ u8 mac_addr[ETH_ALEN]; ++ u8 _rsv1[2]; ++ u32 sta_interval; ++ u8 _rsv2[28]; ++} __packed; ++ ++struct csi_tlv { ++ __le32 tag; ++ __le32 len; ++} __packed; ++ ++#define CSI_MAX_BUF_NUM 3000 ++ ++struct mt7915_mcu_csi_report { ++ struct csi_tlv _t0; ++ __le32 ver; ++ struct csi_tlv _t1; ++ __le32 ch_bw; ++ struct csi_tlv _t2; ++ __le32 rssi; ++ struct csi_tlv _t3; ++ __le32 snr; ++ struct csi_tlv _t4; ++ __le32 band; ++ struct csi_tlv _t5; ++ __le32 data_num; ++ struct csi_tlv _t6; ++ __le16 data_i[CSI_BW80_DATA_COUNT]; ++ struct csi_tlv _t7; ++ __le16 data_q[CSI_BW80_DATA_COUNT]; ++ struct csi_tlv _t8; ++ __le32 data_bw; ++ struct csi_tlv _t9; ++ __le32 pri_ch_idx; ++ struct csi_tlv _t10; ++ u8 ta[8]; ++ struct csi_tlv _t11; ++ __le32 ext_info; ++ struct csi_tlv _t12; ++ __le32 rx_mode; ++ struct csi_tlv _t17; ++ __le32 chain_info; ++ struct csi_tlv _t18; ++ __le32 trx_idx; ++ struct csi_tlv _t19; ++ __le32 ts; ++ struct csi_tlv _t20; ++ __le32 pkt_sn; ++ struct csi_tlv _t21; ++ __le32 segment_num; ++ struct csi_tlv _t22; ++ __le32 remain_last; ++ struct csi_tlv _t23; ++ __le32 tr_stream; ++} __packed; ++ ++enum CSI_CHAIN_TYPE { ++ CSI_CHAIN_ERR, ++ CSI_CHAIN_COMPLETE, ++ CSI_CHAIN_SEGMENT_FIRST, ++ CSI_CHAIN_SEGMENT_MIDDLE, ++ CSI_CHAIN_SEGMENT_LAST, ++ CSI_CHAIN_SEGMENT_ERR, ++}; ++#endif ++ + #endif +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 398f851..5a26335 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -195,6 +195,45 @@ struct mt7915_hif { + int irq; + }; + ++#ifdef CONFIG_MTK_VENDOR ++enum csi_bw { ++ CSI_BW20, ++ CSI_BW40, ++ CSI_BW80, ++ CSI_BW160 ++}; ++ ++#define CSI_BW20_DATA_COUNT 64 ++#define CSI_BW40_DATA_COUNT 128 ++#define CSI_BW80_DATA_COUNT 256 ++#define CSI_BW160_DATA_COUNT 512 ++ ++struct csi_data { ++ u8 ch_bw; ++ u16 data_num; ++ s16 data_i[CSI_BW160_DATA_COUNT]; ++ s16 data_q[CSI_BW160_DATA_COUNT]; ++ u8 band; ++ s8 rssi; ++ u8 snr; ++ u32 ts; ++ u8 data_bw; ++ u8 pri_ch_idx; ++ u8 ta[ETH_ALEN]; ++ u32 ext_info; ++ u8 rx_mode; ++ u32 chain_info; ++ u16 tx_idx; ++ u16 rx_idx; ++ u32 segment_num; ++ u8 remain_last; ++ u16 pkt_sn; ++ u8 tr_stream; ++ ++ struct list_head node; ++}; ++#endif ++ + struct mt7915_phy { + struct mt76_phy *mt76; + struct mt7915_dev *dev; +@@ -243,6 +282,21 @@ struct mt7915_phy { + u8 spe_idx; + } test; + #endif ++ ++#ifdef CONFIG_MTK_VENDOR ++ struct { ++ struct list_head csi_list; ++ spinlock_t csi_lock; /* used for csi data push/pop */ ++ u32 count; ++ bool mask; ++ bool reorder; ++ bool enable; ++ ++ struct csi_data buffered_csi; ++ u32 interval; ++ u32 last_record; ++ } csi; ++#endif + }; + + #ifdef MTK_DEBUG +@@ -647,6 +701,12 @@ void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, + bool pci, int *irq); + ++#ifdef CONFIG_MTK_VENDOR ++void mt7915_vendor_register(struct mt7915_phy *phy); ++int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode, ++ u8 cfg, u8 v1, u32 v2, u8 *mac_addr, u32 sta_interval); ++#endif ++ + #ifdef MTK_DEBUG + int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir); + int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp); +diff --git a/mt7915/vendor.c b/mt7915/vendor.c +new file mode 100644 +index 0000000..55da60a +--- /dev/null ++++ b/mt7915/vendor.c +@@ -0,0 +1,470 @@ ++// SPDX-License-Identifier: ISC ++/* ++ * Copyright (C) 2020, MediaTek Inc. All rights reserved. ++ */ ++ ++#include ++ ++#include "mt7915.h" ++#include "mcu.h" ++#include "vendor.h" ++ ++static const struct nla_policy ++csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = { ++ [MTK_VENDOR_ATTR_CSI_CTRL_CFG] = {.type = NLA_NESTED }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR] = { .type = NLA_NESTED }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_INTERVAL] = { .type = NLA_U32 }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_STA_INTERVAL] = { .type = NLA_U32 }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM] = { .type = NLA_U16 }, ++ [MTK_VENDOR_ATTR_CSI_CTRL_DATA] = { .type = NLA_NESTED }, ++}; ++ ++struct csi_null_tone { ++ u8 start; ++ u8 end; ++}; ++ ++struct csi_reorder { ++ u8 dest; ++ u8 start; ++ u8 end; ++}; ++ ++struct csi_mask { ++ struct csi_null_tone null[10]; ++ u8 pilot[8]; ++ struct csi_reorder ro[3]; ++}; ++ ++static const struct csi_mask csi_mask_groups[] = { ++ /* OFDM */ ++ { .null = { { 0 }, { 27, 37 } }, ++ .ro = { {0, 0, 63} }, ++ }, ++ { .null = { { 0, 69 }, { 96 }, { 123, 127 } }, ++ .ro = { { 0, 96 }, { 38, 70, 95 }, { 1, 97, 122 } }, ++ }, ++ { .null = { { 0, 5 }, { 32 }, { 59, 127 } }, ++ .ro = { { 0, 32 }, { 38, 6, 31 }, { 1, 33, 58 } }, ++ }, ++ { .null = { { 0, 5 }, { 32 }, { 59, 69 }, { 96 }, { 123, 127 } }, ++ .ro = { { 0, 0, 127 } }, ++ }, ++ { .null = { { 0, 133 }, { 160 }, { 187, 255 } }, ++ .ro = { { 0, 160 }, { 1, 161, 186 }, { 38, 134, 159 } }, ++ }, ++ { .null = { { 0, 197 }, { 224 }, { 251, 255 } }, ++ .ro = { { 0, 224 }, { 1, 225, 250 }, { 38, 198, 223 } }, ++ }, ++ { .null = { { 0, 5 }, { 32 }, { 59, 255 } }, ++ .ro = { { 0, 32 }, { 1, 33, 58 }, { 38, 6, 31 } }, ++ }, ++ { .null = { { 0, 69 }, { 96 }, { 123, 255 } }, ++ .ro = { { 0, 96 }, { 1, 97, 122 }, { 38, 70, 95 } }, ++ }, ++ { .null = { { 0, 133 }, { 160 }, { 187, 197 }, { 224 }, { 251, 255 } }, ++ .ro = { { 0, 192 }, { 2, 198, 250 }, { 74, 134, 186 } }, ++ }, ++ { .null = { { 0, 5 }, { 32 }, { 59, 69 }, { 96 }, { 123, 255 } }, ++ .ro = { { 0, 64 }, { 2, 70, 122 }, { 74, 6, 58 } }, ++ }, ++ { .null = { { 0, 5 }, { 32 }, { 59, 69 }, { 96 }, { 123, 133 }, ++ { 160 }, { 187, 197 }, { 224 }, { 251, 255 } }, ++ .ro = { { 0, 0, 255 } }, ++ }, ++ ++ /* HT/VHT */ ++ { .null = { { 0 }, { 29, 35 } }, ++ .pilot = { 7, 21, 43, 57 }, ++ .ro = { { 0, 0, 63 } }, ++ }, ++ { .null = { { 0, 67 }, { 96 }, { 125, 127 } }, ++ .pilot = { 75, 89, 103, 117 }, ++ .ro = { { 0, 96 }, { 36, 68, 95 }, { 1, 97, 124 } }, ++ }, ++ { .null = { { 0, 3 }, { 32 }, { 61, 127 } }, ++ .pilot = { 11, 25, 39, 53 }, ++ .ro = { { 0, 32 }, { 36, 4, 31 }, { 1, 33, 60 } }, ++ }, ++ { .null = { { 0, 1 }, { 59, 69 }, { 127 } }, ++ .pilot = { 11, 25, 53, 75, 103, 117 }, ++ .ro = { { 0, 0, 127 } }, ++ }, ++ { .null = { { 0, 131 }, { 160 }, { 189, 255 } }, ++ .pilot = { 139, 153, 167, 181 }, ++ .ro = { { 0, 160 }, { 1, 161, 188 }, { 36, 132, 159 } }, ++ }, ++ { .null = { { 0, 195 }, { 224 }, { 253 }, { 255 } }, ++ .pilot = { 203, 217, 231, 245 }, ++ .ro = { { 0, 224 }, { 1, 225, 252 }, { 36, 196, 223 } }, ++ }, ++ { .null = { { 0, 3 }, { 32 }, { 61, 255 } }, ++ .pilot = { 11, 25, 39, 53 }, ++ .ro = { { 0, 32 }, { 1, 33, 60 }, { 36, 4, 31 } }, ++ }, ++ { .null = { { 0, 67 }, { 96 }, { 125, 255 } }, ++ .pilot = { 75, 89, 103, 117 }, ++ .ro = { { 0, 96 }, { 1, 97, 124 }, { 36, 68, 95 } }, ++ }, ++ { .null = { { 0, 133 }, { 191, 193 }, { 251, 255 } }, ++ .pilot = { 139, 167, 181, 203, 217, 245 }, ++ .ro = { { 0, 192 }, { 2, 194, 250 }, { 70, 134, 190 } }, ++ }, ++ { .null = { { 0, 5 }, { 63, 65 }, { 123, 127 } }, ++ .pilot = { 11, 39, 53, 75, 89, 117 }, ++ .ro = { { 0, 64 }, { 2, 66, 122 }, { 70, 6, 62 } }, ++ }, ++ { .null = { { 0, 1 }, { 123, 133 }, { 255 } }, ++ .pilot = { 11, 39, 75, 103, 153, 181, 217, 245 }, ++ .ro = { { 0, 0, 255 } }, ++ }, ++ ++ /* HE */ ++ { .null = { { 0 }, { 31, 33 } }, ++ .pilot = { 12, 29, 35, 52 }, ++ .ro = { { 0, 0, 63 } }, ++ }, ++ { .null = { { 30, 34 }, { 96 } }, ++ .pilot = { 4, 21, 43, 60, 70, 87, 105, 122 }, ++ .ro = { { 0, 96 }, { 34, 66, 95 }, { 1, 97, 126 } }, ++ }, ++ { .null = { { 32 }, { 94, 98 } }, ++ .pilot = { 6, 23, 41, 58, 68, 85, 107, 124 }, ++ .ro = { { 0, 32 }, { 34, 2, 31 }, { 1, 31, 62 } }, ++ }, ++ { .null = { { 0 }, { 62, 66 } }, ++ .pilot = { 9, 26, 36, 53, 75, 92, 102, 119 }, ++ .ro = { { 0, 0, 127 } }, ++ }, ++ { .null = { { 30, 34 }, { 160 } }, ++ .pilot = { 4, 21, 43, 60, 137, 154, 166, 183 }, ++ .ro = { { 0, 160 }, { 1, 161, 190 }, { 34, 130, 159 } }, ++ }, ++ { .null = { { 94, 98 }, { 224 } }, ++ .pilot = { 68, 85, 107, 124, 201, 218, 230, 247 }, ++ .ro = { { 0, 224 }, { 1, 225, 254 }, { 34, 194, 223 } }, ++ }, ++ { .null = { { 32 }, { 158, 162 } }, ++ .pilot = { 9, 26, 38, 55, 132, 149, 171, 188 }, ++ .ro = { { 0, 32 }, { 1, 33, 62 }, { 34, 2, 31 } }, ++ }, ++ { .null = { { 96 }, { 222, 226 } }, ++ .pilot = { 73, 90, 102, 119, 196, 213, 235, 252 }, ++ .ro = { { 0, 96 }, { 1, 97, 126 }, { 34, 66, 95 } }, ++ }, ++ { .null = { { 62, 66 }, { 192 } }, ++ .pilot = { 36, 53, 75, 92, 169, 186, 198, 215 }, ++ .ro = { { 0, 192 }, { 1, 193, 253 }, { 67, 131, 191 } }, ++ }, ++ { .null = { { 64 }, { 190, 194 } }, ++ .pilot = { 41, 58, 70, 87, 164, 181, 203, 220 }, ++ .ro = { { 0, 64 }, { 1, 65, 125 }, { 67, 3, 63 } }, ++ }, ++ { .null = { { 0 }, { 126, 130 } }, ++ .pilot = { 6, 23, 100, 117, 139, 156, 233, 250 }, ++ .ro = { { 0, 0, 255 } }, ++ }, ++}; ++ ++static inline u8 csi_group_idx(u8 mode, u8 ch_bw, u8 data_bw, u8 pri_ch_idx) ++{ ++ if (ch_bw < 2 || data_bw < 1) ++ return mode * 11 + ch_bw * ch_bw + pri_ch_idx; ++ else ++ return mode * 11 + ch_bw * ch_bw + (data_bw + 1) * 2 + pri_ch_idx; ++} ++ ++static int mt7915_vendor_csi_ctrl(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_CSI_CTRL]; ++ int err; ++ ++ err = nla_parse(tb, MTK_VENDOR_ATTR_CSI_CTRL_MAX, data, data_len, ++ csi_ctrl_policy, NULL); ++ if (err) ++ return err; ++ ++ if (is_mt7915(phy->mt76->dev) && phy->mt76->chandef.width > NL80211_CHAN_WIDTH_80) { ++ err = -EINVAL; ++ return err; ++ } ++ ++ if (tb[MTK_VENDOR_ATTR_CSI_CTRL_CFG]) { ++ u8 mode = 0, type = 0, v1 = 0, v2 = 0; ++ u8 mac_addr[ETH_ALEN] = {}; ++ struct nlattr *cur; ++ int rem; ++ u32 sta_interval = 0; ++ ++ nla_for_each_nested(cur, tb[MTK_VENDOR_ATTR_CSI_CTRL_CFG], rem) { ++ switch (nla_type(cur)) { ++ case MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE: ++ mode = nla_get_u8(cur); ++ break; ++ case MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE: ++ type = nla_get_u8(cur); ++ break; ++ case MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1: ++ v1 = nla_get_u8(cur); ++ break; ++ case MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2: ++ v2 = nla_get_u8(cur); ++ break; ++ default: ++ return -EINVAL; ++ }; ++ } ++ ++ if (tb[MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR]) { ++ int idx = 0; ++ ++ nla_for_each_nested(cur, tb[MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR], rem) { ++ mac_addr[idx++] = nla_get_u8(cur); ++ } ++ ++ /* when configure mac filter, add interval for report interval per sta */ ++ if (tb[MTK_VENDOR_ATTR_CSI_CTRL_STA_INTERVAL]) ++ sta_interval = ++ nla_get_u32(tb[MTK_VENDOR_ATTR_CSI_CTRL_STA_INTERVAL]); ++ } ++ ++ err = mt7915_mcu_set_csi(phy, mode, type, v1, v2, mac_addr, sta_interval); ++ ++ if (err < 0) ++ return err; ++ ++ spin_lock_bh(&phy->csi.csi_lock); ++ ++ phy->csi.enable = !!mode; ++ ++ if (mode == 2 && type == 5) { ++ if (v1 >= 1) ++ phy->csi.mask = 1; ++ if (v1 == 2) ++ phy->csi.reorder = 1; ++ } ++ ++ /* clean up old csi stats */ ++ if ((mode == 0 || mode == 2) && !list_empty(&phy->csi.csi_list)) { ++ struct csi_data *c, *tmp_c; ++ ++ list_for_each_entry_safe(c, tmp_c, &phy->csi.csi_list, ++ node) { ++ list_del(&c->node); ++ kfree(c); ++ phy->csi.count--; ++ } ++ } else if (mode == 1) { ++ phy->csi.last_record = 0; ++ } ++ ++ spin_unlock_bh(&phy->csi.csi_lock); ++ } ++ ++ if (tb[MTK_VENDOR_ATTR_CSI_CTRL_INTERVAL]) ++ phy->csi.interval = nla_get_u32(tb[MTK_VENDOR_ATTR_CSI_CTRL_INTERVAL]); ++ ++ return 0; ++} ++ ++static void ++mt7915_vendor_csi_tone_mask(struct mt7915_phy *phy, struct csi_data *csi) ++{ ++ static const u8 mode_map[] = { ++ [MT_PHY_TYPE_OFDM] = 0, ++ [MT_PHY_TYPE_HT] = 1, ++ [MT_PHY_TYPE_VHT] = 1, ++ [MT_PHY_TYPE_HE_SU] = 2, ++ }; ++ const struct csi_mask *cmask; ++ int i; ++ ++ if (csi->rx_mode == MT_PHY_TYPE_CCK || !phy->csi.mask) ++ return; ++ ++ if (csi->data_bw == IEEE80211_STA_RX_BW_40) ++ csi->pri_ch_idx /= 2; ++ ++ cmask = &csi_mask_groups[csi_group_idx(mode_map[csi->rx_mode], ++ csi->ch_bw, ++ csi->data_bw, ++ csi->pri_ch_idx)]; ++ ++ for (i = 0; i < 10; i++) { ++ const struct csi_null_tone *ntone = &cmask->null[i]; ++ u8 start = ntone->start; ++ u8 end = ntone->end; ++ int j; ++ ++ if (!start && !end && i > 0) ++ break; ++ ++ if (!end) ++ end = start; ++ ++ for (j = start; j <= end; j++) { ++ csi->data_i[j] = 0; ++ csi->data_q[j] = 0; ++ } ++ } ++ ++ for (i = 0; i < 8; i++) { ++ u8 pilot = cmask->pilot[i]; ++ ++ if (!pilot) ++ break; ++ ++ csi->data_i[pilot] = 0; ++ csi->data_q[pilot] = 0; ++ } ++ ++ if (!phy->csi.reorder) ++ return; ++ ++ for (i = 0; i < 3; i++) { ++ const struct csi_reorder *ro = &cmask->ro[i]; ++ u8 dest = ro->dest; ++ u8 start = ro->start; ++ u8 end = ro->end; ++ ++ if (!dest && !start && !end) ++ break; ++ ++ if (dest == start) ++ continue; ++ ++ if (end) { ++ memmove(&csi->data_i[dest], &csi->data_i[start], ++ end - start + 1); ++ memmove(&csi->data_q[dest], &csi->data_q[start], ++ end - start + 1); ++ } else { ++ csi->data_i[dest] = csi->data_i[start]; ++ csi->data_q[dest] = csi->data_q[start]; ++ } ++ } ++} ++ ++static int ++mt7915_vendor_csi_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct sk_buff *skb, const void *data, int data_len, ++ unsigned long *storage) ++{ ++#define RESERVED_SET BIT(31) ++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_CSI_CTRL]; ++ int err = 0; ++ ++ if (*storage & RESERVED_SET) { ++ if ((*storage & GENMASK(15, 0)) == 0) ++ return -ENOENT; ++ (*storage)--; ++ } ++ ++ if (data) { ++ err = nla_parse(tb, MTK_VENDOR_ATTR_CSI_CTRL_MAX, data, data_len, ++ csi_ctrl_policy, NULL); ++ if (err) ++ return err; ++ } ++ ++ if (!(*storage & RESERVED_SET) && tb[MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM]) { ++ *storage = nla_get_u16(tb[MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM]); ++ *storage |= RESERVED_SET; ++ } ++ ++ spin_lock_bh(&phy->csi.csi_lock); ++ ++ if (!list_empty(&phy->csi.csi_list)) { ++ struct csi_data *csi; ++ void *a, *b; ++ int i; ++ ++ csi = list_first_entry(&phy->csi.csi_list, struct csi_data, node); ++ ++ mt7915_vendor_csi_tone_mask(phy, csi); ++ ++ a = nla_nest_start(skb, MTK_VENDOR_ATTR_CSI_CTRL_DATA); ++ ++ if (nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_VER, 1) || ++ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_RSSI, csi->rssi) || ++ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_SNR, csi->snr) || ++ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_BW, csi->data_bw) || ++ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_CH_IDX, csi->pri_ch_idx) || ++ nla_put_u8(skb, MTK_VENDOR_ATTR_CSI_DATA_MODE, csi->rx_mode)) ++ goto out; ++ ++ if (nla_put_u16(skb, MTK_VENDOR_ATTR_CSI_DATA_TX_ANT, csi->tx_idx) || ++ nla_put_u16(skb, MTK_VENDOR_ATTR_CSI_DATA_RX_ANT, csi->rx_idx)) ++ goto out; ++ ++ if (nla_put_u32(skb, MTK_VENDOR_ATTR_CSI_DATA_INFO, csi->ext_info) || ++ nla_put_u32(skb, MTK_VENDOR_ATTR_CSI_DATA_CHAIN_INFO, csi->chain_info) || ++ nla_put_u32(skb, MTK_VENDOR_ATTR_CSI_DATA_TS, csi->ts)) ++ goto out; ++ ++ b = nla_nest_start(skb, MTK_VENDOR_ATTR_CSI_DATA_TA); ++ for (i = 0; i < ARRAY_SIZE(csi->ta); i++) ++ if (nla_put_u8(skb, i, csi->ta[i])) ++ goto out; ++ nla_nest_end(skb, b); ++ ++ if (nla_put_u32(skb, MTK_VENDOR_ATTR_CSI_DATA_NUM, csi->data_num)) ++ goto out; ++ ++ b = nla_nest_start(skb, MTK_VENDOR_ATTR_CSI_DATA_I); ++ for (i = 0; i < csi->data_num; i++) ++ if (nla_put_u16(skb, i, csi->data_i[i])) ++ goto out; ++ nla_nest_end(skb, b); ++ ++ b = nla_nest_start(skb, MTK_VENDOR_ATTR_CSI_DATA_Q); ++ for (i = 0; i < csi->data_num; i++) ++ if (nla_put_u16(skb, i, csi->data_q[i])) ++ goto out; ++ nla_nest_end(skb, b); ++ ++ nla_nest_end(skb, a); ++ ++ list_del(&csi->node); ++ kfree(csi); ++ phy->csi.count--; ++ ++ err = phy->csi.count; ++ } ++out: ++ spin_unlock_bh(&phy->csi.csi_lock); ++ ++ return err; ++} ++ ++static const struct wiphy_vendor_command mt7915_vendor_commands[] = { ++ { ++ .info = { ++ .vendor_id = MTK_NL80211_VENDOR_ID, ++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL, ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | ++ WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = mt7915_vendor_csi_ctrl, ++ .dumpit = mt7915_vendor_csi_ctrl_dump, ++ .policy = csi_ctrl_policy, ++ .maxattr = MTK_VENDOR_ATTR_CSI_CTRL_MAX, ++ } ++}; ++ ++void mt7915_vendor_register(struct mt7915_phy *phy) ++{ ++ phy->mt76->hw->wiphy->vendor_commands = mt7915_vendor_commands; ++ phy->mt76->hw->wiphy->n_vendor_commands = ARRAY_SIZE(mt7915_vendor_commands); ++} +diff --git a/mt7915/vendor.h b/mt7915/vendor.h +new file mode 100644 +index 0000000..e1f5fd3 +--- /dev/null ++++ b/mt7915/vendor.h +@@ -0,0 +1,63 @@ ++/* SPDX-License-Identifier: ISC */ ++#ifndef __MT7915_VENDOR_H ++#define __MT7915_VENDOR_H ++ ++#define MTK_NL80211_VENDOR_ID 0x0ce7 ++ ++enum mtk_nl80211_vendor_subcmds { ++ MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL = 0xc2, ++}; ++ ++enum mtk_vendor_attr_csi_ctrl { ++ MTK_VENDOR_ATTR_CSI_CTRL_UNSPEC, ++ ++ MTK_VENDOR_ATTR_CSI_CTRL_CFG, ++ MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE, ++ MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE, ++ MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1, ++ MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2, ++ MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR, ++ MTK_VENDOR_ATTR_CSI_CTRL_INTERVAL, ++ MTK_VENDOR_ATTR_CSI_CTRL_STA_INTERVAL, ++ ++ MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM, ++ ++ MTK_VENDOR_ATTR_CSI_CTRL_DATA, ++ ++ /* keep last */ ++ NUM_MTK_VENDOR_ATTRS_CSI_CTRL, ++ MTK_VENDOR_ATTR_CSI_CTRL_MAX = ++ NUM_MTK_VENDOR_ATTRS_CSI_CTRL - 1 ++}; ++ ++enum mtk_vendor_attr_csi_data { ++ MTK_VENDOR_ATTR_CSI_DATA_UNSPEC, ++ MTK_VENDOR_ATTR_CSI_DATA_PAD, ++ ++ MTK_VENDOR_ATTR_CSI_DATA_VER, ++ MTK_VENDOR_ATTR_CSI_DATA_TS, ++ MTK_VENDOR_ATTR_CSI_DATA_RSSI, ++ MTK_VENDOR_ATTR_CSI_DATA_SNR, ++ MTK_VENDOR_ATTR_CSI_DATA_BW, ++ MTK_VENDOR_ATTR_CSI_DATA_CH_IDX, ++ MTK_VENDOR_ATTR_CSI_DATA_TA, ++ MTK_VENDOR_ATTR_CSI_DATA_NUM, ++ MTK_VENDOR_ATTR_CSI_DATA_I, ++ MTK_VENDOR_ATTR_CSI_DATA_Q, ++ MTK_VENDOR_ATTR_CSI_DATA_INFO, ++ MTK_VENDOR_ATTR_CSI_DATA_RSVD1, ++ MTK_VENDOR_ATTR_CSI_DATA_RSVD2, ++ MTK_VENDOR_ATTR_CSI_DATA_RSVD3, ++ MTK_VENDOR_ATTR_CSI_DATA_RSVD4, ++ MTK_VENDOR_ATTR_CSI_DATA_TX_ANT, ++ MTK_VENDOR_ATTR_CSI_DATA_RX_ANT, ++ MTK_VENDOR_ATTR_CSI_DATA_MODE, ++ MTK_VENDOR_ATTR_CSI_DATA_CHAIN_INFO, ++ ++ /* keep last */ ++ NUM_MTK_VENDOR_ATTRS_CSI_DATA, ++ MTK_VENDOR_ATTR_CSI_DATA_MAX = ++ NUM_MTK_VENDOR_ATTRS_CSI_DATA - 1 ++}; ++ ++#endif +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1002-wifi-mt76-mt7915-air-monitor-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1002-wifi-mt76-mt7915-air-monitor-support.patch new file mode 100644 index 000000000..b2156ede1 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1002-wifi-mt76-mt7915-air-monitor-support.patch @@ -0,0 +1,549 @@ +From 1a63c07be0a813d1342346c937cd2f949439b837 Mon Sep 17 00:00:00 2001 +From: Bo Jiao +Date: Tue, 11 Jan 2022 12:03:23 +0800 +Subject: [PATCH] wifi: mt76: mt7915: air monitor support + +--- + mt76_connac_mcu.h | 2 + + mt7915/mac.c | 4 + + mt7915/main.c | 3 + + mt7915/mt7915.h | 32 ++++ + mt7915/vendor.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/vendor.h | 38 +++++ + 6 files changed, 440 insertions(+) + +diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h +index cda7559..3aa4e59 100644 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1243,6 +1243,8 @@ enum { + MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, + MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, + MCU_EXT_CMD_PHY_STAT_INFO = 0xad, ++ /* for vendor csi and air monitor */ ++ MCU_EXT_CMD_SMESH_CTRL = 0xae, + MCU_EXT_CMD_SET_QOS_MAP = 0xb4, + MCU_EXT_CMD_CSI_CTRL = 0xc2, + }; +diff --git a/mt7915/mac.c b/mt7915/mac.c +index d99864f..e38905a 100644 +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -531,6 +531,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); + qos_ctl = *ieee80211_get_qos_ctl(hdr); + } ++#ifdef CONFIG_MTK_VENDOR ++ if (phy->amnt_ctrl.enable) ++ mt7915_vendor_amnt_fill_rx(phy, skb); ++#endif + } else { + status->flag |= RX_FLAG_8023; + mt7915_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb, +diff --git a/mt7915/main.c b/mt7915/main.c +index 4edb11a..847c74b 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -800,6 +800,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 30); + mt76_rmw_field(dev, addr, GENMASK(7, 0), 0xa0); + ++#ifdef CONFIG_MTK_VENDOR ++ mt7915_vendor_amnt_sta_remove(mvif->phy, sta); ++#endif + return mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); + } + +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 5a26335..576e70a 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -232,6 +232,33 @@ struct csi_data { + + struct list_head node; + }; ++ ++#define MT7915_AIR_MONITOR_MAX_ENTRY 16 ++#define MT7915_AIR_MONITOR_MAX_GROUP MT7915_AIR_MONITOR_MAX_ENTRY >> 1 ++ ++struct mt7915_air_monitor_group { ++ bool enable; ++ bool used[2]; ++}; ++ ++struct mt7915_air_monitor_entry { ++ bool enable; ++ ++ u8 group_idx; ++ u8 group_used_idx; ++ u8 muar_idx; ++ u8 addr[ETH_ALEN]; ++ unsigned int last_seen; ++ s8 rssi[4]; ++ struct ieee80211_sta *sta; ++}; ++ ++struct mt7915_air_monitor_ctrl { ++ u8 enable; ++ ++ struct mt7915_air_monitor_group group[MT7915_AIR_MONITOR_MAX_GROUP]; ++ struct mt7915_air_monitor_entry entry[MT7915_AIR_MONITOR_MAX_ENTRY]; ++}; + #endif + + struct mt7915_phy { +@@ -296,6 +323,8 @@ struct mt7915_phy { + u32 interval; + u32 last_record; + } csi; ++ ++ struct mt7915_air_monitor_ctrl amnt_ctrl; + #endif + }; + +@@ -705,6 +734,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, + void mt7915_vendor_register(struct mt7915_phy *phy); + int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode, + u8 cfg, u8 v1, u32 v2, u8 *mac_addr, u32 sta_interval); ++void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb); ++int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, ++ struct ieee80211_sta *sta); + #endif + + #ifdef MTK_DEBUG +diff --git a/mt7915/vendor.c b/mt7915/vendor.c +index 55da60a..c964b14 100644 +--- a/mt7915/vendor.c ++++ b/mt7915/vendor.c +@@ -448,6 +448,355 @@ out: + return err; + } + ++static const struct nla_policy ++amnt_ctrl_policy[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL] = { ++ [MTK_VENDOR_ATTR_AMNT_CTRL_SET] = {.type = NLA_NESTED }, ++ [MTK_VENDOR_ATTR_AMNT_CTRL_DUMP] = { .type = NLA_NESTED }, ++}; ++ ++static const struct nla_policy ++amnt_set_policy[NUM_MTK_VENDOR_ATTRS_AMNT_SET] = { ++ [MTK_VENDOR_ATTR_AMNT_SET_INDEX] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_AMNT_SET_MACADDR] = { .type = NLA_NESTED }, ++}; ++ ++static const struct nla_policy ++amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = { ++ [MTK_VENDOR_ATTR_AMNT_DUMP_INDEX] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_AMNT_DUMP_LEN] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_AMNT_DUMP_RESULT] = { .type = NLA_NESTED }, ++}; ++ ++struct mt7915_amnt_data { ++ u8 idx; ++ u8 addr[ETH_ALEN]; ++ s8 rssi[4]; ++ u32 last_seen; ++}; ++ ++struct mt7915_smesh { ++ u8 band; ++ u8 write; ++ u8 enable; ++ bool a2; ++ bool a1; ++ bool data; ++ bool mgnt; ++ bool ctrl; ++} __packed; ++ ++struct mt7915_smesh_event { ++ u8 band; ++ __le32 value; ++} __packed; ++ ++static int ++mt7915_vendor_smesh_ctrl(struct mt7915_phy *phy, u8 write, ++ u8 enable, u32 *value) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct mt7915_smesh req = { ++ .band = phy != &dev->phy, ++ .write = write, ++ .enable = enable, ++ .a2 = 1, ++ .a1 = 1, ++ .data = 1, ++ }; ++ struct mt7915_smesh_event *res; ++ struct sk_buff *skb; ++ int ret = 0; ++ ++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(SMESH_CTRL), ++ &req, sizeof(req), !write, &skb); ++ ++ if (ret || write) ++ return ret; ++ ++ res = (struct mt7915_smesh_event *) skb->data; ++ ++ if (!value) ++ return -EINVAL; ++ ++ *value = res->value; ++ ++ dev_kfree_skb(skb); ++ ++ return 0; ++} ++ ++static int ++mt7915_vendor_amnt_muar(struct mt7915_phy *phy, u8 muar_idx, u8 *addr) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ u8 mode; ++ u8 force_clear; ++ u8 clear_bitmap[8]; ++ u8 entry_count; ++ u8 write; ++ u8 band; ++ ++ u8 index; ++ u8 bssid; ++ u8 addr[ETH_ALEN]; ++ } __packed req = { ++ .entry_count = 1, ++ .write = 1, ++ .band = phy != &dev->phy, ++ .index = muar_idx, ++ }; ++ ++ ether_addr_copy(req.addr, addr); ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MUAR_UPDATE), &req, ++ sizeof(req), true); ++} ++ ++static int ++mt7915_vendor_amnt_set_en(struct mt7915_phy *phy, u8 enable) ++{ ++ u32 status; ++ int ret; ++ ++ ret = mt7915_vendor_smesh_ctrl(phy, 0, enable, &status); ++ if (ret) ++ return ret; ++ ++ status = status & 0xff; ++ ++ if (status == enable) ++ return 0; ++ ++ ret = mt7915_vendor_smesh_ctrl(phy, 1, enable, &status); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int ++mt7915_vendor_amnt_set_addr(struct mt7915_phy *phy, u8 index, u8 *addr) ++{ ++ struct mt7915_air_monitor_ctrl *amnt_ctrl = &phy->amnt_ctrl; ++ struct mt7915_air_monitor_group *group; ++ struct mt7915_air_monitor_entry *entry = &amnt_ctrl->entry[index]; ++ const u8 zero_addr[ETH_ALEN] = {}; ++ int enable = !ether_addr_equal(addr, zero_addr); ++ int ret, i, j; ++ ++ if (enable == 1 && entry->enable == 1) { ++ ether_addr_copy(entry->addr, addr); ++ } else if (enable == 1 && entry->enable == 0){ ++ for (i = 0; i < MT7915_AIR_MONITOR_MAX_GROUP; i++) { ++ group = &(amnt_ctrl->group[i]); ++ if (group->used[0] == 0) ++ j = 0; ++ else if (group->used[1] == 0) ++ j = 1; ++ else ++ continue; ++ ++ group->enable = 1; ++ group->used[j] = 1; ++ entry->enable = 1; ++ entry->group_idx = i; ++ entry->group_used_idx = j; ++ entry->muar_idx = 32 + 2 * i + 2 * i + 2 * j; ++ ether_addr_copy(entry->addr, addr); ++ break; ++ } ++ } else { ++ group = &(amnt_ctrl->group[entry->group_idx]); ++ ++ group->used[entry->group_used_idx] = 0; ++ if (group->used[0] == 0 && group->used[1] == 0) ++ group->enable = 0; ++ ++ entry->enable = 0; ++ ether_addr_copy(entry->addr, addr); ++ } ++ ++ amnt_ctrl->enable &= ~(1 << entry->group_idx); ++ amnt_ctrl->enable |= entry->enable << entry->group_idx; ++ ret = mt7915_vendor_amnt_muar(phy, entry->muar_idx, addr); ++ if (ret) ++ return ret; ++ ++ return mt7915_vendor_amnt_set_en(phy, amnt_ctrl->enable); ++} ++ ++void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb) ++{ ++ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; ++ struct mt7915_air_monitor_ctrl *ctrl = &phy->amnt_ctrl; ++ struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); ++ __le16 fc = hdr->frame_control; ++ u8 addr[ETH_ALEN]; ++ int i; ++ ++ if (!ieee80211_has_fromds(fc)) ++ ether_addr_copy(addr, hdr->addr2); ++ else if (ieee80211_has_tods(fc)) ++ ether_addr_copy(addr, hdr->addr4); ++ else ++ ether_addr_copy(addr, hdr->addr3); ++ ++ for (i = 0; i < MT7915_AIR_MONITOR_MAX_ENTRY; i++) { ++ struct mt7915_air_monitor_entry *entry; ++ ++ if (ether_addr_equal(addr, ctrl->entry[i].addr)) { ++ entry = &ctrl->entry[i]; ++ entry->rssi[0] = status->chain_signal[0]; ++ entry->rssi[1] = status->chain_signal[1]; ++ entry->rssi[2] = status->chain_signal[2]; ++ entry->rssi[3] = status->chain_signal[3]; ++ entry->last_seen = jiffies; ++ } ++ } ++ ++ if (ieee80211_has_tods(fc) && ++ !ether_addr_equal(hdr->addr3, phy->mt76->macaddr)) ++ return; ++ else if (!ether_addr_equal(hdr->addr1, phy->mt76->macaddr)) ++ return; ++} ++ ++int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, ++ struct ieee80211_sta *sta) ++{ ++ u8 zero[ETH_ALEN] = {}; ++ int i; ++ ++ if (!phy->amnt_ctrl.enable) ++ return 0; ++ ++ for (i = 0; i < MT7915_AIR_MONITOR_MAX_ENTRY; i++) ++ if (ether_addr_equal(sta->addr, phy->amnt_ctrl.entry[i].addr)) ++ return mt7915_vendor_amnt_set_addr(phy, i, zero); ++ ++ return 0; ++} ++ ++static int ++mt7915_vendor_amnt_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len) ++{ ++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct nlattr *tb1[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL]; ++ struct nlattr *tb2[NUM_MTK_VENDOR_ATTRS_AMNT_SET]; ++ struct nlattr *cur; ++ u8 index = 0, i = 0; ++ u8 mac_addr[ETH_ALEN] = {}; ++ int err, rem; ++ ++ err = nla_parse(tb1, MTK_VENDOR_ATTR_AMNT_CTRL_MAX, data, data_len, ++ amnt_ctrl_policy, NULL); ++ if (err) ++ return err; ++ ++ if (!tb1[MTK_VENDOR_ATTR_AMNT_CTRL_SET]) ++ return -EINVAL; ++ ++ err = nla_parse_nested(tb2, MTK_VENDOR_ATTR_AMNT_SET_MAX, ++ tb1[MTK_VENDOR_ATTR_AMNT_CTRL_SET], amnt_set_policy, NULL); ++ ++ if (!tb2[MTK_VENDOR_ATTR_AMNT_SET_INDEX] || ++ !tb2[MTK_VENDOR_ATTR_AMNT_SET_MACADDR]) ++ return -EINVAL; ++ ++ index = nla_get_u8(tb2[MTK_VENDOR_ATTR_AMNT_SET_INDEX]); ++ nla_for_each_nested(cur, tb2[MTK_VENDOR_ATTR_AMNT_SET_MACADDR], rem) { ++ mac_addr[i++] = nla_get_u8(cur); ++ } ++ ++ return mt7915_vendor_amnt_set_addr(phy, index, mac_addr); ++} ++ ++static int ++mt7915_amnt_dump(struct mt7915_phy *phy, struct sk_buff *skb, ++ u8 amnt_idx, int *attrtype) ++{ ++ struct mt7915_air_monitor_entry *entry = ++ &phy->amnt_ctrl.entry[amnt_idx]; ++ struct mt7915_amnt_data data; ++ u32 last_seen = 0; ++ ++ if (entry->enable == 0) ++ return 0; ++ ++ last_seen = jiffies_to_msecs(jiffies - entry->last_seen); ++ ++ data.idx = amnt_idx; ++ ether_addr_copy(data.addr, entry->addr); ++ data.rssi[0] = entry->rssi[0]; ++ data.rssi[1] = entry->rssi[1]; ++ data.rssi[2] = entry->rssi[2]; ++ data.rssi[3] = entry->rssi[3]; ++ data.last_seen = last_seen; ++ ++ nla_put(skb, (*attrtype)++, sizeof(struct mt7915_amnt_data), &data); ++ ++ return 1; ++} ++ ++static int ++mt7915_vendor_amnt_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev, ++ struct sk_buff *skb, const void *data, int data_len, ++ unsigned long *storage) ++{ ++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct nlattr *tb1[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL]; ++ struct nlattr *tb2[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP]; ++ void *a, *b; ++ int err = 0, attrtype = 0, i, len = 0; ++ u8 amnt_idx; ++ ++ if (*storage == 1) ++ return -ENOENT; ++ *storage = 1; ++ ++ err = nla_parse(tb1, MTK_VENDOR_ATTR_AMNT_CTRL_MAX, data, data_len, ++ amnt_ctrl_policy, NULL); ++ if (err) ++ return err; ++ ++ if (!tb1[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP]) ++ return -EINVAL; ++ ++ err = nla_parse_nested(tb2, MTK_VENDOR_ATTR_AMNT_DUMP_MAX, ++ tb1[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP], ++ amnt_dump_policy, NULL); ++ if (err) ++ return err; ++ ++ if (!tb2[MTK_VENDOR_ATTR_AMNT_DUMP_INDEX]) ++ return -EINVAL; ++ ++ amnt_idx = nla_get_u8(tb2[MTK_VENDOR_ATTR_AMNT_DUMP_INDEX]); ++ ++ a = nla_nest_start(skb, MTK_VENDOR_ATTR_AMNT_CTRL_DUMP); ++ b = nla_nest_start(skb, MTK_VENDOR_ATTR_AMNT_DUMP_RESULT); ++ ++ if (amnt_idx != 0xff) { ++ len += mt7915_amnt_dump(phy, skb, amnt_idx, &attrtype); ++ } else { ++ for (i = 0; i < MT7915_AIR_MONITOR_MAX_ENTRY; i++) { ++ len += mt7915_amnt_dump(phy, skb, i, &attrtype); ++ } ++ } ++ ++ nla_nest_end(skb, b); ++ ++ nla_put_u8(skb, MTK_VENDOR_ATTR_AMNT_DUMP_LEN, len); ++ ++ nla_nest_end(skb, a); ++ ++ return len + 1; ++} ++ + static const struct wiphy_vendor_command mt7915_vendor_commands[] = { + { + .info = { +@@ -460,6 +809,18 @@ static const struct wiphy_vendor_command mt7915_vendor_commands[] = { + .dumpit = mt7915_vendor_csi_ctrl_dump, + .policy = csi_ctrl_policy, + .maxattr = MTK_VENDOR_ATTR_CSI_CTRL_MAX, ++ }, ++ { ++ .info = { ++ .vendor_id = MTK_NL80211_VENDOR_ID, ++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL, ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | ++ WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = mt7915_vendor_amnt_ctrl, ++ .dumpit = mt7915_vendor_amnt_ctrl_dump, ++ .policy = amnt_ctrl_policy, ++ .maxattr = MTK_VENDOR_ATTR_AMNT_CTRL_MAX, + } + }; + +diff --git a/mt7915/vendor.h b/mt7915/vendor.h +index e1f5fd3..1863eee 100644 +--- a/mt7915/vendor.h ++++ b/mt7915/vendor.h +@@ -5,6 +5,7 @@ + #define MTK_NL80211_VENDOR_ID 0x0ce7 + + enum mtk_nl80211_vendor_subcmds { ++ MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae, + MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL = 0xc2, + }; + +@@ -60,4 +61,41 @@ enum mtk_vendor_attr_csi_data { + NUM_MTK_VENDOR_ATTRS_CSI_DATA - 1 + }; + ++enum mtk_vendor_attr_mnt_ctrl { ++ MTK_VENDOR_ATTR_AMNT_CTRL_UNSPEC, ++ ++ MTK_VENDOR_ATTR_AMNT_CTRL_SET, ++ MTK_VENDOR_ATTR_AMNT_CTRL_DUMP, ++ ++ /* keep last */ ++ NUM_MTK_VENDOR_ATTRS_AMNT_CTRL, ++ MTK_VENDOR_ATTR_AMNT_CTRL_MAX = ++ NUM_MTK_VENDOR_ATTRS_AMNT_CTRL - 1 ++}; ++ ++enum mtk_vendor_attr_mnt_set { ++ MTK_VENDOR_ATTR_AMNT_SET_UNSPEC, ++ ++ MTK_VENDOR_ATTR_AMNT_SET_INDEX, ++ MTK_VENDOR_ATTR_AMNT_SET_MACADDR, ++ ++ /* keep last */ ++ NUM_MTK_VENDOR_ATTRS_AMNT_SET, ++ MTK_VENDOR_ATTR_AMNT_SET_MAX = ++ NUM_MTK_VENDOR_ATTRS_AMNT_SET - 1 ++}; ++ ++enum mtk_vendor_attr_mnt_dump { ++ MTK_VENDOR_ATTR_AMNT_DUMP_UNSPEC, ++ ++ MTK_VENDOR_ATTR_AMNT_DUMP_INDEX, ++ MTK_VENDOR_ATTR_AMNT_DUMP_LEN, ++ MTK_VENDOR_ATTR_AMNT_DUMP_RESULT, ++ ++ /* keep last */ ++ NUM_MTK_VENDOR_ATTRS_AMNT_DUMP, ++ MTK_VENDOR_ATTR_AMNT_DUMP_MAX = ++ NUM_MTK_VENDOR_ATTRS_AMNT_DUMP - 1 ++}; ++ + #endif +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1003-wifi-mt76-mt7915-add-support-for-muru_onoff-via.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1003-wifi-mt76-mt7915-add-support-for-muru_onoff-via.patch new file mode 100644 index 000000000..d7b9f550c --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1003-wifi-mt76-mt7915-add-support-for-muru_onoff-via.patch @@ -0,0 +1,140 @@ +From a0249520b2ff800bcff8ed1f8531dddccc97d29b Mon Sep 17 00:00:00 2001 +From: Evelyn Tsai +Date: Tue, 4 Apr 2023 02:23:57 +0800 +Subject: [PATCH 1003/1053] wifi: mt76: mt7915: add support for muru_onoff via + +--- + mt7915/init.c | 1 + + mt7915/mcu.c | 10 ++++++++-- + mt7915/mcu.h | 6 ++++++ + mt7915/mt7915.h | 2 ++ + mt7915/mtk_debugfs.c | 33 +++++++++++++++++++++++++++++++++ + 5 files changed, 50 insertions(+), 2 deletions(-) + +diff --git a/mt7915/init.c b/mt7915/init.c +index 6d23dfd..fc42974 100644 +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -363,6 +363,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy) + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; + + phy->slottime = 9; ++ phy->muru_onoff = OFDMA_DL | OFDMA_UL | MUMIMO_DL | MUMIMO_UL; + + hw->sta_data_size = sizeof(struct mt7915_sta); + hw->vif_data_size = sizeof(struct mt7915_vif); +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index 9baf52b..6f73a7b 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -965,6 +965,7 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; ++ struct mt7915_phy *phy = mvif->phy; + struct sta_rec_muru *muru; + struct tlv *tlv; + +@@ -976,13 +977,18 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + + muru = (struct sta_rec_muru *)tlv; + +- muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer || ++ muru->cfg.mimo_dl_en = (mvif->cap.he_mu_ebfer || + mvif->cap.vht_mu_ebfer || +- mvif->cap.vht_mu_ebfee; ++ mvif->cap.vht_mu_ebfee) && ++ !!(phy->muru_onoff & MUMIMO_DL); + if (!is_mt7915(&dev->mt76)) + muru->cfg.mimo_ul_en = true; + muru->cfg.ofdma_dl_en = true; + ++ muru->cfg.mimo_ul_en = !!(phy->muru_onoff & MUMIMO_UL); ++ muru->cfg.ofdma_dl_en = !!(phy->muru_onoff & OFDMA_DL); ++ muru->cfg.ofdma_ul_en = !!(phy->muru_onoff & OFDMA_UL); ++ + if (sta->deflink.vht_cap.vht_supported) + muru->mimo_dl.vht_mu_bfee = + !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); +diff --git a/mt7915/mcu.h b/mt7915/mcu.h +index f32d525..f44146e 100644 +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -678,4 +678,10 @@ enum CSI_CHAIN_TYPE { + }; + #endif + ++/* MURU */ ++#define OFDMA_DL BIT(0) ++#define OFDMA_UL BIT(1) ++#define MUMIMO_DL BIT(2) ++#define MUMIMO_UL BIT(3) ++ + #endif +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 35ccfa3..e21a101 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -289,6 +289,8 @@ struct mt7915_phy { + u32 rx_ampdu_ts; + u32 ampdu_ref; + ++ u8 muru_onoff; ++ + struct mt76_mib_stats mib; + struct mt76_channel_state state_ts; + +diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c +index d2b5b7d..f521740 100644 +--- a/mt7915/mtk_debugfs.c ++++ b/mt7915/mtk_debugfs.c +@@ -2554,6 +2554,38 @@ static int mt7915_token_txd_read(struct seq_file *s, void *data) + return 0; + } + ++static int mt7915_muru_onoff_get(void *data, u64 *val) ++{ ++ struct mt7915_phy *phy = data; ++ ++ *val = phy->muru_onoff; ++ ++ printk("mumimo ul:%d, mumimo dl:%d, ofdma ul:%d, ofdma dl:%d\n", ++ !!(phy->muru_onoff & MUMIMO_UL), ++ !!(phy->muru_onoff & MUMIMO_DL), ++ !!(phy->muru_onoff & OFDMA_UL), ++ !!(phy->muru_onoff & OFDMA_DL)); ++ ++ return 0; ++} ++ ++static int mt7915_muru_onoff_set(void *data, u64 val) ++{ ++ struct mt7915_phy *phy = data; ++ ++ if (val > 15) { ++ printk("Wrong value! The value is between 0 ~ 15.\n"); ++ goto exit; ++ } ++ ++ phy->muru_onoff = val; ++exit: ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_muru_onoff, mt7915_muru_onoff_get, ++ mt7915_muru_onoff_set, "%llx\n"); ++ + static int mt7915_amsduinfo_read(struct seq_file *s, void *data) + { + struct mt7915_dev *dev = dev_get_drvdata(s->private); +@@ -3680,6 +3712,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) + + mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, 0); + ++ debugfs_create_file("muru_onoff", 0600, dir, phy, &fops_muru_onoff); + debugfs_create_file("fw_debug_module", 0600, dir, dev, + &fops_fw_debug_module); + debugfs_create_file("fw_debug_level", 0600, dir, dev, +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1004-wifi-mt76-mt7915-certification-patches.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1004-wifi-mt76-mt7915-certification-patches.patch new file mode 100644 index 000000000..6f8ce965f --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1004-wifi-mt76-mt7915-certification-patches.patch @@ -0,0 +1,1137 @@ +From e98f4b4ccc941705436b9cdfbd22b2e72b2ef055 Mon Sep 17 00:00:00 2001 +From: MeiChia Chiu +Date: Mon, 6 Jun 2022 20:15:51 +0800 +Subject: [PATCH] wifi: mt76: mt7915: certification patches + +--- + mt76_connac_mcu.h | 1 + + mt7915/mac.c | 23 +++ + mt7915/main.c | 13 +- + mt7915/mcu.c | 466 +++++++++++++++++++++++++++++++++++++++++++ + mt7915/mcu.h | 207 ++++++++++++++++++- + mt7915/mt7915.h | 13 ++ + mt7915/mtk_debugfs.c | 7 +- + mt7915/vendor.c | 188 +++++++++++++++++ + mt7915/vendor.h | 42 ++++ + 9 files changed, 955 insertions(+), 5 deletions(-) + +diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h +index 3aa4e59..d62b7df 100644 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1246,6 +1246,7 @@ enum { + /* for vendor csi and air monitor */ + MCU_EXT_CMD_SMESH_CTRL = 0xae, + MCU_EXT_CMD_SET_QOS_MAP = 0xb4, ++ MCU_EXT_CMD_CERT_CFG = 0xb7, + MCU_EXT_CMD_CSI_CTRL = 0xc2, + }; + +diff --git a/mt7915/mac.c b/mt7915/mac.c +index e38905a..43cff27 100644 +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -8,6 +8,7 @@ + #include "../dma.h" + #include "mac.h" + #include "mcu.h" ++#include "vendor.h" + + #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2) + +@@ -2002,6 +2003,21 @@ static void mt7915_mac_sta_stats_work(struct mt7915_phy *phy) + spin_unlock_bh(&phy->stats_lock); + } + ++#ifdef CONFIG_MTK_VENDOR ++void mt7915_capi_sta_rc_work(void *data, struct ieee80211_sta *sta) ++{ ++ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; ++ struct mt7915_dev *dev = msta->vif->phy->dev; ++ u32 *changed = data; ++ ++ spin_lock_bh(&dev->mt76.sta_poll_lock); ++ msta->changed |= *changed; ++ if (list_empty(&msta->rc_list)) ++ list_add_tail(&msta->rc_list, &dev->sta_rc_list); ++ spin_unlock_bh(&dev->mt76.sta_poll_lock); ++} ++#endif ++ + void mt7915_mac_sta_rc_work(struct work_struct *work) + { + struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work); +@@ -2024,6 +2040,13 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) + sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); + vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); + ++#ifdef CONFIG_MTK_VENDOR ++ if (changed & CAPI_RFEATURE_CHANGED) { ++ mt7915_mcu_set_rfeature_starec(&changed, dev, vif, sta); ++ spin_lock_bh(&dev->mt76.sta_poll_lock); ++ continue; ++ } ++#endif + if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | + IEEE80211_RC_NSS_CHANGED | + IEEE80211_RC_BW_CHANGED)) +diff --git a/mt7915/main.c b/mt7915/main.c +index 847c74b..8835cda 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -771,6 +771,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + bool ext_phy = mvif->phy != &dev->phy; ++#ifdef CONFIG_MTK_VENDOR ++ struct mt7915_phy *phy = ext_phy ? mt7915_ext_phy(dev) : &dev->phy; ++#endif + int ret, idx; + u32 addr; + +@@ -803,7 +806,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + #ifdef CONFIG_MTK_VENDOR + mt7915_vendor_amnt_sta_remove(mvif->phy, sta); + #endif +- return mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); ++ ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); ++ if (ret) ++ return ret; ++ ++#ifdef CONFIG_MTK_VENDOR ++ if (phy->muru_onoff & MUMIMO_DL_CERT) ++ mt7915_mcu_set_mimo(phy, 0); ++#endif ++ return 0; + } + + void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index b38c3d1..b50a2c2 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -4402,6 +4402,472 @@ mt7915_mcu_report_csi(struct mt7915_dev *dev, struct sk_buff *skb) + + return 0; + } ++void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif) ++{ ++ u8 mode, val; ++ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; ++ struct mt7915_phy *phy = mvif->phy; ++ ++ mode = FIELD_GET(RATE_CFG_MODE, *((u32 *)data)); ++ val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data)); ++ ++ switch (mode) { ++ case RATE_PARAM_FIXED_OFDMA: ++ if (val == 3) /* DL 20 and 80 */ ++ phy->muru_onoff = OFDMA_DL; /* Enable OFDMA DL only */ ++ else ++ phy->muru_onoff = val; ++ break; ++ case RATE_PARAM_FIXED_MIMO: ++ if (val == 0) ++ phy->muru_onoff = MUMIMO_DL_CERT | MUMIMO_DL; ++ break; ++ } ++} ++ ++void mt7915_mcu_set_rfeature_starec(void *data, struct mt7915_dev *dev, ++ struct ieee80211_vif *vif, struct ieee80211_sta *sta) ++{ ++ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; ++ struct mt7915_vif *mvif = msta->vif; ++ struct sta_rec_ra_fixed *ra; ++ struct sk_buff *skb; ++ struct tlv *tlv; ++ u8 mode, val; ++ int len = sizeof(struct sta_req_hdr) + sizeof(*ra); ++ ++ mode = FIELD_GET(RATE_CFG_MODE, *((u32 *)data)); ++ val = FIELD_GET(RATE_CFG_VAL, *((u32 *)data)); ++ ++ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &msta->wcid, len); ++ if (IS_ERR(skb)) ++ return; ++ ++ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); ++ ra = (struct sta_rec_ra_fixed *)tlv; ++ ++ switch (mode) { ++ case RATE_PARAM_FIXED_GI: ++ ra->field = cpu_to_le32(RATE_PARAM_FIXED_GI); ++ ra->phy.sgi = val * 85; ++ break; ++ case RATE_PARAM_FIXED_HE_LTF: ++ ra->field = cpu_to_le32(RATE_PARAM_FIXED_HE_LTF); ++ ra->phy.he_ltf = val * 85; ++ break; ++ case RATE_PARAM_FIXED_MCS: ++ ra->field = cpu_to_le32(RATE_PARAM_FIXED_MCS); ++ ra->phy.mcs = val; ++ break; ++ } ++ ++ mt76_mcu_skb_send_msg(&dev->mt76, skb, ++ MCU_EXT_CMD(STA_REC_UPDATE), true); ++} ++ ++int mt7915_mcu_set_mu_prot_frame_th(struct mt7915_phy *phy, u32 val) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ __le32 cmd; ++ __le32 threshold; ++ } __packed req = { ++ .cmd = cpu_to_le32(MURU_SET_PROT_FRAME_THR), ++ .threshold = val, ++ }; ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req, ++ sizeof(req), false); ++} ++ ++int mt7915_mcu_set_mu_edca(struct mt7915_phy *phy, u8 val) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ __le32 cmd; ++ u8 override; ++ } __packed req = { ++ .cmd = cpu_to_le32(MURU_SET_CERT_MU_EDCA_OVERRIDE), ++ .override = val, ++ }; ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req, ++ sizeof(req), false); ++} ++ ++int mt7915_mcu_set_muru_cfg(struct mt7915_phy *phy, struct mt7915_muru *muru) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ __le32 cmd; ++ struct mt7915_muru muru; ++ } __packed req = { ++ .cmd = cpu_to_le32(MURU_SET_MANUAL_CFG), ++ }; ++ ++ memcpy(&req.muru, muru, sizeof(struct mt7915_muru)); ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req, ++ sizeof(req), false); ++} ++ ++int mt7915_set_muru_cfg(struct mt7915_phy *phy, u8 action, u8 val) ++{ ++ struct mt7915_muru muru; ++ struct mt7915_muru_dl *dl = &muru.dl; ++ struct mt7915_muru_ul *ul = &muru.ul; ++ struct mt7915_muru_comm *comm = &muru.comm; ++ ++ memset(&muru, 0, sizeof(muru)); ++ ++ switch (action) { ++ case MURU_DL_USER_CNT: ++ dl->user_num = val; ++ comm->ppdu_format |= MURU_PPDU_HE_MU; ++ comm->sch_type |= MURU_OFDMA_SCH_TYPE_DL; ++ muru.cfg_comm = cpu_to_le32(MURU_COMM_SET); ++ muru.cfg_dl = cpu_to_le32(MURU_USER_CNT); ++ return mt7915_mcu_set_muru_cfg(phy, &muru); ++ case MURU_UL_USER_CNT: ++ ul->user_num = val; ++ comm->ppdu_format |= MURU_PPDU_HE_TRIG; ++ comm->sch_type |= MURU_OFDMA_SCH_TYPE_UL; ++ muru.cfg_comm = cpu_to_le32(MURU_COMM_SET); ++ muru.cfg_ul = cpu_to_le32(MURU_USER_CNT); ++ return mt7915_mcu_set_muru_cfg(phy, &muru); ++ default: ++ return 0; ++ } ++} ++ ++void mt7915_mcu_set_ppdu_tx_type(struct mt7915_phy *phy, u8 ppdu_type) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ __le32 cmd; ++ u8 enable_su; ++ } __packed ppdu_type_req = { ++ .cmd = cpu_to_le32(MURU_SET_SUTX), ++ }; ++ ++ switch(ppdu_type) { ++ case CAPI_SU: ++ ppdu_type_req.enable_su = 1; ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), ++ &ppdu_type_req, sizeof(ppdu_type_req), false); ++ mt7915_set_muru_cfg(phy, MURU_DL_USER_CNT, 0); ++ break; ++ case CAPI_MU: ++ ppdu_type_req.enable_su = 0; ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), ++ &ppdu_type_req, sizeof(ppdu_type_req), false); ++ break; ++ default: ++ break; ++ } ++} ++ ++void mt7915_mcu_set_nusers_ofdma(struct mt7915_phy *phy, u8 type, u8 ofdma_user_cnt) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ __le32 cmd; ++ u8 enable_su; ++ } __packed nusers_ofdma_req = { ++ .cmd = cpu_to_le32(MURU_SET_SUTX), ++ .enable_su = 0, ++ }; ++ ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), ++ &nusers_ofdma_req, sizeof(nusers_ofdma_req), false); ++ ++ mt7915_mcu_set_mu_dl_ack_policy(phy, MU_DL_ACK_POLICY_SU_BAR); ++ mt7915_mcu_set_mu_prot_frame_th(phy, 9999); ++ switch(type) { ++ case MURU_UL_USER_CNT: ++ mt7915_set_muru_cfg(phy, MURU_UL_USER_CNT, ofdma_user_cnt); ++ break; ++ case MURU_DL_USER_CNT: ++ default: ++ mt7915_set_muru_cfg(phy, MURU_DL_USER_CNT, ofdma_user_cnt); ++ break; ++ } ++} ++ ++void mt7915_mcu_set_mimo(struct mt7915_phy *phy, u8 direction) ++{ ++#define MUMIMO_SET_FIXED_RATE 10 ++#define MUMIMO_SET_FIXED_GRP_RATE 11 ++#define MUMIMO_SET_FORCE_MU 12 ++ struct mt7915_dev *dev = phy->dev; ++ struct cfg80211_chan_def *chandef = &phy->mt76->chandef; ++ struct { ++ __le32 cmd; ++ __le16 sub_cmd; ++ __le16 disable_ra; ++ } __packed fixed_rate_req = { ++ .cmd = cpu_to_le32(MURU_SET_MUMIMO_CTRL), ++ .sub_cmd = cpu_to_le16(MUMIMO_SET_FIXED_RATE), ++ .disable_ra = cpu_to_le16(1), ++ }; ++ struct { ++ __le32 cmd; ++ __le32 sub_cmd; ++ struct { ++ u8 user_cnt:2; ++ u8 rsv:2; ++ u8 ns0:1; ++ u8 ns1:1; ++ u8 ns2:1; ++ u8 ns3:1; ++ ++ __le16 wlan_id_user0; ++ __le16 wlan_id_user1; ++ __le16 wlan_id_user2; ++ __le16 wlan_id_user3; ++ ++ u8 dl_mcs_user0:4; ++ u8 dl_mcs_user1:4; ++ u8 dl_mcs_user2:4; ++ u8 dl_mcs_user3:4; ++ ++ u8 ul_mcs_user0:4; ++ u8 ul_mcs_user1:4; ++ u8 ul_mcs_user2:4; ++ u8 ul_mcs_user3:4; ++ ++ u8 ru_alloc; ++ u8 cap; ++ u8 gi; ++ u8 dl_ul; ++ } grp_rate_conf; ++ } fixed_grp_rate_req = { ++ .cmd = cpu_to_le32(MURU_SET_MUMIMO_CTRL), ++ .sub_cmd = cpu_to_le32(MUMIMO_SET_FIXED_GRP_RATE), ++ .grp_rate_conf = { ++ .user_cnt = 1, ++ .ru_alloc = 134, ++ .gi = 0, ++ .cap = 1, ++ .dl_ul = 0, ++ .wlan_id_user0 = cpu_to_le16(1), ++ .dl_mcs_user0 = 4, ++ .wlan_id_user1 = cpu_to_le16(2), ++ .dl_mcs_user1 = 4, ++ }, ++ }; ++ struct { ++ __le32 cmd; ++ __le16 sub_cmd; ++ bool force_mu; ++ } __packed force_mu_req = { ++ .cmd = cpu_to_le32(MURU_SET_MUMIMO_CTRL), ++ .sub_cmd = cpu_to_le16(MUMIMO_SET_FORCE_MU), ++ .force_mu = true, ++ }; ++ ++ switch (chandef->width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ fixed_grp_rate_req.grp_rate_conf.ru_alloc = 122; ++ break; ++ case NL80211_CHAN_WIDTH_80: ++ default: ++ break; ++ } ++ ++ mt7915_mcu_set_mu_dl_ack_policy(phy, MU_DL_ACK_POLICY_SU_BAR); ++ ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), ++ &fixed_rate_req, sizeof(fixed_rate_req), false); ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), ++ &fixed_grp_rate_req, sizeof(fixed_grp_rate_req), false); ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), ++ &force_mu_req, sizeof(force_mu_req), false); ++} ++ ++void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ __le32 cmd; ++ u8 enable; ++ } __packed req = { ++ .cmd = cpu_to_le32(MURU_SET_20M_DYN_ALGO), ++ .enable = enable, ++ }; ++ ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), ++ &req, sizeof(req), false); ++} ++ ++void mt7915_mcu_set_cert(struct mt7915_phy *phy, u8 type) ++{ ++#define CFGINFO_CERT_CFG 4 ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ struct basic_info{ ++ u8 dbdc_idx; ++ u8 rsv[3]; ++ __le32 tlv_num; ++ u8 tlv_buf[0]; ++ } hdr; ++ struct cert_cfg{ ++ __le16 tag; ++ __le16 length; ++ u8 cert_program; ++ u8 rsv[3]; ++ } tlv; ++ } req = { ++ .hdr = { ++ .dbdc_idx = phy != &dev->phy, ++ .tlv_num = cpu_to_le32(1), ++ }, ++ .tlv = { ++ .tag = cpu_to_le16(CFGINFO_CERT_CFG), ++ .length = cpu_to_le16(sizeof(struct cert_cfg)), ++ .cert_program = type, /* 1: CAPI Enable */ ++ } ++ }; ++ ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(CERT_CFG), ++ &req, sizeof(req), false); ++} ++ ++void mt7915_mcu_set_bypass_smthint(struct mt7915_phy *phy, u8 val) ++{ ++#define BF_CMD_CFG_PHY 36 ++#define BF_PHY_SMTH_INTL_BYPASS 0 ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ u8 cmd_category_id; ++ u8 action; ++ u8 band_idx; ++ u8 smthintbypass; ++ u8 rsv[12]; ++ } req = { ++ .cmd_category_id = BF_CMD_CFG_PHY, ++ .action = BF_PHY_SMTH_INTL_BYPASS, ++ .band_idx = phy != &dev->phy, ++ .smthintbypass = val, ++ }; ++ ++ mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), ++ &req, sizeof(req), false); ++} ++ ++int mt7915_mcu_set_bsrp_ctrl(struct mt7915_phy *phy, u16 interval, ++ u16 ru_alloc, u32 ppdu_dur, u8 trig_flow, u8 ext_cmd) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ __le32 cmd; ++ __le16 bsrp_interval; ++ __le16 bsrp_ru_alloc; ++ __le32 ppdu_duration; ++ u8 trigger_flow; ++ u8 ext_cmd_bsrp; ++ } __packed req = { ++ .cmd = cpu_to_le32(MURU_SET_BSRP_CTRL), ++ .bsrp_interval = cpu_to_le16(interval), ++ .bsrp_ru_alloc = cpu_to_le16(ru_alloc), ++ .ppdu_duration = cpu_to_le32(ppdu_dur), ++ .trigger_flow = trig_flow, ++ .ext_cmd_bsrp = ext_cmd, ++ }; ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req, ++ sizeof(req), false); ++} ++ ++int mt7915_mcu_set_mu_dl_ack_policy(struct mt7915_phy *phy, u8 policy_num) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ __le32 cmd; ++ u8 ack_policy; ++ } __packed req = { ++ .cmd = cpu_to_le32(MURU_SET_MU_DL_ACK_POLICY), ++ .ack_policy = policy_num, ++ }; ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req, ++ sizeof(req), false); ++} ++ ++int mt7915_mcu_set_txbf_sound_info(struct mt7915_phy *phy, u8 action, ++ u8 v1, u8 v2, u8 v3) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct { ++ u8 cmd_category_id; ++ u8 action; ++ u8 read_clear; ++ u8 vht_opt; ++ u8 he_opt; ++ u8 glo_opt; ++ __le16 wlan_idx; ++ u8 sound_interval; ++ u8 sound_stop; ++ u8 max_sound_sta; ++ u8 tx_time; ++ u8 mcs; ++ bool ldpc; ++ u8 inf; ++ u8 rsv; ++ } __packed req = { ++ .cmd_category_id = BF_CMD_TXSND_INFO, ++ .action = action, ++ }; ++ ++ switch (action) { ++ case BF_SND_CFG_OPT: ++ req.vht_opt = v1; ++ req.he_opt = v2; ++ req.glo_opt = v3; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req, ++ sizeof(req), false); ++} ++ ++int mt7915_mcu_set_rfeature_trig_type(struct mt7915_phy *phy, u8 enable, u8 trig_type) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ int ret = 0; ++ struct { ++ __le32 cmd; ++ u8 trig_type; ++ } __packed req = { ++ .cmd = cpu_to_le32(MURU_SET_TRIG_TYPE), ++ .trig_type = trig_type, ++ }; ++ ++ if (enable) { ++ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req, ++ sizeof(req), false); ++ if (ret) ++ return ret; ++ } ++ ++ switch (trig_type) { ++ case CAPI_BASIC: ++ return mt7915_mcu_set_bsrp_ctrl(phy, 5, 67, 0, 0, enable); ++ case CAPI_BRP: ++ return mt7915_mcu_set_txbf_sound_info(phy, BF_SND_CFG_OPT, ++ 0x0, 0x0, 0x1b); ++ case CAPI_MU_BAR: ++ return mt7915_mcu_set_mu_dl_ack_policy(phy, ++ MU_DL_ACK_POLICY_MU_BAR); ++ case CAPI_BSRP: ++ return mt7915_mcu_set_bsrp_ctrl(phy, 5, 67, 4, 0, enable); ++ default: ++ return 0; ++ } ++} + #endif + + #ifdef MTK_DEBUG +diff --git a/mt7915/mcu.h b/mt7915/mcu.h +index f44146e..eef2fc0 100644 +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -486,10 +486,14 @@ enum { + RATE_PARAM_FIXED = 3, + RATE_PARAM_MMPS_UPDATE = 5, + RATE_PARAM_FIXED_HE_LTF = 7, +- RATE_PARAM_FIXED_MCS, ++ RATE_PARAM_FIXED_MCS = 8, + RATE_PARAM_FIXED_GI = 11, + RATE_PARAM_AUTO = 20, + RATE_PARAM_SPE_UPDATE = 22, ++#ifdef CONFIG_MTK_VENDOR ++ RATE_PARAM_FIXED_MIMO = 30, ++ RATE_PARAM_FIXED_OFDMA = 31, ++#endif + }; + + #define RATE_CFG_MCS GENMASK(3, 0) +@@ -501,6 +505,9 @@ enum { + #define RATE_CFG_PHY_TYPE GENMASK(27, 24) + #define RATE_CFG_HE_LTF GENMASK(31, 28) + ++#define RATE_CFG_MODE GENMASK(15, 8) ++#define RATE_CFG_VAL GENMASK(7, 0) ++ + enum { + TX_POWER_LIMIT_ENABLE, + TX_POWER_LIMIT_TABLE = 0x4, +@@ -683,5 +690,203 @@ enum CSI_CHAIN_TYPE { + #define OFDMA_UL BIT(1) + #define MUMIMO_DL BIT(2) + #define MUMIMO_UL BIT(3) ++#define MUMIMO_DL_CERT BIT(4) ++ ++#ifdef CONFIG_MTK_VENDOR ++struct mt7915_muru_comm { ++ u8 ppdu_format; ++ u8 sch_type; ++ u8 band; ++ u8 wmm_idx; ++ u8 spe_idx; ++ u8 proc_type; ++}; ++ ++struct mt7915_muru_dl { ++ u8 user_num; ++ u8 tx_mode; ++ u8 bw; ++ u8 gi; ++ u8 ltf; ++ /* sigB */ ++ u8 mcs; ++ u8 dcm; ++ u8 cmprs; ++ ++ u8 ru[8]; ++ u8 c26[2]; ++ u8 ack_policy; ++ ++ struct { ++ __le16 wlan_idx; ++ u8 ru_alloc_seg; ++ u8 ru_idx; ++ u8 ldpc; ++ u8 nss; ++ u8 mcs; ++ u8 mu_group_idx; ++ u8 vht_groud_id; ++ u8 vht_up; ++ u8 he_start_stream; ++ u8 he_mu_spatial; ++ u8 ack_policy; ++ __le16 tx_power_alpha; ++ } usr[16]; ++}; ++ ++struct mt7915_muru_ul { ++ u8 user_num; ++ ++ /* UL TX */ ++ u8 trig_type; ++ __le16 trig_cnt; ++ __le16 trig_intv; ++ u8 bw; ++ u8 gi_ltf; ++ __le16 ul_len; ++ u8 pad; ++ u8 trig_ta[ETH_ALEN]; ++ u8 ru[8]; ++ u8 c26[2]; ++ ++ struct { ++ __le16 wlan_idx; ++ u8 ru_alloc; ++ u8 ru_idx; ++ u8 ldpc; ++ u8 nss; ++ u8 mcs; ++ u8 target_rssi; ++ __le32 trig_pkt_size; ++ } usr[16]; ++ ++ /* HE TB RX Debug */ ++ __le32 rx_hetb_nonsf_en_bitmap; ++ __le32 rx_hetb_cfg[2]; ++ ++ /* DL TX */ ++ u8 ba_type; ++}; ++ ++struct mt7915_muru { ++ __le32 cfg_comm; ++ __le32 cfg_dl; ++ __le32 cfg_ul; ++ ++ struct mt7915_muru_comm comm; ++ struct mt7915_muru_dl dl; ++ struct mt7915_muru_ul ul; ++}; ++ ++#define MURU_PPDU_HE_TRIG BIT(2) ++#define MURU_PPDU_HE_MU BIT(3) ++ ++#define MURU_OFDMA_SCH_TYPE_DL BIT(0) ++#define MURU_OFDMA_SCH_TYPE_UL BIT(1) ++ ++/* Common Config */ ++#define MURU_COMM_PPDU_FMT BIT(0) ++#define MURU_COMM_SCH_TYPE BIT(1) ++#define MURU_COMM_SET (MURU_COMM_PPDU_FMT | MURU_COMM_SCH_TYPE) ++/* DL&UL User config*/ ++#define MURU_USER_CNT BIT(4) ++ ++enum { ++ CAPI_SU, ++ CAPI_MU, ++ CAPI_ER_SU, ++ CAPI_TB, ++ CAPI_LEGACY ++}; ++ ++enum { ++ CAPI_BASIC, ++ CAPI_BRP, ++ CAPI_MU_BAR, ++ CAPI_MU_RTS, ++ CAPI_BSRP, ++ CAPI_GCR_MU_BAR, ++ CAPI_BQRP, ++ CAPI_NDP_FRP ++}; ++ ++enum { ++ MURU_SET_BSRP_CTRL = 1, ++ MURU_SET_SUTX = 16, ++ MURU_SET_MUMIMO_CTRL = 17, ++ MURU_SET_MANUAL_CFG = 100, ++ MURU_SET_MU_DL_ACK_POLICY = 200, ++ MURU_SET_TRIG_TYPE = 201, ++ MURU_SET_20M_DYN_ALGO = 202, ++ MURU_SET_PROT_FRAME_THR = 204, ++ MURU_SET_CERT_MU_EDCA_OVERRIDE = 205, ++}; ++ ++enum { ++ MU_DL_ACK_POLICY_MU_BAR = 3, ++ MU_DL_ACK_POLICY_TF_FOR_ACK = 4, ++ MU_DL_ACK_POLICY_SU_BAR = 5, ++}; ++ ++enum { ++ BF_SOUNDING_OFF = 0, ++ BF_SOUNDING_ON, ++ BF_DATA_PACKET_APPLY, ++ BF_PFMU_MEM_ALLOCATE, ++ BF_PFMU_MEM_RELEASE, ++ BF_PFMU_TAG_READ, ++ BF_PFMU_TAG_WRITE, ++ BF_PROFILE_READ, ++ BF_PROFILE_WRITE, ++ BF_PN_READ, ++ BF_PN_WRITE, ++ BF_PFMU_MEM_ALLOC_MAP_READ, ++ BF_AID_SET, ++ BF_STA_REC_READ, ++ BF_PHASE_CALIBRATION, ++ BF_IBF_PHASE_COMP, ++ BF_LNA_GAIN_CONFIG, ++ BF_PROFILE_WRITE_20M_ALL, ++ BF_APCLIENT_CLUSTER, ++ BF_AWARE_CTRL, ++ BF_HW_ENABLE_STATUS_UPDATE, ++ BF_REPT_CLONED_STA_TO_NORMAL_STA, ++ BF_GET_QD, ++ BF_BFEE_HW_CTRL, ++ BF_PFMU_SW_TAG_WRITE, ++ BF_MOD_EN_CTRL, ++ BF_DYNSND_EN_INTR, ++ BF_DYNSND_CFG_DMCS_TH, ++ BF_DYNSND_EN_PFID_INTR, ++ BF_CONFIG, ++ BF_PFMU_DATA_WRITE, ++ BF_FBRPT_DBG_INFO_READ, ++ BF_CMD_TXSND_INFO, ++ BF_CMD_PLY_INFO, ++ BF_CMD_MU_METRIC, ++ BF_CMD_TXCMD, ++ BF_CMD_CFG_PHY, ++ BF_CMD_SND_CNT, ++ BF_CMD_MAX ++}; ++ ++enum { ++ BF_SND_READ_INFO = 0, ++ BF_SND_CFG_OPT, ++ BF_SND_CFG_INTV, ++ BF_SND_STA_STOP, ++ BF_SND_CFG_MAX_STA, ++ BF_SND_CFG_BFRP, ++ BF_SND_CFG_INF ++}; ++ ++enum { ++ MURU_UPDATE = 0, ++ MURU_DL_USER_CNT, ++ MURU_UL_USER_CNT, ++ MURU_DL_INIT, ++ MURU_UL_INIT, ++}; ++#endif + + #endif +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 30fb064..136e89f 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -733,6 +733,19 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, + bool pci, int *irq); + + #ifdef CONFIG_MTK_VENDOR ++void mt7915_capi_sta_rc_work(void *data, struct ieee80211_sta *sta); ++void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif); ++void mt7915_mcu_set_rfeature_starec(void *data, struct mt7915_dev *dev, ++ struct ieee80211_vif *vif, struct ieee80211_sta *sta); ++int mt7915_mcu_set_rfeature_trig_type(struct mt7915_phy *phy, u8 enable, u8 trig_type); ++int mt7915_mcu_set_mu_dl_ack_policy(struct mt7915_phy *phy, u8 policy_num); ++void mt7915_mcu_set_ppdu_tx_type(struct mt7915_phy *phy, u8 ppdu_type); ++void mt7915_mcu_set_nusers_ofdma(struct mt7915_phy *phy, u8 type, u8 ofdma_user_cnt); ++void mt7915_mcu_set_mimo(struct mt7915_phy *phy, u8 direction); ++void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable); ++int mt7915_mcu_set_mu_edca(struct mt7915_phy *phy, u8 val); ++void mt7915_mcu_set_cert(struct mt7915_phy *phy, u8 type); ++void mt7915_mcu_set_bypass_smthint(struct mt7915_phy *phy, u8 val); + void mt7915_vendor_register(struct mt7915_phy *phy); + int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode, + u8 cfg, u8 v1, u32 v2, u8 *mac_addr, u32 sta_interval); +diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c +index 2f55a84..84f8fae 100644 +--- a/mt7915/mtk_debugfs.c ++++ b/mt7915/mtk_debugfs.c +@@ -2560,7 +2560,8 @@ static int mt7915_muru_onoff_get(void *data, u64 *val) + + *val = phy->muru_onoff; + +- printk("mumimo ul:%d, mumimo dl:%d, ofdma ul:%d, ofdma dl:%d\n", ++ printk("cert mumimo dl:%d, normal mumimo ul:%d, mumimo dl:%d, ofdma ul:%d, ofdma dl:%d\n", ++ !!(phy->muru_onoff & MUMIMO_DL_CERT), + !!(phy->muru_onoff & MUMIMO_UL), + !!(phy->muru_onoff & MUMIMO_DL), + !!(phy->muru_onoff & OFDMA_UL), +@@ -2573,8 +2574,8 @@ static int mt7915_muru_onoff_set(void *data, u64 val) + { + struct mt7915_phy *phy = data; + +- if (val > 15) { +- printk("Wrong value! The value is between 0 ~ 15.\n"); ++ if (val > 31) { ++ printk("Wrong value! The value is between 0 ~ 31.\n"); + goto exit; + } + +diff --git a/mt7915/vendor.c b/mt7915/vendor.c +index c964b14..7a71894 100644 +--- a/mt7915/vendor.c ++++ b/mt7915/vendor.c +@@ -23,6 +23,29 @@ csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = { + [MTK_VENDOR_ATTR_CSI_CTRL_DATA] = { .type = NLA_NESTED }, + }; + ++static const struct nla_policy ++wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = { ++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE] = {.type = NLA_U16 }, ++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_MU_EDCA] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT] = {.type = NLA_U8 }, ++}; ++ ++static const struct nla_policy ++rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL] = { ++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI] = {.type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG] = { .type = NLA_NESTED }, ++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY] = { .type = NLA_U8 }, ++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF] = { .type = NLA_U8 }, ++}; ++ + struct csi_null_tone { + u8 start; + u8 end; +@@ -797,6 +820,149 @@ mt7915_vendor_amnt_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev, + return len + 1; + } + ++static int mt7915_vendor_rfeature_ctrl(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct mt7915_dev *dev = phy->dev; ++ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL]; ++ int err; ++ u32 val; ++ ++ err = nla_parse(tb, MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX, data, data_len, ++ rfeature_ctrl_policy, NULL); ++ if (err) ++ return err; ++ ++ val = CAPI_RFEATURE_CHANGED; ++ ++ if (tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI]) { ++ val |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_FIXED_GI)| ++ FIELD_PREP(RATE_CFG_VAL, nla_get_u8(tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI])); ++ ieee80211_iterate_stations_atomic(hw, mt7915_capi_sta_rc_work, &val); ++ ieee80211_queue_work(hw, &dev->rc_work); ++ } ++ else if (tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF]) { ++ val |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_FIXED_HE_LTF)| ++ FIELD_PREP(RATE_CFG_VAL, nla_get_u8(tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF])); ++ ieee80211_iterate_stations_atomic(hw, mt7915_capi_sta_rc_work, &val); ++ ieee80211_queue_work(hw, &dev->rc_work); ++ } ++ else if (tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG]) { ++ u8 enable, trig_type; ++ int rem; ++ struct nlattr *cur; ++ ++ nla_for_each_nested(cur, tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG], rem) { ++ switch(nla_type(cur)) { ++ case MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN: ++ enable = nla_get_u8(cur); ++ break; ++ case MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE: ++ trig_type = nla_get_u8(cur); ++ break; ++ default: ++ return -EINVAL; ++ }; ++ } ++ ++ err = mt7915_mcu_set_rfeature_trig_type(phy, enable, trig_type); ++ if (err) ++ return err; ++ } ++ else if (tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY]) { ++ u8 ack_policy; ++ ++ ack_policy = nla_get_u8(tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY]); ++#define HE_TB_PPDU_ACK 4 ++ switch (ack_policy) { ++ case HE_TB_PPDU_ACK: ++ return mt7915_mcu_set_mu_dl_ack_policy(phy, ack_policy); ++ default: ++ return 0; ++ } ++ } ++ else if (tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF]) { ++ u8 trig_txbf; ++ ++ trig_txbf = nla_get_u8(tb[MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF]); ++ /* CAPI only issues trig_txbf=disable */ ++ } ++ ++ return 0; ++} ++ ++static int mt7915_vendor_wireless_ctrl(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct mt7915_dev *dev = phy->dev; ++ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL]; ++ int err; ++ u8 val8; ++ u16 val16; ++ u32 val32; ++ ++ err = nla_parse(tb, MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX, data, data_len, ++ wireless_ctrl_policy, NULL); ++ if (err) ++ return err; ++ ++ val32 = CAPI_WIRELESS_CHANGED; ++ ++ if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS]) { ++ val32 &= ~CAPI_WIRELESS_CHANGED; ++ val32 |= CAPI_RFEATURE_CHANGED | ++ FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_FIXED_MCS) | ++ FIELD_PREP(RATE_CFG_VAL, nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS])); ++ ieee80211_iterate_stations_atomic(hw, mt7915_capi_sta_rc_work, &val32); ++ ieee80211_queue_work(hw, &dev->rc_work); ++ } else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA]) { ++ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA]); ++ val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_FIXED_OFDMA) | ++ FIELD_PREP(RATE_CFG_VAL, val8); ++ ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL, ++ mt7915_set_wireless_vif, &val32); ++ if (val8 == 3) /* DL20and80 */ ++ mt7915_mcu_set_dynalgo(phy, 1); /* Enable dynamic algo */ ++ mt7915_mcu_set_mu_prot_frame_th(phy, 9999); ++ } else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE]) { ++ val16 = nla_get_u16(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE]); ++ hw->max_tx_aggregation_subframes = val16; ++ hw->max_rx_aggregation_subframes = val16; ++ } else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_MU_EDCA]) { ++ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_MU_EDCA]); ++ mt7915_mcu_set_mu_edca(phy, val8); ++ } else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE]) { ++ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE]); ++ mt7915_mcu_set_ppdu_tx_type(phy, val8); ++ } else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA]) { ++ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA]); ++ if (FIELD_GET(OFDMA_UL, phy->muru_onoff) == 1) ++ mt7915_mcu_set_nusers_ofdma(phy, MURU_UL_USER_CNT, val8); ++ else ++ mt7915_mcu_set_nusers_ofdma(phy, MURU_DL_USER_CNT, val8); ++ } else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO]) { ++ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO]); ++ val32 |= FIELD_PREP(RATE_CFG_MODE, RATE_PARAM_FIXED_MIMO) | ++ FIELD_PREP(RATE_CFG_VAL, val8); ++ ieee80211_iterate_active_interfaces_atomic(hw, IEEE80211_IFACE_ITER_RESUME_ALL, ++ mt7915_set_wireless_vif, &val32); ++ } else if (tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT]) { ++ val8 = nla_get_u8(tb[MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT]); ++ mt7915_mcu_set_cert(phy, val8); /* Cert Enable for OMI */ ++ mt7915_mcu_set_bypass_smthint(phy, val8); /* Cert bypass smooth interpolation */ ++ } ++ ++ return 0; ++} ++ + static const struct wiphy_vendor_command mt7915_vendor_commands[] = { + { + .info = { +@@ -821,6 +987,28 @@ static const struct wiphy_vendor_command mt7915_vendor_commands[] = { + .dumpit = mt7915_vendor_amnt_ctrl_dump, + .policy = amnt_ctrl_policy, + .maxattr = MTK_VENDOR_ATTR_AMNT_CTRL_MAX, ++ }, ++ { ++ .info = { ++ .vendor_id = MTK_NL80211_VENDOR_ID, ++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL, ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | ++ WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = mt7915_vendor_rfeature_ctrl, ++ .policy = rfeature_ctrl_policy, ++ .maxattr = MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX, ++ }, ++ { ++ .info = { ++ .vendor_id = MTK_NL80211_VENDOR_ID, ++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL, ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV | ++ WIPHY_VENDOR_CMD_NEED_RUNNING, ++ .doit = mt7915_vendor_wireless_ctrl, ++ .policy = wireless_ctrl_policy, ++ .maxattr = MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX, + } + }; + +diff --git a/mt7915/vendor.h b/mt7915/vendor.h +index 1863eee..1a18cae 100644 +--- a/mt7915/vendor.h ++++ b/mt7915/vendor.h +@@ -7,6 +7,48 @@ + enum mtk_nl80211_vendor_subcmds { + MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae, + MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL = 0xc2, ++ MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL = 0xc3, ++ MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4, ++}; ++ ++enum mtk_capi_control_changed { ++ CAPI_RFEATURE_CHANGED = BIT(16), ++ CAPI_WIRELESS_CHANGED = BIT(17), ++}; ++ ++enum mtk_vendor_attr_wireless_ctrl { ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_UNSPEC, ++ ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS, ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_OFDMA, ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE, ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA, ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE, ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO, ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT = 9, ++ ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_MU_EDCA, /* reserve */ ++ /* keep last */ ++ NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL, ++ MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX = ++ NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL - 1 ++}; ++ ++enum mtk_vendor_attr_rfeature_ctrl { ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC, ++ ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI, ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF, ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG, ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN, ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE, ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY, ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF, ++ ++ /* keep last */ ++ NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL, ++ MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX = ++ NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL - 1 + }; + + enum mtk_vendor_attr_csi_ctrl { +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/patches/1006-wifi-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1005-wifi-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch similarity index 92% rename from feeds/mediatek-sdk/mt76/patches/1006-wifi-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1005-wifi-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch index a9296d62f..137028bb5 100644 --- a/feeds/mediatek-sdk/mt76/patches/1006-wifi-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1005-wifi-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch @@ -1,7 +1,7 @@ -From b2ea4e76a819ce4e0182abb3e8ae3e295340c687 Mon Sep 17 00:00:00 2001 +From 7f14adae86830929258aad73e8290a7fd2b4e03e Mon Sep 17 00:00:00 2001 From: Evelyn Tsai Date: Tue, 4 Apr 2023 02:27:44 +0800 -Subject: [PATCH 1006/1049] wifi: mt76: mt7915: add mt76 vendor muru onoff +Subject: [PATCH 1005/1053] wifi: mt76: mt7915: add mt76 vendor muru onoff command --- @@ -12,10 +12,10 @@ Subject: [PATCH 1006/1049] wifi: mt76: mt7915: add mt76 vendor muru onoff 4 files changed, 63 insertions(+) diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 65d11f1e..9c07b14d 100644 +index cd533ae..63fb826 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -4357,6 +4357,13 @@ void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif) +@@ -4422,6 +4422,13 @@ void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif) if (val == 0) phy->muru_onoff = MUMIMO_DL_CERT | MUMIMO_DL; break; @@ -30,7 +30,7 @@ index 65d11f1e..9c07b14d 100644 } diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index eef2fc00..86500536 100644 +index eef2fc0..8650053 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -493,6 +493,7 @@ enum { @@ -42,7 +42,7 @@ index eef2fc00..86500536 100644 }; diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index 7a718944..a8b1fa84 100644 +index 7a71894..a8b1fa8 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -35,6 +35,11 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = { @@ -110,7 +110,7 @@ index 7a718944..a8b1fa84 100644 }; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 1a18cae7..a4a91804 100644 +index 1a18cae..a4a9180 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -9,6 +9,7 @@ enum mtk_nl80211_vendor_subcmds { diff --git a/feeds/mediatek-sdk/mt76/patches/1007-wifi-mt76-mt7915-drop-undefined-action-frame.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1006-wifi-mt76-mt7915-drop-undefined-action-frame.patch similarity index 87% rename from feeds/mediatek-sdk/mt76/patches/1007-wifi-mt76-mt7915-drop-undefined-action-frame.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1006-wifi-mt76-mt7915-drop-undefined-action-frame.patch index 2b7cf9e5f..71d9c03f5 100644 --- a/feeds/mediatek-sdk/mt76/patches/1007-wifi-mt76-mt7915-drop-undefined-action-frame.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1006-wifi-mt76-mt7915-drop-undefined-action-frame.patch @@ -1,14 +1,14 @@ -From 3b720669cc45ecb1f165b79a23bc91ffc75f2fb4 Mon Sep 17 00:00:00 2001 +From 3b76edcb079437bf742c4442c4db4609cf10d6b6 Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Thu, 14 Apr 2022 15:18:02 +0800 -Subject: [PATCH 1007/1049] wifi: mt76: mt7915: drop undefined action frame +Subject: [PATCH 1006/1053] wifi: mt76: mt7915: drop undefined action frame --- mt7915/mac.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mt7915/mac.c b/mt7915/mac.c -index d851017b..746b71df 100644 +index 43cff27..6b99437 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c @@ -744,6 +744,8 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, diff --git a/feeds/mediatek-sdk/mt76/patches/1008-wifi-mt76-testmode-rework-testmode-init-registers.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1007-wifi-mt76-testmode-rework-testmode-init-registers.patch similarity index 96% rename from feeds/mediatek-sdk/mt76/patches/1008-wifi-mt76-testmode-rework-testmode-init-registers.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1007-wifi-mt76-testmode-rework-testmode-init-registers.patch index f7b2b4e9a..8f2d84103 100644 --- a/feeds/mediatek-sdk/mt76/patches/1008-wifi-mt76-testmode-rework-testmode-init-registers.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1007-wifi-mt76-testmode-rework-testmode-init-registers.patch @@ -1,7 +1,7 @@ -From e16904d6d79bc036cb4db2e79999864f41c751bb Mon Sep 17 00:00:00 2001 +From 6668ef935f03e166732511ed063f706b9139cd19 Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Mon, 6 Jun 2022 19:46:26 +0800 -Subject: [PATCH 1008/1049] wifi: mt76: testmode: rework testmode init +Subject: [PATCH 1007/1053] wifi: mt76: testmode: rework testmode init registers --- @@ -18,7 +18,7 @@ Subject: [PATCH 1008/1049] wifi: mt76: testmode: rework testmode init 10 files changed, 164 insertions(+), 35 deletions(-) diff --git a/mac80211.c b/mac80211.c -index b30a74e8..3f5c2ed5 100644 +index b30a74e..3f5c2ed 100644 --- a/mac80211.c +++ b/mac80211.c @@ -804,7 +804,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) @@ -32,7 +32,7 @@ index b30a74e8..3f5c2ed5 100644 if (status->flag & RX_FLAG_FAILED_FCS_CRC) phy->test.rx_stats.fcs_error[q]++; diff --git a/mt76.h b/mt76.h -index 8b6e0a1c..8648dc27 100644 +index a07c7df..fe5b136 100644 --- a/mt76.h +++ b/mt76.h @@ -709,6 +709,8 @@ struct mt76_testmode_ops { @@ -62,10 +62,10 @@ index 8b6e0a1c..8648dc27 100644 }; diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 36054bd9..edc9e124 100644 +index 53262ce..75cb4e9 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1231,6 +1231,7 @@ enum { +@@ -1239,6 +1239,7 @@ enum { MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a, MCU_EXT_CMD_SET_RDD_TH = 0x9d, MCU_EXT_CMD_MURU_CTRL = 0x9f, @@ -74,7 +74,7 @@ index 36054bd9..edc9e124 100644 MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 86500536..7653b5e2 100644 +index 8650053..7653b5e 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -9,6 +9,7 @@ @@ -86,7 +86,7 @@ index 86500536..7653b5e2 100644 MCU_ATE_CLEAN_TXQUEUE = 0x1c, }; diff --git a/mt7915/mmio.c b/mt7915/mmio.c -index 6004d64f..694fc1bc 100644 +index 6004d64..694fc1b 100644 --- a/mt7915/mmio.c +++ b/mt7915/mmio.c @@ -120,6 +120,7 @@ static const u32 mt7986_reg[] = { @@ -106,7 +106,7 @@ index 6004d64f..694fc1bc 100644 [TMAC_ODTR] = 0x0cc, [TMAC_ATCR] = 0x00c, diff --git a/mt7915/regs.h b/mt7915/regs.h -index 7515b23f..2a9e50b3 100644 +index 3452a7e..8bb6a9f 100644 --- a/mt7915/regs.h +++ b/mt7915/regs.h @@ -48,6 +48,7 @@ enum reg_rev { @@ -154,7 +154,7 @@ index 7515b23f..2a9e50b3 100644 #define MT_AGG_ACR0(_band) MT_WF_AGG(_band, __OFFS(AGG_ACR0)) #define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) diff --git a/mt7915/testmode.c b/mt7915/testmode.c -index 0d76ae31..46939191 100644 +index 0d76ae3..4693919 100644 --- a/mt7915/testmode.c +++ b/mt7915/testmode.c @@ -30,7 +30,7 @@ struct reg_band { @@ -379,7 +379,7 @@ index 0d76ae31..46939191 100644 const struct mt76_testmode_ops mt7915_testmode_ops = { diff --git a/mt7915/testmode.h b/mt7915/testmode.h -index 5573ac30..a1c54c89 100644 +index 5573ac3..a1c54c8 100644 --- a/mt7915/testmode.h +++ b/mt7915/testmode.h @@ -33,6 +33,12 @@ struct mt7915_tm_clean_txq { @@ -430,7 +430,7 @@ index 5573ac30..a1c54c89 100644 + #endif diff --git a/testmode.c b/testmode.c -index 4644dace..1b37392c 100644 +index ca4fecc..9e05b86 100644 --- a/testmode.c +++ b/testmode.c @@ -448,8 +448,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -454,7 +454,7 @@ index 4644dace..1b37392c 100644 return -EMSGSIZE; diff --git a/testmode.h b/testmode.h -index 5e2792d8..89613266 100644 +index 5e2792d..8961326 100644 --- a/testmode.h +++ b/testmode.h @@ -101,6 +101,8 @@ enum mt76_testmode_attr { diff --git a/feeds/mediatek-sdk/mt76/patches/1009-wifi-mt76-testmode-additional-supports.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1008-wifi-mt76-testmode-additional-supports.patch similarity index 97% rename from feeds/mediatek-sdk/mt76/patches/1009-wifi-mt76-testmode-additional-supports.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1008-wifi-mt76-testmode-additional-supports.patch index 38bb8d06f..fa6094e9c 100644 --- a/feeds/mediatek-sdk/mt76/patches/1009-wifi-mt76-testmode-additional-supports.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1008-wifi-mt76-testmode-additional-supports.patch @@ -1,14 +1,14 @@ -From da7cb3d1f9dbde242f0843f8715a58d1537fbebf Mon Sep 17 00:00:00 2001 +From e6c4c7343a54ef607d8ceafa4615a32165c121fd Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Thu, 21 Apr 2022 15:43:19 +0800 -Subject: [PATCH 1009/1049] wifi: mt76: testmode: additional supports +Subject: [PATCH] wifi: mt76: testmode: additional supports Signed-off-by: Shayne Chen Signed-off-by: StanleyYP Wang --- dma.c | 3 +- mac80211.c | 12 + - mt76.h | 110 +++- + mt76.h | 119 ++++- mt76_connac_mcu.c | 4 + mt76_connac_mcu.h | 2 + mt7915/eeprom.c | 2 +- @@ -26,13 +26,13 @@ Signed-off-by: StanleyYP Wang testmode.h | 79 +++ tools/fields.c | 90 +++- tx.c | 3 +- - 20 files changed, 2064 insertions(+), 169 deletions(-) + 20 files changed, 2073 insertions(+), 169 deletions(-) diff --git a/dma.c b/dma.c -index 8240691f..bbae84f1 100644 +index ccdd564..bc8afcf 100644 --- a/dma.c +++ b/dma.c -@@ -613,8 +613,7 @@ free: +@@ -614,8 +614,7 @@ free: if (mt76_is_testmode_skb(dev, skb, &hw)) { struct mt76_phy *phy = hw->priv; @@ -43,7 +43,7 @@ index 8240691f..bbae84f1 100644 #endif diff --git a/mac80211.c b/mac80211.c -index 3f5c2ed5..305cae78 100644 +index 3f5c2ed..305cae7 100644 --- a/mac80211.c +++ b/mac80211.c @@ -55,6 +55,13 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = { @@ -73,7 +73,7 @@ index 3f5c2ed5..305cae78 100644 static const struct ieee80211_channel mt76_channels_6ghz[] = { diff --git a/mt76.h b/mt76.h -index 8648dc27..cf689dcc 100644 +index fe5b136..a7d424f 100644 --- a/mt76.h +++ b/mt76.h @@ -707,6 +707,21 @@ struct mt76_testmode_ops { @@ -156,7 +156,7 @@ index 8648dc27..cf689dcc 100644 u32 tx_pending; u32 tx_queued; u16 tx_queued_limit; -@@ -1348,6 +1387,59 @@ static inline bool mt76_testmode_enabled(struct mt76_phy *phy) +@@ -1348,6 +1387,68 @@ static inline bool mt76_testmode_enabled(struct mt76_phy *phy) #endif } @@ -172,6 +172,15 @@ index 8648dc27..cf689dcc 100644 + list); +} + ++static inline struct mt76_wcid * ++mt76_testmode_next_entry(struct mt76_phy *phy, struct mt76_wcid *wcid) ++{ ++ if (wcid == &phy->dev->global_wcid) ++ return NULL; ++ ++ return list_next_entry(wcid, list); ++} ++ +static inline struct mt76_testmode_entry_data * +mt76_testmode_entry_data(struct mt76_phy *phy, struct mt76_wcid *wcid) +{ @@ -184,13 +193,13 @@ index 8648dc27..cf689dcc 100644 + phy->hw->sta_data_size); +} + -+#define mt76_tm_for_each_entry(phy, wcid, ed) \ -+ for (wcid = mt76_testmode_first_entry(phy), \ -+ ed = mt76_testmode_entry_data(phy, wcid); \ -+ ((phy->test.aid && \ ++#define mt76_tm_for_each_entry(phy, wcid, ed) \ ++ for (wcid = mt76_testmode_first_entry(phy), \ ++ ed = mt76_testmode_entry_data(phy, wcid); \ ++ ((phy->test.aid && \ + !list_entry_is_head(wcid, &phy->test.tm_entry_list, list)) || \ + (!phy->test.aid && wcid == &phy->dev->global_wcid)) && ed; \ -+ wcid = list_next_entry(wcid, list), \ ++ wcid = mt76_testmode_next_entry(phy, wcid), \ + ed = mt76_testmode_entry_data(phy, wcid)) +#endif + @@ -216,7 +225,7 @@ index 8648dc27..cf689dcc 100644 static inline bool mt76_is_testmode_skb(struct mt76_dev *dev, struct sk_buff *skb, struct ieee80211_hw **hw) -@@ -1358,7 +1450,8 @@ static inline bool mt76_is_testmode_skb(struct mt76_dev *dev, +@@ -1358,7 +1459,8 @@ static inline bool mt76_is_testmode_skb(struct mt76_dev *dev, for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { struct mt76_phy *phy = dev->phys[i]; @@ -226,7 +235,7 @@ index 8648dc27..cf689dcc 100644 *hw = dev->phys[i]->hw; return true; } -@@ -1460,7 +1553,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +@@ -1460,7 +1562,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, struct netlink_callback *cb, void *data, int len); int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state); @@ -237,10 +246,10 @@ index 8648dc27..cf689dcc 100644 static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable) { diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c -index 7692423b..2b322b05 100644 +index a8f097d..44cd646 100644 --- a/mt76_connac_mcu.c +++ b/mt76_connac_mcu.c -@@ -400,6 +400,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, +@@ -407,6 +407,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, switch (vif->type) { case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: @@ -248,7 +257,7 @@ index 7692423b..2b322b05 100644 if (vif->p2p && !is_mt7921(dev)) conn_type = CONNECTION_P2P_GC; else -@@ -581,6 +582,9 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, +@@ -588,6 +589,9 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, rx->rca2 = 1; rx->rv = 1; @@ -259,10 +268,10 @@ index 7692423b..2b322b05 100644 return; diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index edc9e124..49a3406d 100644 +index 22d477f..0f408d9 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1016,6 +1016,7 @@ enum { +@@ -1023,6 +1023,7 @@ enum { MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13, MCU_EXT_EVENT_THERMAL_PROTECT = 0x22, MCU_EXT_EVENT_ASSERT_DUMP = 0x23, @@ -270,19 +279,19 @@ index edc9e124..49a3406d 100644 MCU_EXT_EVENT_RDD_REPORT = 0x3a, MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, MCU_EXT_EVENT_BSS_ACQ_PKT_CNT = 0x52, -@@ -1238,6 +1239,7 @@ enum { +@@ -1246,6 +1247,7 @@ enum { MCU_EXT_CMD_PHY_STAT_INFO = 0xad, /* for vendor csi and air monitor */ MCU_EXT_CMD_SMESH_CTRL = 0xae, + MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3, + MCU_EXT_CMD_SET_QOS_MAP = 0xb4, MCU_EXT_CMD_CERT_CFG = 0xb7, MCU_EXT_CMD_CSI_CTRL = 0xc2, - }; diff --git a/mt7915/eeprom.c b/mt7915/eeprom.c -index 3bb2643d..0441d91a 100644 +index bfdbc15..f4876fe 100644 --- a/mt7915/eeprom.c +++ b/mt7915/eeprom.c -@@ -136,7 +136,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) +@@ -142,7 +142,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) /* read eeprom data from efuse */ block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size); for (i = 0; i < block_num; i++) { @@ -292,10 +301,10 @@ index 3bb2643d..0441d91a 100644 return ret; } diff --git a/mt7915/init.c b/mt7915/init.c -index 4d594cfc..cdceb437 100644 +index 0350250..5c4aa1e 100644 --- a/mt7915/init.c +++ b/mt7915/init.c -@@ -726,7 +726,7 @@ static void mt7915_init_work(struct work_struct *work) +@@ -727,7 +727,7 @@ static void mt7915_init_work(struct work_struct *work) struct mt7915_dev *dev = container_of(work, struct mt7915_dev, init_work); @@ -305,7 +314,7 @@ index 4d594cfc..cdceb437 100644 mt7915_txbf_init(dev); } diff --git a/mt7915/mac.c b/mt7915/mac.c -index 746b71df..fe165275 100644 +index 6b99437..7d3397e 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c @@ -586,6 +586,7 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) @@ -385,7 +394,7 @@ index 746b71df..fe165275 100644 #endif } -@@ -1422,7 +1446,7 @@ mt7915_mac_restart(struct mt7915_dev *dev) +@@ -1420,7 +1444,7 @@ mt7915_mac_restart(struct mt7915_dev *dev) goto out; /* set the necessary init items */ @@ -395,7 +404,7 @@ index 746b71df..fe165275 100644 goto out; diff --git a/mt7915/main.c b/mt7915/main.c -index 1e9a3a64..2a7ad8b2 100644 +index 8835cda..e53754c 100644 --- a/mt7915/main.c +++ b/mt7915/main.c @@ -238,7 +238,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, @@ -408,7 +417,7 @@ index 1e9a3a64..2a7ad8b2 100644 mvif->mt76.wmm_idx += 2; diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 9c07b14d..8094c9a0 100644 +index 0d1bab1..05919e9 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c @@ -478,6 +478,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) @@ -489,7 +498,7 @@ index 9c07b14d..8094c9a0 100644 return 0; diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 7653b5e2..c791c7fa 100644 +index 7653b5e..c791c7f 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -8,10 +8,15 @@ @@ -547,7 +556,7 @@ index 7653b5e2..c791c7fa 100644 enum { diff --git a/mt7915/mmio.c b/mt7915/mmio.c -index 694fc1bc..222e2cfd 100644 +index 694fc1b..222e2cf 100644 --- a/mt7915/mmio.c +++ b/mt7915/mmio.c @@ -134,6 +134,7 @@ static const u32 mt7915_offs[] = { @@ -567,7 +576,7 @@ index 694fc1bc..222e2cfd 100644 [AGG_PCR0] = 0x040, [AGG_ACR0] = 0x054, diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index eee4df84..03a89306 100644 +index 136e89f..37abf56 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h @@ -304,11 +304,15 @@ struct mt7915_phy { @@ -586,7 +595,7 @@ index eee4df84..03a89306 100644 } test; #endif -@@ -409,6 +413,14 @@ struct mt7915_dev { +@@ -421,6 +425,14 @@ struct mt7915_dev { void __iomem *dcm; void __iomem *sku; @@ -601,7 +610,7 @@ index eee4df84..03a89306 100644 #ifdef MTK_DEBUG u16 wlan_idx; struct { -@@ -583,8 +595,8 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, +@@ -601,8 +613,8 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, void *data, u32 field); @@ -612,16 +621,16 @@ index eee4df84..03a89306 100644 int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num); int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, bool hdr_trans); -@@ -623,6 +635,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); +@@ -641,6 +653,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb); void mt7915_mcu_exit(struct mt7915_dev *dev); +int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb); void mt7915_mcu_wmm_pbc_work(struct work_struct *work); + int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif); - static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev) diff --git a/mt7915/regs.h b/mt7915/regs.h -index 2a9e50b3..67837975 100644 +index 8bb6a9f..1236da9 100644 --- a/mt7915/regs.h +++ b/mt7915/regs.h @@ -62,6 +62,7 @@ enum offs_rev { @@ -642,7 +651,7 @@ index 2a9e50b3..67837975 100644 (_n) * 4)) #define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_PCR0) + \ diff --git a/mt7915/testmode.c b/mt7915/testmode.c -index 46939191..32dc85cd 100644 +index 4693919..32dc85c 100644 --- a/mt7915/testmode.c +++ b/mt7915/testmode.c @@ -9,6 +9,10 @@ @@ -2102,7 +2111,7 @@ index 46939191..32dc85cd 100644 + .set_eeprom = mt7915_tm_set_eeprom, }; diff --git a/mt7915/testmode.h b/mt7915/testmode.h -index a1c54c89..eb0e0432 100644 +index a1c54c8..eb0e043 100644 --- a/mt7915/testmode.h +++ b/mt7915/testmode.h @@ -4,6 +4,8 @@ @@ -2417,7 +2426,7 @@ index a1c54c89..eb0e0432 100644 + #endif diff --git a/testmode.c b/testmode.c -index 1b37392c..bc7f0b56 100644 +index 9e05b86..7587047 100644 --- a/testmode.c +++ b/testmode.c @@ -8,6 +8,7 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = { @@ -2910,7 +2919,7 @@ index 1b37392c..bc7f0b56 100644 if (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER)) { diff --git a/testmode.h b/testmode.h -index 89613266..7a686250 100644 +index 8961326..7a68625 100644 --- a/testmode.h +++ b/testmode.h @@ -6,6 +6,8 @@ @@ -3047,7 +3056,7 @@ index 89613266..7a686250 100644 + #endif diff --git a/tools/fields.c b/tools/fields.c -index e3f69089..406ba77c 100644 +index e3f6908..406ba77 100644 --- a/tools/fields.c +++ b/tools/fields.c @@ -10,6 +10,7 @@ static const char * const testmode_state[] = { @@ -3226,7 +3235,7 @@ index e3f69089..406ba77c 100644 }; diff --git a/tx.c b/tx.c -index b602d9d7..7b747239 100644 +index 0fdf7d8..db0d4df 100644 --- a/tx.c +++ b/tx.c @@ -259,8 +259,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff * diff --git a/feeds/mediatek-sdk/mt76/patches/1010-wifi-mt76-testmode-add-pre-cal-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1009-wifi-mt76-testmode-add-pre-cal-support.patch similarity index 84% rename from feeds/mediatek-sdk/mt76/patches/1010-wifi-mt76-testmode-add-pre-cal-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1009-wifi-mt76-testmode-add-pre-cal-support.patch index 6cdcafbdf..3ccce52f3 100644 --- a/feeds/mediatek-sdk/mt76/patches/1010-wifi-mt76-testmode-add-pre-cal-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1009-wifi-mt76-testmode-add-pre-cal-support.patch @@ -1,25 +1,24 @@ -From 9bf70603e20e2564dee80a65704c2164667d3f9d Mon Sep 17 00:00:00 2001 +From 2d9fc3393a175ec0b132e6186df69baaad77e428 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Wed, 31 Aug 2022 20:06:52 +0800 -Subject: [PATCH 1010/1049] wifi: mt76: testmode: add pre-cal support +Subject: [PATCH 1009/1053] wifi: mt76: testmode: add pre-cal support Signed-off-by: StanleyYP Wang --- eeprom.c | 6 +- mt76.h | 1 + mt76_connac_mcu.h | 1 + - mt7915/eeprom.h | 34 +++- - mt7915/mcu.c | 27 ++- - mt7915/mt7915.h | 5 + + mt7915/mcu.c | 3 + + mt7915/mt7915.h | 1 + mt7915/testmode.c | 425 +++++++++++++++++++++++++++++++++++++++++++++- mt7915/testmode.h | 36 ++++ testmode.c | 15 +- testmode.h | 17 ++ tools/fields.c | 8 + - 11 files changed, 562 insertions(+), 13 deletions(-) + 10 files changed, 506 insertions(+), 7 deletions(-) diff --git a/eeprom.c b/eeprom.c -index a2673978..3625b169 100644 +index a267397..3625b16 100644 --- a/eeprom.c +++ b/eeprom.c @@ -94,8 +94,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l @@ -36,7 +35,7 @@ index a2673978..3625b169 100644 out_put_node: diff --git a/mt76.h b/mt76.h -index cf689dcc..95b5cc92 100644 +index 3fe18cd..22d76bb 100644 --- a/mt76.h +++ b/mt76.h @@ -708,6 +708,7 @@ struct mt76_testmode_ops { @@ -48,10 +47,10 @@ index cf689dcc..95b5cc92 100644 struct mt76_testmode_entry_data { diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 49a3406d..1a32268b 100644 +index 0972010..b75d340 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1012,6 +1012,7 @@ enum { +@@ -1019,6 +1019,7 @@ enum { /* ext event table */ enum { @@ -59,61 +58,8 @@ index 49a3406d..1a32268b 100644 MCU_EXT_EVENT_PS_SYNC = 0x5, MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13, MCU_EXT_EVENT_THERMAL_PROTECT = 0x22, -diff --git a/mt7915/eeprom.h b/mt7915/eeprom.h -index adc26a22..25f0b32a 100644 ---- a/mt7915/eeprom.h -+++ b/mt7915/eeprom.h -@@ -39,10 +39,18 @@ enum mt7915_eeprom_field { - }; - - #define MT_EE_WIFI_CAL_GROUP BIT(0) --#define MT_EE_WIFI_CAL_DPD GENMASK(2, 1) -+#define MT_EE_WIFI_CAL_DPD_2G BIT(2) -+#define MT_EE_WIFI_CAL_DPD_5G BIT(1) -+#define MT_EE_WIFI_CAL_DPD_6G BIT(3) -+#define MT_EE_WIFI_CAL_DPD GENMASK(3, 1) - #define MT_EE_CAL_UNIT 1024 --#define MT_EE_CAL_GROUP_SIZE (49 * MT_EE_CAL_UNIT + 16) --#define MT_EE_CAL_DPD_SIZE (54 * MT_EE_CAL_UNIT) -+#define MT_EE_CAL_GROUP_SIZE_7915 (49 * MT_EE_CAL_UNIT + 16) -+#define MT_EE_CAL_GROUP_SIZE_7916 (54 * MT_EE_CAL_UNIT + 16) -+#define MT_EE_CAL_GROUP_SIZE_7975 (54 * MT_EE_CAL_UNIT + 16) -+#define MT_EE_CAL_GROUP_SIZE_7976 (94 * MT_EE_CAL_UNIT + 16) -+#define MT_EE_CAL_GROUP_SIZE_7916_6G (94 * MT_EE_CAL_UNIT + 16) -+#define MT_EE_CAL_DPD_SIZE_V1 (54 * MT_EE_CAL_UNIT) -+#define MT_EE_CAL_DPD_SIZE_V2 (300 * MT_EE_CAL_UNIT) - - #define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0) - #define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6) -@@ -156,6 +164,26 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band) - return val & MT_EE_WIFI_CONF7_TSSI0_5G; - } - -+static inline u32 -+mt7915_get_cal_group_size(struct mt7915_dev *dev) -+{ -+ u8 *eep = dev->mt76.eeprom.data; -+ u32 val; -+ -+ if (is_mt7915(&dev->mt76)) { -+ return MT_EE_CAL_GROUP_SIZE_7915; -+ } else if (is_mt7916(&dev->mt76)) { -+ val = eep[MT_EE_WIFI_CONF + 1]; -+ val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val); -+ return (val == MT_EE_V2_BAND_SEL_6GHZ) ? MT_EE_CAL_GROUP_SIZE_7916_6G : -+ MT_EE_CAL_GROUP_SIZE_7916; -+ } else if (mt7915_check_adie(dev, false)) { -+ return MT_EE_CAL_GROUP_SIZE_7976; -+ } else { -+ return MT_EE_CAL_GROUP_SIZE_7975; -+ } -+} -+ - extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM]; - - #endif diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 8094c9a0..d983432f 100644 +index 233411c..ad58e3b 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c @@ -482,6 +482,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) @@ -126,63 +72,11 @@ index 8094c9a0..d983432f 100644 #endif case MCU_EXT_EVENT_BSS_ACQ_PKT_CNT: mt7915_mcu_rx_bss_acq_pkt_cnt(dev, skb); -@@ -3028,7 +3031,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev) - u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data; - u32 total = MT_EE_CAL_GROUP_SIZE; - -- if (1 || !(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_GROUP)) -+ if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP)) - return 0; - - /* -@@ -3108,11 +3111,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy) - { - struct mt7915_dev *dev = phy->dev; - struct cfg80211_chan_def *chandef = &phy->mt76->chandef; -- u16 total = 2, center_freq = chandef->center_freq1; -+ enum nl80211_band band = chandef->chan->band; -+ u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2; -+ u16 center_freq = chandef->center_freq1; - u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data; -+ u8 dpd_mask, cal_num = is_mt7915(&dev->mt76) ? 2 : 3; - int idx; - -- if (1 || !(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_DPD)) -+ switch (band) { -+ case NL80211_BAND_2GHZ: -+ dpd_mask = MT_EE_WIFI_CAL_DPD_2G; -+ break; -+ case NL80211_BAND_5GHZ: -+ dpd_mask = MT_EE_WIFI_CAL_DPD_5G; -+ break; -+ case NL80211_BAND_6GHZ: -+ dpd_mask = MT_EE_WIFI_CAL_DPD_6G; -+ break; -+ default: -+ dpd_mask = 0; -+ break; -+ } -+ -+ if (!(eep[offs] & dpd_mask)) - return 0; - - idx = mt7915_dpd_freq_idx(center_freq, chandef->width); diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 03a89306..d77a5f0c 100644 +index 1846e2f..dd2e80b 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -397,6 +397,10 @@ struct mt7915_dev { - struct rchan *relay_fwlog; - - void *cal; -+ u32 cur_prek_offset; -+ u8 dpd_chan_num_2g; -+ u8 dpd_chan_num_5g; -+ u8 dpd_chan_num_6g; - - struct { - u8 debug_wm; -@@ -636,6 +640,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); +@@ -654,6 +654,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb); void mt7915_mcu_exit(struct mt7915_dev *dev); int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb); @@ -191,7 +85,7 @@ index 03a89306..d77a5f0c 100644 static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev) diff --git a/mt7915/testmode.c b/mt7915/testmode.c -index 32dc85cd..4b344303 100644 +index 32dc85c..4b34430 100644 --- a/mt7915/testmode.c +++ b/mt7915/testmode.c @@ -5,6 +5,7 @@ @@ -666,7 +560,7 @@ index 32dc85cd..4b344303 100644 + .dump_precal = mt7915_tm_dump_precal, }; diff --git a/mt7915/testmode.h b/mt7915/testmode.h -index eb0e0432..75698261 100644 +index eb0e043..7569826 100644 --- a/mt7915/testmode.h +++ b/mt7915/testmode.h @@ -81,6 +81,11 @@ struct tm_tx_cont { @@ -734,7 +628,7 @@ index eb0e0432..75698261 100644 TAM_ARB_OP_MODE_NORMAL = 1, TAM_ARB_OP_MODE_TEST, diff --git a/testmode.c b/testmode.c -index bc7f0b56..3f108e40 100644 +index 7587047..070b296 100644 --- a/testmode.c +++ b/testmode.c @@ -771,6 +771,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, @@ -767,7 +661,7 @@ index bc7f0b56..3f108e40 100644 if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) || diff --git a/testmode.h b/testmode.h -index 7a686250..e4c1b521 100644 +index 7a68625..e4c1b52 100644 --- a/testmode.h +++ b/testmode.h @@ -19,6 +19,7 @@ @@ -823,7 +717,7 @@ index 7a686250..e4c1b521 100644 /* keep last */ diff --git a/tools/fields.c b/tools/fields.c -index 406ba77c..27801dbe 100644 +index 406ba77..27801db 100644 --- a/tools/fields.c +++ b/tools/fields.c @@ -11,6 +11,14 @@ static const char * const testmode_state[] = { diff --git a/feeds/mediatek-sdk/mt76/patches/1011-wifi-mt76-testmode-add-iBF-command-mode-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1010-wifi-mt76-testmode-add-iBF-command-mode-support.patch similarity index 96% rename from feeds/mediatek-sdk/mt76/patches/1011-wifi-mt76-testmode-add-iBF-command-mode-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1010-wifi-mt76-testmode-add-iBF-command-mode-support.patch index 8b76c7b42..c4d423eea 100644 --- a/feeds/mediatek-sdk/mt76/patches/1011-wifi-mt76-testmode-add-iBF-command-mode-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1010-wifi-mt76-testmode-add-iBF-command-mode-support.patch @@ -1,7 +1,7 @@ -From af9610a641bcdfb5662e3c2f326bc7592360ea44 Mon Sep 17 00:00:00 2001 +From be62cd03caedf8de9f3d6f2ef8883f85be51b9c7 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Mon, 12 Sep 2022 18:16:54 +0800 -Subject: [PATCH 1011/1049] wifi: mt76: testmode: add iBF command mode support +Subject: [PATCH 1010/1053] wifi: mt76: testmode: add iBF command mode support Signed-off-by: StanleyYP Wang --- @@ -12,7 +12,7 @@ Signed-off-by: StanleyYP Wang 4 files changed, 85 insertions(+), 7 deletions(-) diff --git a/mt7915/testmode.c b/mt7915/testmode.c -index 4b344303..453319e1 100644 +index 4b34430..453319e 100644 --- a/mt7915/testmode.c +++ b/mt7915/testmode.c @@ -722,6 +722,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf) @@ -104,7 +104,7 @@ index 4b344303..453319e1 100644 mt7915_tm_set_tx_len(phy, tx_time); diff --git a/testmode.c b/testmode.c -index 3f108e40..898ef3ae 100644 +index 070b296..b1986ad 100644 --- a/testmode.c +++ b/testmode.c @@ -535,6 +535,42 @@ out: @@ -163,7 +163,7 @@ index 3f108e40..898ef3ae 100644 nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) { if (nla_len(cur) != 2 || diff --git a/testmode.h b/testmode.h -index e4c1b521..1d7aef86 100644 +index e4c1b52..1d7aef8 100644 --- a/testmode.h +++ b/testmode.h @@ -285,8 +285,10 @@ enum mt76_testmode_txbf_act { @@ -178,7 +178,7 @@ index e4c1b521..1d7aef86 100644 /* keep last */ diff --git a/tools/fields.c b/tools/fields.c -index 27801dbe..b0ee84d2 100644 +index 27801db..b0ee84d 100644 --- a/tools/fields.c +++ b/tools/fields.c @@ -32,6 +32,20 @@ static const char * const testmode_tx_mode[] = { diff --git a/feeds/mediatek-sdk/mt76/patches/1012-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1011-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch similarity index 96% rename from feeds/mediatek-sdk/mt76/patches/1012-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1011-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch index e0357a084..b42e14190 100644 --- a/feeds/mediatek-sdk/mt76/patches/1012-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1011-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch @@ -1,7 +1,7 @@ -From 8d0b090a987138808ac8b06978fab0ce58cc47a7 Mon Sep 17 00:00:00 2001 +From 460f28c1cba4632a4bd046d0a93d1569f69acea0 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Thu, 27 Oct 2022 17:42:07 +0800 -Subject: [PATCH 1012/1049] wifi: mt76: testmode: add ZWDFS test mode support +Subject: [PATCH] wifi: mt76: testmode: add ZWDFS test mode support Signed-off-by: StanleyYP Wang --- @@ -18,7 +18,7 @@ Signed-off-by: StanleyYP Wang 10 files changed, 508 insertions(+), 1 deletion(-) diff --git a/mt76.h b/mt76.h -index 95b5cc92..1abb6499 100644 +index 20577af..53b0964 100644 --- a/mt76.h +++ b/mt76.h @@ -793,6 +793,15 @@ struct mt76_testmode_data { @@ -38,10 +38,10 @@ index 95b5cc92..1abb6499 100644 struct mt76_vif { diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 1a32268b..4d85d323 100644 +index 6511060..9ac1c46 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1233,6 +1233,7 @@ enum { +@@ -1241,6 +1241,7 @@ enum { MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a, MCU_EXT_CMD_SET_RDD_TH = 0x9d, MCU_EXT_CMD_MURU_CTRL = 0x9f, @@ -49,8 +49,8 @@ index 1a32268b..4d85d323 100644 MCU_EXT_CMD_RX_STAT = 0xa4, MCU_EXT_CMD_SET_SPR = 0xa8, MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, -@@ -1243,6 +1244,7 @@ enum { - MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3, +@@ -1252,6 +1253,7 @@ enum { + MCU_EXT_CMD_SET_QOS_MAP = 0xb4, MCU_EXT_CMD_CERT_CFG = 0xb7, MCU_EXT_CMD_CSI_CTRL = 0xc2, + MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5, @@ -58,7 +58,7 @@ index 1a32268b..4d85d323 100644 enum { diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index d983432f..61cf60e8 100644 +index 5f3fec8..2025ef3 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c @@ -2759,6 +2759,7 @@ mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy, @@ -69,11 +69,10 @@ index d983432f..61cf60e8 100644 req.band_idx = phy->mt76->band_idx; req.scan_mode = 2; break; -@@ -4907,3 +4908,68 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable) - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MEC_CTRL), &req, sizeof(req), true); +@@ -4955,6 +4956,71 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable) } #endif -+ + +int mt7915_mcu_ipi_hist_ctrl(struct mt7915_phy *phy, void *data, u8 cmd, bool wait_resp) +{ + struct mt7915_dev *dev = phy->dev; @@ -138,8 +137,12 @@ index d983432f..61cf60e8 100644 + + return 0; +} ++ + int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif) + { + #define IP_DSCP_NUM 64 diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index c791c7fa..066246bb 100644 +index c791c7f..066246b 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -698,6 +698,52 @@ enum CSI_CHAIN_TYPE { @@ -196,7 +199,7 @@ index c791c7fa..066246bb 100644 #define OFDMA_DL BIT(0) #define OFDMA_UL BIT(1) diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index d77a5f0c..827ee295 100644 +index b716b57..ec33afd 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h @@ -293,6 +293,7 @@ struct mt7915_phy { @@ -207,7 +210,7 @@ index d77a5f0c..827ee295 100644 u8 stats_work_count; struct list_head stats_list; -@@ -753,6 +754,9 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, +@@ -768,6 +769,9 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, struct ieee80211_sta *sta); #endif @@ -218,10 +221,10 @@ index d77a5f0c..827ee295 100644 int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir); int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp); diff --git a/mt7915/regs.h b/mt7915/regs.h -index 67837975..44863e88 100644 +index 1236da9..7e9b76b 100644 --- a/mt7915/regs.h +++ b/mt7915/regs.h -@@ -1209,6 +1209,8 @@ enum offs_rev { +@@ -1211,6 +1211,8 @@ enum offs_rev { #define MT_WF_IRPI_NSS(phy, nss) MT_WF_IRPI(0x6000 + ((phy) << 20) + ((nss) << 16)) #define MT_WF_IRPI_NSS_MT7916(phy, nss) MT_WF_IRPI(0x1000 + ((phy) << 20) + ((nss) << 16)) @@ -231,7 +234,7 @@ index 67837975..44863e88 100644 #define MT_WF_PHY_BASE 0x83080000 #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) diff --git a/mt7915/testmode.c b/mt7915/testmode.c -index 453319e1..caa35906 100644 +index 453319e..caa3590 100644 --- a/mt7915/testmode.c +++ b/mt7915/testmode.c @@ -14,6 +14,12 @@ enum { @@ -558,7 +561,7 @@ index 453319e1..caa35906 100644 static int diff --git a/testmode.c b/testmode.c -index 898ef3ae..dc972e3e 100644 +index b1986ad..b369826 100644 --- a/testmode.c +++ b/testmode.c @@ -26,6 +26,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = { @@ -622,7 +625,7 @@ index 898ef3ae..dc972e3e 100644 nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) || (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) && diff --git a/testmode.h b/testmode.h -index 1d7aef86..b39cf511 100644 +index 1d7aef8..b39cf51 100644 --- a/testmode.h +++ b/testmode.h @@ -64,6 +64,20 @@ @@ -690,7 +693,7 @@ index 1d7aef86..b39cf511 100644 + #endif diff --git a/tools/fields.c b/tools/fields.c -index b0ee84d2..e2cf4b92 100644 +index b0ee84d..e2cf4b9 100644 --- a/tools/fields.c +++ b/tools/fields.c @@ -46,6 +46,14 @@ static const char * const testmode_txbf_act[] = { diff --git a/feeds/mediatek-sdk/mt76/patches/1013-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1012-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch similarity index 97% rename from feeds/mediatek-sdk/mt76/patches/1013-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1012-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch index e2a94c6d9..289bbe401 100644 --- a/feeds/mediatek-sdk/mt76/patches/1013-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1012-wifi-mt76-testmode-add-iBF-eBF-cal-and-cert-commands.patch @@ -1,8 +1,8 @@ -From 64977a81891bd66f57abbd4b35b02dfa815c2848 Mon Sep 17 00:00:00 2001 +From 2a34bd2105e5021dacaf30c90bb6816f107cabd4 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Thu, 15 Dec 2022 19:45:18 +0800 -Subject: [PATCH 1013/1049] wifi: mt76: testmode: add iBF/eBF cal and cert - commands with golden +Subject: [PATCH] wifi: mt76: testmode: add iBF/eBF cal and cert commands with + golden Signed-off-by: StanleyYP Wang --- @@ -25,7 +25,7 @@ Signed-off-by: StanleyYP Wang 16 files changed, 859 insertions(+), 325 deletions(-) diff --git a/mt76.h b/mt76.h -index 1abb6499..f13f40d1 100644 +index 53b0964..1455144 100644 --- a/mt76.h +++ b/mt76.h @@ -755,6 +755,7 @@ struct mt76_testmode_data { @@ -47,10 +47,10 @@ index 1abb6499..f13f40d1 100644 u32 tx_pending; u32 tx_queued; diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c -index 2b322b05..e23dd773 100644 +index 44cd646..15e61c9 100644 --- a/mt76_connac_mcu.c +++ b/mt76_connac_mcu.c -@@ -2680,6 +2680,7 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, +@@ -2688,6 +2688,7 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, u32 type = vif->p2p ? NETWORK_P2P : NETWORK_INFRA; struct bss_info_basic *bss; struct tlv *tlv; @@ -58,7 +58,7 @@ index 2b322b05..e23dd773 100644 tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); bss = (struct bss_info_basic *)tlv; -@@ -2739,6 +2740,8 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, +@@ -2747,6 +2748,8 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb, bss->dtim_period = vif->bss_conf.dtim_period; bss->phy_mode = mt76_connac_get_phy_mode(phy, vif, chandef->chan->band, NULL); @@ -68,7 +68,7 @@ index 2b322b05..e23dd773 100644 memcpy(bss->bssid, phy->macaddr, ETH_ALEN); } diff --git a/mt7915/mac.c b/mt7915/mac.c -index fe165275..9cbc7d85 100644 +index 7d3397e..d94a0d5 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c @@ -737,8 +737,10 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi, @@ -84,7 +84,7 @@ index fe165275..9cbc7d85 100644 txwi[6] |= cpu_to_le32(val); #endif diff --git a/mt7915/main.c b/mt7915/main.c -index 2a7ad8b2..d4d5a93c 100644 +index e53754c..69477f1 100644 --- a/mt7915/main.c +++ b/mt7915/main.c @@ -205,46 +205,37 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif) @@ -175,7 +175,7 @@ index 2a7ad8b2..d4d5a93c 100644 return ret; diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 61cf60e8..1707aaf7 100644 +index 2025ef3..f5042ae 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c @@ -199,6 +199,7 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, @@ -227,7 +227,7 @@ index 61cf60e8..1707aaf7 100644 if (enable) { mt7915_mcu_bss_rfch_tlv(skb, vif, phy); -@@ -3529,6 +3543,7 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band) +@@ -3582,6 +3596,7 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band) int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action) { @@ -235,7 +235,7 @@ index 61cf60e8..1707aaf7 100644 struct { u8 action; union { -@@ -3555,7 +3570,6 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action) +@@ -3608,7 +3623,6 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action) .action = action, }; @@ -243,7 +243,7 @@ index 61cf60e8..1707aaf7 100644 switch (action) { case MT_BF_SOUNDING_ON: req.snd.snd_mode = MT_BF_PROCESSING; -@@ -4800,6 +4814,9 @@ int mt7915_mcu_set_txbf_sound_info(struct mt7915_phy *phy, u8 action, +@@ -4847,6 +4861,9 @@ int mt7915_mcu_set_txbf_sound_info(struct mt7915_phy *phy, u8 action, req.he_opt = v2; req.glo_opt = v3; break; @@ -254,7 +254,7 @@ index 61cf60e8..1707aaf7 100644 return -EINVAL; } diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 066246bb..de17c579 100644 +index 066246b..de17c57 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -546,10 +546,12 @@ enum { @@ -448,7 +448,7 @@ index 066246bb..de17c579 100644 MURU_SET_ARB_OP_MODE = 14, MURU_SET_PLATFORM_TYPE = 25, diff --git a/mt7915/mmio.c b/mt7915/mmio.c -index 222e2cfd..ddf1b72a 100644 +index 222e2cf..ddf1b72 100644 --- a/mt7915/mmio.c +++ b/mt7915/mmio.c @@ -133,6 +133,7 @@ static const u32 mt7915_offs[] = { @@ -468,7 +468,7 @@ index 222e2cfd..ddf1b72a 100644 [AGG_AALCR0] = 0x028, [AGG_AWSCR0] = 0x030, diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 827ee295..42710e75 100644 +index ec33afd..700efaf 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h @@ -312,7 +312,6 @@ struct mt7915_phy { @@ -479,7 +479,7 @@ index 827ee295..42710e75 100644 bool bf_ever_en; } test; #endif -@@ -418,7 +417,7 @@ struct mt7915_dev { +@@ -426,7 +425,7 @@ struct mt7915_dev { void __iomem *dcm; void __iomem *sku; @@ -488,7 +488,7 @@ index 827ee295..42710e75 100644 struct { void *txbf_phase_cal; void *txbf_pfmu_data; -@@ -560,6 +559,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force); +@@ -574,6 +573,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force); int mt7915_dma_start(struct mt7915_dev *dev, bool reset, bool wed_reset); int mt7915_txbf_init(struct mt7915_dev *dev); void mt7915_init_txpower(struct mt7915_phy *phy); @@ -496,13 +496,14 @@ index 827ee295..42710e75 100644 void mt7915_reset(struct mt7915_dev *dev); int mt7915_run(struct ieee80211_hw *hw); int mt7915_mcu_init(struct mt7915_dev *dev); -@@ -640,10 +640,12 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); +@@ -654,11 +654,13 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb); void mt7915_mcu_exit(struct mt7915_dev *dev); -int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb); -void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb); void mt7915_mcu_wmm_pbc_work(struct work_struct *work); + int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif); +#ifdef CONFIG_NL80211_TESTMODE +void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb); @@ -511,7 +512,7 @@ index 827ee295..42710e75 100644 static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev) { return is_mt7915(&dev->mt76) ? MT7915_WTBL_SIZE : MT7916_WTBL_SIZE; -@@ -777,4 +779,10 @@ enum { +@@ -792,4 +794,10 @@ enum { #endif @@ -523,7 +524,7 @@ index 827ee295..42710e75 100644 + #endif diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 6ff9b10d..e13b98d0 100644 +index 84f8fae..9e490ad 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c @@ -2888,6 +2888,36 @@ mt7915_txpower_level_set(void *data, u64 val) @@ -563,7 +564,7 @@ index 6ff9b10d..e13b98d0 100644 /* usage: echo 0x[arg3][arg2][arg1] > fw_wa_set */ static int mt7915_wa_set(void *data, u64 val) -@@ -3770,6 +3800,11 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3777,6 +3807,11 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) debugfs_create_file("txpower_level", 0400, dir, dev, &fops_txpower_level); @@ -576,7 +577,7 @@ index 6ff9b10d..e13b98d0 100644 return 0; diff --git a/mt7915/mtk_mcu.c b/mt7915/mtk_mcu.c -index 143dae26..7a2d28c7 100644 +index 143dae2..7a2d28c 100644 --- a/mt7915/mtk_mcu.c +++ b/mt7915/mtk_mcu.c @@ -1,9 +1,10 @@ @@ -840,7 +841,7 @@ index 143dae26..7a2d28c7 100644 +} +#endif diff --git a/mt7915/regs.h b/mt7915/regs.h -index 44863e88..1f1f8b9c 100644 +index 7e9b76b..4d05e39 100644 --- a/mt7915/regs.h +++ b/mt7915/regs.h @@ -61,6 +61,7 @@ enum offs_rev { @@ -862,7 +863,7 @@ index 44863e88..1f1f8b9c 100644 #define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000) #define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs)) diff --git a/mt7915/testmode.c b/mt7915/testmode.c -index caa35906..faf60146 100644 +index caa3590..faf6014 100644 --- a/mt7915/testmode.c +++ b/mt7915/testmode.c @@ -55,6 +55,8 @@ struct reg_band { @@ -1706,7 +1707,7 @@ index caa35906..faf60146 100644 rateval = mode << 6 | rate_idx; tx_cont->rateval = cpu_to_le16(rateval); diff --git a/mt7915/testmode.h b/mt7915/testmode.h -index 75698261..5aba13cf 100644 +index 7569826..5aba13c 100644 --- a/mt7915/testmode.h +++ b/mt7915/testmode.h @@ -311,137 +311,7 @@ struct mt7915_tm_muru { @@ -1850,7 +1851,7 @@ index 75698261..5aba13cf 100644 #endif diff --git a/testmode.c b/testmode.c -index dc972e3e..0dfed1e3 100644 +index b369826..a3e6d4a 100644 --- a/testmode.c +++ b/testmode.c @@ -196,6 +196,7 @@ mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len, @@ -1862,7 +1863,7 @@ index dc972e3e..0dfed1e3 100644 memcpy(hdr->addr2, addr[1], ETH_ALEN); memcpy(hdr->addr3, addr[2], ETH_ALEN); diff --git a/testmode.h b/testmode.h -index b39cf511..20fab3ec 100644 +index b39cf51..20fab3e 100644 --- a/testmode.h +++ b/testmode.h @@ -303,7 +303,10 @@ enum mt76_testmode_cfg { @@ -1890,7 +1891,7 @@ index b39cf511..20fab3ec 100644 /* keep last */ NUM_MT76_TM_TXBF_ACT, diff --git a/tools/fields.c b/tools/fields.c -index e2cf4b92..027b8cdb 100644 +index e2cf4b9..027b8cd 100644 --- a/tools/fields.c +++ b/tools/fields.c @@ -33,7 +33,10 @@ static const char * const testmode_tx_mode[] = { diff --git a/feeds/mediatek-sdk/mt76/patches/1015-wifi-mt76-connac-airtime-fairness-feature-off-in-mac.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1013-wifi-mt76-connac-airtime-fairness-feature-off-in-mac.patch similarity index 79% rename from feeds/mediatek-sdk/mt76/patches/1015-wifi-mt76-connac-airtime-fairness-feature-off-in-mac.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1013-wifi-mt76-connac-airtime-fairness-feature-off-in-mac.patch index 9d5e64947..cea0e5be1 100644 --- a/feeds/mediatek-sdk/mt76/patches/1015-wifi-mt76-connac-airtime-fairness-feature-off-in-mac.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1013-wifi-mt76-connac-airtime-fairness-feature-off-in-mac.patch @@ -1,7 +1,7 @@ -From 6cff1d3ae9c78598ee3828682c10b5936584083b Mon Sep 17 00:00:00 2001 +From b19594cf12b01dede83a984ca717e26be37bbfdd Mon Sep 17 00:00:00 2001 From: Evelyn Tsai Date: Fri, 6 May 2022 15:58:42 +0800 -Subject: [PATCH 1015/1049] wifi: mt76: connac: airtime fairness feature off in +Subject: [PATCH 1013/1053] wifi: mt76: connac: airtime fairness feature off in mac80211 --- @@ -9,7 +9,7 @@ Subject: [PATCH 1015/1049] wifi: mt76: connac: airtime fairness feature off in 1 file changed, 1 deletion(-) diff --git a/mac80211.c b/mac80211.c -index 305cae78..f9dfdf8c 100644 +index 305cae7..f9dfdf8 100644 --- a/mac80211.c +++ b/mac80211.c @@ -451,7 +451,6 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) diff --git a/feeds/mediatek-sdk/mt76/patches/1017-wifi-mt76-mt7915-add-phy-capability-vendor-command.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1014-wifi-mt76-mt7915-add-phy-capability-vendor-command.patch similarity index 94% rename from feeds/mediatek-sdk/mt76/patches/1017-wifi-mt76-mt7915-add-phy-capability-vendor-command.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1014-wifi-mt76-mt7915-add-phy-capability-vendor-command.patch index c6d638dec..7f75d0019 100644 --- a/feeds/mediatek-sdk/mt76/patches/1017-wifi-mt76-mt7915-add-phy-capability-vendor-command.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1014-wifi-mt76-mt7915-add-phy-capability-vendor-command.patch @@ -1,7 +1,7 @@ -From c5f0bbd2c4c256d8ef386421d7bbef1bfcf8b8cf Mon Sep 17 00:00:00 2001 +From 34cb90df1cfbbe69bb96a4eabd249e190d821e03 Mon Sep 17 00:00:00 2001 From: Yi-Chia Hsieh Date: Tue, 12 Jul 2022 10:04:35 -0700 -Subject: [PATCH 1017/1049] wifi: mt76: mt7915: add phy capability vendor +Subject: [PATCH 1014/1053] wifi: mt76: mt7915: add phy capability vendor command --- @@ -11,7 +11,7 @@ Subject: [PATCH 1017/1049] wifi: mt76: mt7915: add phy capability vendor 3 files changed, 78 insertions(+) diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 42710e75..87a63ec6 100644 +index b06e5ca..d21b843 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h @@ -11,6 +11,7 @@ @@ -23,7 +23,7 @@ index 42710e75..87a63ec6 100644 #define MT7916_WTBL_SIZE 544 #define MT7915_WTBL_RESERVED (mt7915_wtbl_size(dev) - 1) diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index a8b1fa84..757aecb6 100644 +index a8b1fa8..757aecb 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -51,6 +51,18 @@ rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL] = { @@ -100,7 +100,7 @@ index a8b1fa84..757aecb6 100644 }; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index a4a91804..34dd7d02 100644 +index a4a9180..34dd7d0 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -10,6 +10,7 @@ enum mtk_nl80211_vendor_subcmds { diff --git a/feeds/mediatek-sdk/mt76/patches/1018-wifi-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1015-wifi-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable.patch similarity index 93% rename from feeds/mediatek-sdk/mt76/patches/1018-wifi-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1015-wifi-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable.patch index 4e94fc5eb..14f77a57f 100644 --- a/feeds/mediatek-sdk/mt76/patches/1018-wifi-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1015-wifi-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable.patch @@ -1,33 +1,33 @@ -From 898ec79a07baeb435f54b3747b965f8e9a13b155 Mon Sep 17 00:00:00 2001 +From 7f9793b9c724014e9993091b47566cd9bf3cec06 Mon Sep 17 00:00:00 2001 From: Howard Hsu Date: Fri, 24 Jun 2022 11:15:45 +0800 -Subject: [PATCH 1018/1049] wifi: mt76: mt7915: add vendor subcmd EDCCA ctrl +Subject: [PATCH] wifi: mt76: mt7915: add vendor subcmd EDCCA ctrl enable/threshold/compensation --- mt76_connac_mcu.h | 1 + mt7915/main.c | 3 ++ - mt7915/mcu.c | 73 +++++++++++++++++++++++++ + mt7915/mcu.c | 72 +++++++++++++++++++++++++ mt7915/mcu.h | 21 ++++++++ mt7915/mt7915.h | 3 +- mt7915/vendor.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++ mt7915/vendor.h | 33 ++++++++++++ - 7 files changed, 265 insertions(+), 1 deletion(-) + 7 files changed, 264 insertions(+), 1 deletion(-) diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 4d85d323..8dba184d 100644 +index 9ac1c46..012f9be 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1243,6 +1243,7 @@ enum { - MCU_EXT_CMD_SMESH_CTRL = 0xae, +@@ -1252,6 +1252,7 @@ enum { MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3, + MCU_EXT_CMD_SET_QOS_MAP = 0xb4, MCU_EXT_CMD_CERT_CFG = 0xb7, + MCU_EXT_CMD_EDCCA = 0xba, MCU_EXT_CMD_CSI_CTRL = 0xc2, MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5, }; diff --git a/mt7915/main.c b/mt7915/main.c -index 0a3e8e0b..3f07183b 100644 +index 69477f1..d0ba4b7 100644 --- a/mt7915/main.c +++ b/mt7915/main.c @@ -479,6 +479,9 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed) @@ -41,14 +41,13 @@ index 0a3e8e0b..3f07183b 100644 ret = mt7915_set_channel(phy); if (ret) diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index b21d888b..697e9641 100644 +index f5042ae..20395e9 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -5026,3 +5026,76 @@ int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool w - +@@ -5038,6 +5038,78 @@ int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool w return 0; } -+ + +int mt7915_mcu_set_edcca(struct mt7915_phy *phy, int mode, u8 *value, s8 compensation) +{ + static const u8 ch_band[] = { @@ -88,7 +87,6 @@ index b21d888b..697e9641 100644 + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCCA), &req, sizeof(req), true); +} + -+ +int mt7915_mcu_get_edcca(struct mt7915_phy *phy, u8 mode, s8 *value) +{ + struct mt7915_dev *dev = phy->dev; @@ -121,8 +119,12 @@ index b21d888b..697e9641 100644 + + return 0; +} ++ + int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif) + { + #define IP_DSCP_NUM 64 diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index de17c579..1682c117 100644 +index de17c57..1682c11 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -1128,6 +1128,27 @@ enum { @@ -154,10 +156,10 @@ index de17c579..1682c117 100644 #endif diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 87a63ec6..03df15e3 100644 +index d4a3467..8da1d1b 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -756,7 +756,8 @@ void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb); +@@ -771,7 +771,8 @@ void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb); int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, struct ieee80211_sta *sta); #endif @@ -168,7 +170,7 @@ index 87a63ec6..03df15e3 100644 int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool wait_resp); diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index 757aecb6..3a586846 100644 +index 757aecb..3a58684 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -63,6 +63,24 @@ phy_capa_dump_policy[NUM_MTK_VENDOR_ATTRS_PHY_CAPA_DUMP] = { @@ -325,7 +327,7 @@ index 757aecb6..3a586846 100644 }; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 34dd7d02..284994a2 100644 +index 34dd7d0..284994a 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -3,6 +3,7 @@ diff --git a/feeds/mediatek-sdk/mt76/patches/1019-wifi-mt76-mt7915-implement-bin-file-mode.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1016-wifi-mt76-mt7915-implement-bin-file-mode.patch similarity index 88% rename from feeds/mediatek-sdk/mt76/patches/1019-wifi-mt76-mt7915-implement-bin-file-mode.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1016-wifi-mt76-mt7915-implement-bin-file-mode.patch index 788fb6e68..792580c08 100644 --- a/feeds/mediatek-sdk/mt76/patches/1019-wifi-mt76-mt7915-implement-bin-file-mode.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1016-wifi-mt76-mt7915-implement-bin-file-mode.patch @@ -1,7 +1,7 @@ -From d8e7248fced3ef582b88830e8d6a25e445ccf0d9 Mon Sep 17 00:00:00 2001 +From 9291fdb4f324728e5f4e233a08282f828cc04b80 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Thu, 7 Jul 2022 11:09:59 +0800 -Subject: [PATCH 1019/1049] wifi: mt76: mt7915: implement bin file mode +Subject: [PATCH 1016/1053] wifi: mt76: mt7915: implement bin file mode Signed-off-by: StanleyYP Wang Signed-off-by: Shayne Chen @@ -16,7 +16,7 @@ Signed-off-by: Shayne Chen 7 files changed, 144 insertions(+), 4 deletions(-) diff --git a/eeprom.c b/eeprom.c -index 3625b169..9d029c04 100644 +index 3625b16..9d029c0 100644 --- a/eeprom.c +++ b/eeprom.c @@ -161,6 +161,31 @@ static int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int len) @@ -52,7 +52,7 @@ index 3625b169..9d029c04 100644 mt76_eeprom_override(struct mt76_phy *phy) { diff --git a/mt76.h b/mt76.h -index f13f40d1..6ce598f9 100644 +index 8025e04..48e98a3 100644 --- a/mt76.h +++ b/mt76.h @@ -983,6 +983,9 @@ struct mt76_dev { @@ -74,7 +74,7 @@ index f13f40d1..6ce598f9 100644 struct mt76_queue * mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, diff --git a/mt7915/eeprom.c b/mt7915/eeprom.c -index 5e74b5ff..3c99b4d3 100644 +index f4876fe..c8b1c18 100644 --- a/mt7915/eeprom.c +++ b/mt7915/eeprom.c @@ -5,6 +5,30 @@ @@ -108,7 +108,7 @@ index 5e74b5ff..3c99b4d3 100644 static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) { struct mt76_dev *mdev = &dev->mt76; -@@ -25,6 +49,9 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) +@@ -24,6 +48,9 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2; @@ -118,7 +118,7 @@ index 5e74b5ff..3c99b4d3 100644 ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size); if (!ret) return ret; -@@ -52,8 +79,11 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev) +@@ -59,8 +86,11 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev) } } @@ -131,7 +131,7 @@ index 5e74b5ff..3c99b4d3 100644 switch (mt76_chip(&dev->mt76)) { case 0x7915: return dev->dbdc_support ? -@@ -94,7 +124,10 @@ mt7915_eeprom_load_default(struct mt7915_dev *dev) +@@ -101,7 +131,10 @@ mt7915_eeprom_load_default(struct mt7915_dev *dev) return ret; if (!fw || !fw->data) { @@ -143,7 +143,7 @@ index 5e74b5ff..3c99b4d3 100644 ret = -EINVAL; goto out; } -@@ -119,6 +152,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) +@@ -126,6 +159,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) if (ret) { dev->flash_mode = true; @@ -151,7 +151,7 @@ index 5e74b5ff..3c99b4d3 100644 } else { u8 free_block_num; u32 block_num, i; -@@ -139,6 +173,8 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) +@@ -146,6 +180,8 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) if (ret < 0) return ret; } @@ -160,7 +160,7 @@ index 5e74b5ff..3c99b4d3 100644 } return mt7915_check_eeprom(dev); -@@ -244,12 +280,33 @@ int mt7915_eeprom_init(struct mt7915_dev *dev) +@@ -251,12 +287,33 @@ int mt7915_eeprom_init(struct mt7915_dev *dev) { int ret; @@ -196,10 +196,10 @@ index 5e74b5ff..3c99b4d3 100644 if (ret) return ret; diff --git a/mt7915/eeprom.h b/mt7915/eeprom.h -index 4a313759..a1ab05a7 100644 +index 509fb43..99101f9 100644 --- a/mt7915/eeprom.h +++ b/mt7915/eeprom.h -@@ -108,6 +108,13 @@ enum mt7915_sku_rate_group { +@@ -109,6 +109,13 @@ enum mt7915_sku_rate_group { MAX_SKU_RATE_GROUP_NUM, }; @@ -214,10 +214,10 @@ index 4a313759..a1ab05a7 100644 mt7915_get_channel_group_5g(int channel, bool is_7976) { diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 03df15e3..f3e38bc4 100644 +index 000751b..a06a46e 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -389,6 +389,8 @@ struct mt7915_dev { +@@ -397,6 +397,8 @@ struct mt7915_dev { bool dbdc_support; bool flash_mode; @@ -226,7 +226,7 @@ index 03df15e3..f3e38bc4 100644 bool muru_debug; bool ibf; -@@ -769,6 +771,7 @@ void mt7915_dump_tmac_info(u8 *tmac_info); +@@ -783,6 +785,7 @@ void mt7915_dump_tmac_info(u8 *tmac_info); int mt7915_mcu_set_txpower_level(struct mt7915_phy *phy, u8 drop_level); void mt7915_packet_log_to_host(struct mt7915_dev *dev, const void *data, int len, int type, int des_len); int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable); @@ -235,7 +235,7 @@ index 03df15e3..f3e38bc4 100644 #define PKT_BIN_DEBUG_MAGIC 0xc8763123 enum { diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index e13b98d0..9b69cfb4 100644 +index 30c5f68..02e0db3 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c @@ -3,6 +3,7 @@ @@ -246,7 +246,7 @@ index e13b98d0..9b69cfb4 100644 #ifdef MTK_DEBUG #define LWTBL_IDX2BASE_ID GENMASK(14, 8) -@@ -3721,6 +3722,47 @@ static int mt7915_fw_wm_info_read(struct seq_file *s, void *data) +@@ -3728,6 +3729,47 @@ static int mt7915_fw_wm_info_read(struct seq_file *s, void *data) return 0; } @@ -294,7 +294,7 @@ index e13b98d0..9b69cfb4 100644 int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) { struct mt7915_dev *dev = phy->dev; -@@ -3807,6 +3849,8 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3814,6 +3856,8 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable); @@ -304,7 +304,7 @@ index e13b98d0..9b69cfb4 100644 } #endif diff --git a/testmode.h b/testmode.h -index 20fab3ec..91d1e867 100644 +index 20fab3e..91d1e86 100644 --- a/testmode.h +++ b/testmode.h @@ -17,7 +17,7 @@ diff --git a/feeds/mediatek-sdk/mt76/patches/1020-wifi-mt76-mt7915-Add-mu-dump-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1017-wifi-mt76-mt7915-Add-mu-dump-support.patch similarity index 91% rename from feeds/mediatek-sdk/mt76/patches/1020-wifi-mt76-mt7915-Add-mu-dump-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1017-wifi-mt76-mt7915-Add-mu-dump-support.patch index 705ef2312..a8a9084f4 100644 --- a/feeds/mediatek-sdk/mt76/patches/1020-wifi-mt76-mt7915-Add-mu-dump-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1017-wifi-mt76-mt7915-Add-mu-dump-support.patch @@ -1,7 +1,7 @@ -From dcebd512eefcd6d8a8d3ab727d03284d8414a633 Mon Sep 17 00:00:00 2001 +From 7a381293087e8d94349e5488936e53f884730787 Mon Sep 17 00:00:00 2001 From: TomLiu Date: Thu, 11 Aug 2022 18:09:45 -0700 -Subject: [PATCH 1020/1049] wifi: mt76: mt7915: Add mu dump support +Subject: [PATCH 1017/1053] wifi: mt76: mt7915: Add mu dump support --- mt7915/vendor.c | 24 ++++++++++++++++++++++++ @@ -9,7 +9,7 @@ Subject: [PATCH 1020/1049] wifi: mt76: mt7915: Add mu dump support 2 files changed, 25 insertions(+) diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index 3a586846..ac6f6371 100644 +index 3a58684..ac6f637 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -38,6 +38,7 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = { @@ -58,7 +58,7 @@ index 3a586846..ac6f6371 100644 .maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX, }, diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 284994a2..8c2a996d 100644 +index 284994a..8c2a996 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -73,6 +73,7 @@ enum mtk_vendor_attr_mu_ctrl { diff --git a/feeds/mediatek-sdk/mt76/patches/1021-wifi-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ct.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1018-wifi-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ct.patch similarity index 93% rename from feeds/mediatek-sdk/mt76/patches/1021-wifi-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ct.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1018-wifi-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ct.patch index 6fcb81389..6718ab8fb 100644 --- a/feeds/mediatek-sdk/mt76/patches/1021-wifi-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ct.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1018-wifi-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ct.patch @@ -1,8 +1,7 @@ -From 856646106a7f8ad511515c743931e197eb7ef886 Mon Sep 17 00:00:00 2001 +From 35c3c602288b8c1a11b9c1ca4e1b0182d451d15e Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Fri, 28 Oct 2022 10:15:56 +0800 -Subject: [PATCH 1021/1049] wifi: mt76: mt7915: add vendor subcmd three wire - (PTA) ctrl +Subject: [PATCH] wifi: mt76: mt7915: add vendor subcmd three wire (PTA) ctrl Signed-off-by: StanleyYP Wang --- @@ -15,23 +14,23 @@ Signed-off-by: StanleyYP Wang 6 files changed, 111 insertions(+), 29 deletions(-) diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 8dba184d..6f6a889b 100644 +index 012f9be..7e12c05 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1242,7 +1242,7 @@ enum { - /* for vendor csi and air monitor */ +@@ -1251,7 +1251,7 @@ enum { MCU_EXT_CMD_SMESH_CTRL = 0xae, MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3, + MCU_EXT_CMD_SET_QOS_MAP = 0xb4, - MCU_EXT_CMD_CERT_CFG = 0xb7, + MCU_EXT_CMD_SET_CFG = 0xb7, MCU_EXT_CMD_EDCCA = 0xba, MCU_EXT_CMD_CSI_CTRL = 0xc2, MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5, diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 697e9641..f793a957 100644 +index 20395e9..8f5fcbb 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -4725,37 +4725,33 @@ void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable) +@@ -4736,37 +4736,33 @@ void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable) &req, sizeof(req), false); } @@ -93,7 +92,7 @@ index 697e9641..f793a957 100644 void mt7915_mcu_set_bypass_smthint(struct mt7915_phy *phy, u8 val) diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 1682c117..1b0bd06b 100644 +index 1682c11..1b0bd06 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -916,6 +916,35 @@ struct mt7915_mcu_rdd_ipi_scan { @@ -133,10 +132,10 @@ index 1682c117..1b0bd06b 100644 #define OFDMA_DL BIT(0) #define OFDMA_UL BIT(1) diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index f3e38bc4..e01afea8 100644 +index 27b007b..f9ca9d5 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -750,6 +750,7 @@ void mt7915_mcu_set_mimo(struct mt7915_phy *phy, u8 direction); +@@ -765,6 +765,7 @@ void mt7915_mcu_set_mimo(struct mt7915_phy *phy, u8 direction); void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable); int mt7915_mcu_set_mu_edca(struct mt7915_phy *phy, u8 val); void mt7915_mcu_set_cert(struct mt7915_phy *phy, u8 type); @@ -145,7 +144,7 @@ index f3e38bc4..e01afea8 100644 void mt7915_vendor_register(struct mt7915_phy *phy); int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode, diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index ac6f6371..eeac18d2 100644 +index ac6f637..eeac18d 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -41,6 +41,11 @@ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = { @@ -228,7 +227,7 @@ index ac6f6371..eeac18d2 100644 }; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 8c2a996d..e61a6aaa 100644 +index 8c2a996..e61a6aa 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -13,6 +13,7 @@ enum mtk_nl80211_vendor_subcmds { diff --git a/feeds/mediatek-sdk/mt76/patches/1022-wifi-mt76-mt7915-add-ibf-control-vendor-cmd.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1019-wifi-mt76-mt7915-add-ibf-control-vendor-cmd.patch similarity index 95% rename from feeds/mediatek-sdk/mt76/patches/1022-wifi-mt76-mt7915-add-ibf-control-vendor-cmd.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1019-wifi-mt76-mt7915-add-ibf-control-vendor-cmd.patch index a817d70f7..e0e3ce706 100644 --- a/feeds/mediatek-sdk/mt76/patches/1022-wifi-mt76-mt7915-add-ibf-control-vendor-cmd.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1019-wifi-mt76-mt7915-add-ibf-control-vendor-cmd.patch @@ -1,7 +1,7 @@ -From ec8eafeac5d328a72ebb6b473fd36dd8d096f89d Mon Sep 17 00:00:00 2001 +From 090c1e87976b841379871abfa75879dc115e4224 Mon Sep 17 00:00:00 2001 From: mtk27835 Date: Wed, 7 Sep 2022 14:01:29 -0700 -Subject: [PATCH 1022/1049] wifi: mt76: mt7915: add ibf control vendor cmd +Subject: [PATCH 1019/1053] wifi: mt76: mt7915: add ibf control vendor cmd Signed-off-by: mtk27835 --- @@ -10,7 +10,7 @@ Signed-off-by: mtk27835 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index eeac18d2..a21cbce2 100644 +index eeac18d..a21cbce 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -87,6 +87,11 @@ edcca_dump_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP] = { @@ -100,7 +100,7 @@ index eeac18d2..a21cbce2 100644 }; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index e61a6aaa..876edf34 100644 +index e61a6aa..876edf3 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -13,7 +13,8 @@ enum mtk_nl80211_vendor_subcmds { diff --git a/feeds/mediatek-sdk/mt76/patches/1023-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1020-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch similarity index 86% rename from feeds/mediatek-sdk/mt76/patches/1023-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1020-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch index 27b7261a9..dd8f1dd9f 100644 --- a/feeds/mediatek-sdk/mt76/patches/1023-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1020-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch @@ -1,7 +1,7 @@ -From 51d7a6fb8aba2306e617845ee954652af5930913 Mon Sep 17 00:00:00 2001 +From 0d530532bcd6795ff333eb7dafee44872c35c64b Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Thu, 30 Mar 2023 15:12:37 +0800 -Subject: [PATCH 1023/1049] wifi: mt76: mt7915: add cal free data merge support +Subject: [PATCH 1020/1053] wifi: mt76: mt7915: add cal free data merge support 1. add basic cal free data support 2. add E3 low yield rate workaround for panther E3 with 7976 adie @@ -11,18 +11,18 @@ Subject: [PATCH 1023/1049] wifi: mt76: mt7915: add cal free data merge support Signed-off-by: StanleyYP Wang --- - mt7915/debugfs.c | 41 +++++++++++ - mt7915/eeprom.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/debugfs.c | 41 ++++++++++ + mt7915/eeprom.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++- mt7915/eeprom.h | 2 + mt7915/mcu.c | 13 +++- mt7915/mt7915.h | 1 + - 5 files changed, 240 insertions(+), 4 deletions(-) + 5 files changed, 250 insertions(+), 6 deletions(-) diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c -index f1813776..40a126fa 100644 +index 2661386..5c08910 100644 --- a/mt7915/debugfs.c +++ b/mt7915/debugfs.c -@@ -1240,6 +1240,46 @@ mt7915_rf_regval_set(void *data, u64 val) +@@ -1241,6 +1241,46 @@ mt7915_rf_regval_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get, mt7915_rf_regval_set, "0x%08llx\n"); @@ -69,7 +69,7 @@ index f1813776..40a126fa 100644 int mt7915_init_debugfs(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; -@@ -1282,6 +1322,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) +@@ -1283,6 +1323,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir, mt7915_rdd_monitor); } @@ -78,10 +78,34 @@ index f1813776..40a126fa 100644 if (!ext_phy) dev->debugfs_dir = dir; diff --git a/mt7915/eeprom.c b/mt7915/eeprom.c -index 3c99b4d3..e11ae5e9 100644 +index c8b1c18..6133c20 100644 --- a/mt7915/eeprom.c +++ b/mt7915/eeprom.c -@@ -276,6 +276,189 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, +@@ -48,8 +48,13 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) + + offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2; + +- if (dev->bin_file_mode) +- return mt7915_eeprom_load_precal_binfile(dev, offs, size); ++ if (dev->bin_file_mode) { ++ ret = mt7915_eeprom_load_precal_binfile(dev, offs, size); ++ if (ret) ++ goto out; ++ ++ return 0; ++ } + + ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size); + if (!ret) +@@ -59,6 +64,7 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) + if (!ret) + return ret; + ++out: + dev_warn(mdev->dev, "missing precal data, size=%d\n", size); + devm_kfree(mdev->dev, dev->cal); + dev->cal = NULL; +@@ -283,6 +289,191 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, dev->chainshift = hweight8(dev->mphy.chainmask); } @@ -143,7 +167,9 @@ index 3c99b4d3..e11ae5e9 100644 + case 0x7915: + ddie_offs = ddie_offs_list[DDIE_7915]; + ret = mt7915_mcu_get_eeprom(dev, MT_EE_ADIE_FT_VERSION, buf); -+ if (ret) ++ if (ret == -EINVAL) ++ return 0; ++ else if (ret) + return ret; + adie_id = buf[MT_EE_ADIE_FT_VERSION % MT7915_EEPROM_BLOCK_SIZE] - 1; + adie_offs[0] = adie_offs_list[ADIE_7975]; @@ -271,10 +297,10 @@ index 3c99b4d3..e11ae5e9 100644 int mt7915_eeprom_init(struct mt7915_dev *dev) { int ret; -@@ -316,6 +499,10 @@ int mt7915_eeprom_init(struct mt7915_dev *dev) - if (ret) - return ret; +@@ -320,6 +511,10 @@ int mt7915_eeprom_init(struct mt7915_dev *dev) + } + mt7915_eeprom_load_precal(dev); + ret = mt7915_apply_cal_free_data(dev); + if (ret) + return ret; @@ -283,10 +309,10 @@ index 3c99b4d3..e11ae5e9 100644 memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN); diff --git a/mt7915/eeprom.h b/mt7915/eeprom.h -index a1ab05a7..dd450aac 100644 +index 99101f9..70fca0b 100644 --- a/mt7915/eeprom.h +++ b/mt7915/eeprom.h -@@ -67,6 +67,8 @@ enum mt7915_eeprom_field { +@@ -68,6 +68,8 @@ enum mt7915_eeprom_field { #define MT_EE_RATE_DELTA_SIGN BIT(6) #define MT_EE_RATE_DELTA_EN BIT(7) @@ -296,7 +322,7 @@ index a1ab05a7..dd450aac 100644 MT7976_ONE_ADIE_DBDC = 0x7, MT7975_ONE_ADIE = 0x8, diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index f793a957..0694c9a6 100644 +index 072185f..1262206 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c @@ -2968,6 +2968,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf) @@ -327,10 +353,10 @@ index f793a957..0694c9a6 100644 dev_kfree_skb(skb); diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index e01afea8..a74a4ebd 100644 +index 00d2b35..1e5cd94 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -548,6 +548,7 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id); +@@ -562,6 +562,7 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id); int mt7915_register_device(struct mt7915_dev *dev); void mt7915_unregister_device(struct mt7915_dev *dev); diff --git a/feeds/mediatek-sdk/mt76/patches/1024-wifi-mt76-mt7915-support-on-off-SW-ACI-through-debug.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1021-wifi-mt76-mt7915-support-on-off-SW-ACI-through-debug.patch similarity index 81% rename from feeds/mediatek-sdk/mt76/patches/1024-wifi-mt76-mt7915-support-on-off-SW-ACI-through-debug.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1021-wifi-mt76-mt7915-support-on-off-SW-ACI-through-debug.patch index d453f104a..59e269015 100644 --- a/feeds/mediatek-sdk/mt76/patches/1024-wifi-mt76-mt7915-support-on-off-SW-ACI-through-debug.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1021-wifi-mt76-mt7915-support-on-off-SW-ACI-through-debug.patch @@ -1,7 +1,7 @@ -From f22d2143a18d36aa46bf0c839ee6482fe85e40c6 Mon Sep 17 00:00:00 2001 +From 43d77d4dd7c55898fea4df333be72e77b5571eab Mon Sep 17 00:00:00 2001 From: Evelyn Tsai Date: Fri, 14 Oct 2022 11:15:13 +0800 -Subject: [PATCH 1024/1049] wifi: mt76: mt7915: support on off SW ACI through +Subject: [PATCH 1021/1053] wifi: mt76: mt7915: support on off SW ACI through debugfs Signed-off-by: Evelyn Tsai @@ -11,10 +11,10 @@ Signed-off-by: Evelyn Tsai 2 files changed, 22 insertions(+) diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 6f6a889b..12654017 100644 +index 109462a..c6a43dd 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1244,6 +1244,7 @@ enum { +@@ -1252,6 +1252,7 @@ enum { MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3, MCU_EXT_CMD_SET_CFG = 0xb7, MCU_EXT_CMD_EDCCA = 0xba, @@ -23,10 +23,10 @@ index 6f6a889b..12654017 100644 MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5, }; diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 9b69cfb4..5d10a622 100644 +index 02e0db3..a433e67 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c -@@ -3763,6 +3763,25 @@ static int mt7915_show_eeprom_mode(struct seq_file *s, void *data) +@@ -3770,6 +3770,25 @@ static int mt7915_show_eeprom_mode(struct seq_file *s, void *data) return 0; } @@ -52,7 +52,7 @@ index 9b69cfb4..5d10a622 100644 int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) { struct mt7915_dev *dev = phy->dev; -@@ -3851,6 +3870,8 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3858,6 +3877,8 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) debugfs_create_devm_seqfile(dev->mt76.dev, "eeprom_mode", dir, mt7915_show_eeprom_mode); diff --git a/feeds/mediatek-sdk/mt76/patches/1025-wifi-mt76-mt7915-add-bf-backoff-limit-table-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1022-wifi-mt76-mt7915-add-bf-backoff-limit-table-support.patch similarity index 92% rename from feeds/mediatek-sdk/mt76/patches/1025-wifi-mt76-mt7915-add-bf-backoff-limit-table-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1022-wifi-mt76-mt7915-add-bf-backoff-limit-table-support.patch index f50870540..9030b991a 100644 --- a/feeds/mediatek-sdk/mt76/patches/1025-wifi-mt76-mt7915-add-bf-backoff-limit-table-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1022-wifi-mt76-mt7915-add-bf-backoff-limit-table-support.patch @@ -1,13 +1,12 @@ -From 60c2b729305ef69e6dd0afdfbbb0328ea13aab05 Mon Sep 17 00:00:00 2001 +From ff7ce1171852dedcaec49ea0de398dfea04aaced Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Mon, 5 Dec 2022 18:21:51 +0800 -Subject: [PATCH 1025/1049] wifi: mt76: mt7915: add bf backoff limit table - support +Subject: [PATCH] wifi: mt76: mt7915: add bf backoff limit table support Signed-off-by: Shayne Chen --- debugfs.c | 4 +- - eeprom.c | 43 ++++++++++-- + eeprom.c | 38 ++++++++-- mt76.h | 8 +++ mt7915/debugfs.c | 73 +++++++++++++++++-- mt7915/init.c | 7 ++ @@ -15,10 +14,10 @@ Signed-off-by: Shayne Chen mt7915/mcu.c | 178 +++++++++++++++++++++++++++++++++++++---------- mt7915/mcu.h | 6 ++ mt7915/mt7915.h | 9 ++- - 9 files changed, 279 insertions(+), 55 deletions(-) + 9 files changed, 275 insertions(+), 54 deletions(-) diff --git a/debugfs.c b/debugfs.c -index 1c8328d5..a626f7cf 100644 +index 1c8328d..a626f7c 100644 --- a/debugfs.c +++ b/debugfs.c @@ -95,9 +95,9 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str, @@ -34,7 +33,7 @@ index 1c8328d5..a626f7cf 100644 } EXPORT_SYMBOL_GPL(mt76_seq_puts_array); diff --git a/eeprom.c b/eeprom.c -index 9d029c04..4213e444 100644 +index 9d029c0..aa33e7b 100644 --- a/eeprom.c +++ b/eeprom.c @@ -336,9 +336,10 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data, @@ -76,7 +75,7 @@ index 9d029c04..4213e444 100644 if (!IS_ENABLED(CONFIG_OF)) return target_power; -@@ -428,14 +433,40 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, +@@ -428,12 +433,35 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1); mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]), ARRAY_SIZE(dest->mcs), val, len, @@ -88,8 +87,7 @@ index 9d029c04..4213e444 100644 ARRAY_SIZE(dest->ru), val, len, - target_power, txs_delta, &max_power); + target_power, txs_delta); - -- return max_power; ++ + max_power_backoff = max_power; + val = mt76_get_of_array(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck)); + mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val, @@ -112,16 +110,11 @@ index 9d029c04..4213e444 100644 + mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]), + ARRAY_SIZE(dest->path.ru_bf), val, len, + target_power_combine, txs_delta); -+ -+ if (max_power_backoff == target_power_combine) -+ return max_power; -+ -+ return max_power_backoff; - } - EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits); + return max_power; + } diff --git a/mt76.h b/mt76.h -index 6ce598f9..051afa76 100644 +index 48e98a3..5c26715 100644 --- a/mt76.h +++ b/mt76.h @@ -1089,6 +1089,14 @@ struct mt76_power_limits { @@ -140,10 +133,10 @@ index 6ce598f9..051afa76 100644 struct mt76_ethtool_worker_info { diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c -index 40a126fa..c7002ee0 100644 +index 5c08910..fa1d2ac 100644 --- a/mt7915/debugfs.c +++ b/mt7915/debugfs.c -@@ -1019,7 +1019,7 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, +@@ -1020,7 +1020,7 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; @@ -152,7 +145,7 @@ index 40a126fa..c7002ee0 100644 if (ret) goto out; -@@ -1133,7 +1133,7 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf, +@@ -1134,7 +1134,7 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf, mutex_lock(&dev->mt76.mutex); ret = mt7915_mcu_get_txpower_sku(phy, req.txpower_sku, @@ -161,7 +154,7 @@ index 40a126fa..c7002ee0 100644 if (ret) goto out; -@@ -1175,7 +1175,7 @@ out: +@@ -1176,7 +1176,7 @@ out: return ret ? ret : count; } @@ -170,7 +163,7 @@ index 40a126fa..c7002ee0 100644 .write = mt7915_rate_txpower_set, .read = mt7915_rate_txpower_get, .open = simple_open, -@@ -1183,6 +1183,69 @@ static const struct file_operations mt7915_rate_txpower_fops = { +@@ -1184,6 +1184,69 @@ static const struct file_operations mt7915_rate_txpower_fops = { .llseek = default_llseek, }; @@ -240,7 +233,7 @@ index 40a126fa..c7002ee0 100644 static int mt7915_twt_stats(struct seq_file *s, void *data) { -@@ -1309,7 +1372,9 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) +@@ -1310,7 +1373,9 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) debugfs_create_file("implicit_txbf", 0600, dir, dev, &fops_implicit_txbf); debugfs_create_file("txpower_sku", 0400, dir, phy, @@ -252,7 +245,7 @@ index 40a126fa..c7002ee0 100644 mt7915_twt_stats); debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); diff --git a/mt7915/init.c b/mt7915/init.c -index cdceb437..11598983 100644 +index 439403f..b32e213 100644 --- a/mt7915/init.c +++ b/mt7915/init.c @@ -284,6 +284,8 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy, @@ -277,7 +270,7 @@ index cdceb437..11598983 100644 target_power = DIV_ROUND_UP(target_power, 2); chan->max_power = min_t(int, chan->max_reg_power, diff --git a/mt7915/main.c b/mt7915/main.c -index 3f07183b..6192c20c 100644 +index 9fafa16..da7a87b 100644 --- a/mt7915/main.c +++ b/mt7915/main.c @@ -73,11 +73,7 @@ int mt7915_run(struct ieee80211_hw *hw) @@ -294,10 +287,10 @@ index 3f07183b..6192c20c 100644 goto out; diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 0694c9a6..3e41abd4 100644 +index 1262206..eb7638b 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -3405,7 +3405,8 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy, +@@ -3422,7 +3422,8 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy, int ret; s8 txpower_sku[MT7915_SKU_RATE_NUM]; @@ -307,7 +300,7 @@ index 0694c9a6..3e41abd4 100644 if (ret) return ret; -@@ -3445,53 +3446,139 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy, +@@ -3462,53 +3463,139 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy, sizeof(req), true); } @@ -474,7 +467,7 @@ index 0694c9a6..3e41abd4 100644 struct mt7915_dev *dev = phy->dev; struct { u8 format_id; -@@ -3500,10 +3587,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len) +@@ -3517,10 +3604,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len) u8 _rsv; } __packed req = { .format_id = TX_POWER_LIMIT_INFO, @@ -486,7 +479,7 @@ index 0694c9a6..3e41abd4 100644 struct sk_buff *skb; int ret, i; -@@ -3513,9 +3599,15 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len) +@@ -3530,9 +3616,15 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len) if (ret) return ret; @@ -505,7 +498,7 @@ index 0694c9a6..3e41abd4 100644 dev_kfree_skb(skb); -@@ -3544,7 +3636,7 @@ int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, +@@ -3561,7 +3653,7 @@ int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, sizeof(req), false); } @@ -514,7 +507,7 @@ index 0694c9a6..3e41abd4 100644 { struct mt7915_dev *dev = phy->dev; struct mt7915_sku { -@@ -3555,10 +3647,24 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable) +@@ -3572,10 +3664,24 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable) } __packed req = { .format_id = TX_POWER_LIMIT_ENABLE, .band_idx = phy->mt76->band_idx, @@ -542,7 +535,7 @@ index 0694c9a6..3e41abd4 100644 return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 1b0bd06b..94eff268 100644 +index 1b0bd06..94eff26 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -517,12 +517,18 @@ enum { @@ -565,7 +558,7 @@ index 1b0bd06b..94eff268 100644 SPR_ENABLE = 0x1, SPR_ENABLE_SD = 0x3, diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index a74a4ebd..bb4ef005 100644 +index 1e5cd94..826682b 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h @@ -72,6 +72,7 @@ @@ -586,7 +579,7 @@ index a74a4ebd..bb4ef005 100644 #ifdef CONFIG_NL80211_TESTMODE struct { u32 *reg_backup; -@@ -612,9 +616,10 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, +@@ -626,9 +630,10 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, u8 en); int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band); diff --git a/feeds/mediatek-sdk/mt76/patches/1026-wifi-mt76-mt7915-amsdu-set-and-get-control.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1023-wifi-mt76-mt7915-amsdu-set-and-get-control.patch similarity index 91% rename from feeds/mediatek-sdk/mt76/patches/1026-wifi-mt76-mt7915-amsdu-set-and-get-control.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1023-wifi-mt76-mt7915-amsdu-set-and-get-control.patch index 926f9c1ed..3bad2596a 100644 --- a/feeds/mediatek-sdk/mt76/patches/1026-wifi-mt76-mt7915-amsdu-set-and-get-control.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1023-wifi-mt76-mt7915-amsdu-set-and-get-control.patch @@ -1,7 +1,7 @@ -From 62256b474a49b89791008b202fe045bfd3c6de81 Mon Sep 17 00:00:00 2001 +From 568ebf749e43bade66a39a223a53918db8d71edf Mon Sep 17 00:00:00 2001 From: TomLiu Date: Wed, 14 Dec 2022 00:44:07 -0800 -Subject: [PATCH 1026/1049] wifi: mt76: mt7915: amsdu set and get control +Subject: [PATCH 1023/1053] wifi: mt76: mt7915: amsdu set and get control --- mt7915/mac.c | 7 +++++++ @@ -11,10 +11,10 @@ Subject: [PATCH 1026/1049] wifi: mt76: mt7915: amsdu set and get control 4 files changed, 50 insertions(+) diff --git a/mt7915/mac.c b/mt7915/mac.c -index 9cbc7d85..0c55259a 100644 +index d94a0d5..1e39ad2 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c -@@ -2037,6 +2037,13 @@ static void mt7915_mac_sta_stats_work(struct mt7915_phy *phy) +@@ -2035,6 +2035,13 @@ static void mt7915_mac_sta_stats_work(struct mt7915_phy *phy) spin_unlock_bh(&phy->stats_lock); } @@ -29,10 +29,10 @@ index 9cbc7d85..0c55259a 100644 void mt7915_capi_sta_rc_work(void *data, struct ieee80211_sta *sta) { diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index bb4ef005..36b583e4 100644 +index 826682b..fe7c211 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -744,6 +744,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, +@@ -758,6 +758,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, bool pci, int *irq); #ifdef CONFIG_MTK_VENDOR @@ -41,7 +41,7 @@ index bb4ef005..36b583e4 100644 void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif); void mt7915_mcu_set_rfeature_starec(void *data, struct mt7915_dev *dev, diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index a21cbce2..e25a0ce4 100644 +index a21cbce..e25a0ce 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -31,10 +31,16 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = { @@ -105,7 +105,7 @@ index a21cbce2..e25a0ce4 100644 .maxattr = MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX, }, diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 876edf34..7c4e9148 100644 +index 876edf3..7c4e914 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -75,6 +75,7 @@ enum mtk_vendor_attr_wireless_ctrl { diff --git a/feeds/mediatek-sdk/mt76/patches/1027-wifi-mt76-mt7915-Add-vendor-command-attribute-for-RT.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1024-wifi-mt76-mt7915-Add-vendor-command-attribute-for-RT.patch similarity index 89% rename from feeds/mediatek-sdk/mt76/patches/1027-wifi-mt76-mt7915-Add-vendor-command-attribute-for-RT.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1024-wifi-mt76-mt7915-Add-vendor-command-attribute-for-RT.patch index cb7aef46a..94d7b0e8b 100644 --- a/feeds/mediatek-sdk/mt76/patches/1027-wifi-mt76-mt7915-Add-vendor-command-attribute-for-RT.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1024-wifi-mt76-mt7915-Add-vendor-command-attribute-for-RT.patch @@ -1,7 +1,7 @@ -From 312d7539cca58504272d1e5227b390af4742f15b Mon Sep 17 00:00:00 2001 +From b6063c3c2566911919194c88cb9b68e68596d994 Mon Sep 17 00:00:00 2001 From: "himanshu.goyal" Date: Tue, 24 Jan 2023 14:32:08 +0800 -Subject: [PATCH 1027/1049] wifi: mt76: mt7915: Add vendor command attribute +Subject: [PATCH 1024/1053] wifi: mt76: mt7915: Add vendor command attribute for RTS BW signaling. Signed-off-by: himanshu.goyal @@ -13,10 +13,10 @@ Signed-off-by: himanshu.goyal 4 files changed, 20 insertions(+) diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 3e41abd4..6a3ffe83 100644 +index eb7638b..8e9b801 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -4852,6 +4852,12 @@ int mt7915_mcu_set_cfg(struct mt7915_phy *phy, u8 cfg_info, u8 type) +@@ -4863,6 +4863,12 @@ int mt7915_mcu_set_cfg(struct mt7915_phy *phy, u8 cfg_info, u8 type) req.cert.length = cpu_to_le16(tlv_len); req.cert.cert_program = type; break; @@ -30,7 +30,7 @@ index 3e41abd4..6a3ffe83 100644 tlv_len = sizeof(struct three_wire_cfg); req.three_wire.tag = cpu_to_le16(cfg_info); diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 94eff268..6ebcce0d 100644 +index 94eff26..6ebcce0 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -936,6 +936,13 @@ struct three_wire_cfg { @@ -62,7 +62,7 @@ index 94eff268..6ebcce0d 100644 }; diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index e25a0ce4..8370216f 100644 +index e25a0ce..8370216 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -34,6 +34,7 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = { @@ -84,7 +84,7 @@ index e25a0ce4..8370216f 100644 return 0; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 7c4e9148..3672420c 100644 +index 7c4e914..3672420 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -77,6 +77,7 @@ enum mtk_vendor_attr_wireless_ctrl { diff --git a/feeds/mediatek-sdk/mt76/patches/1028-wifi-mt76-mt7915-add-vendor-cmd-to-get-available-col.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1025-wifi-mt76-mt7915-add-vendor-cmd-to-get-available-col.patch similarity index 93% rename from feeds/mediatek-sdk/mt76/patches/1028-wifi-mt76-mt7915-add-vendor-cmd-to-get-available-col.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1025-wifi-mt76-mt7915-add-vendor-cmd-to-get-available-col.patch index 822516db0..df92c1abe 100644 --- a/feeds/mediatek-sdk/mt76/patches/1028-wifi-mt76-mt7915-add-vendor-cmd-to-get-available-col.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1025-wifi-mt76-mt7915-add-vendor-cmd-to-get-available-col.patch @@ -1,7 +1,7 @@ -From 28ddff16e74f385ba6dcc17f7bf80ccae9da0114 Mon Sep 17 00:00:00 2001 +From 9981c906450cc4758d975b98f89ff62a64529be6 Mon Sep 17 00:00:00 2001 From: Yi-Chia Hsieh Date: Thu, 26 Jan 2023 08:50:47 +0800 -Subject: [PATCH 1028/1049] wifi: mt76: mt7915: add vendor cmd to get available +Subject: [PATCH 1025/1053] wifi: mt76: mt7915: add vendor cmd to get available color bitmap Add a vendor cmd to notify user space available color bitmap. @@ -14,7 +14,7 @@ Signed-off-by: Yi-Chia Hsieh 2 files changed, 48 insertions(+) diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index 8370216f..9a26f7f4 100644 +index 8370216..9a26f7f 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -99,6 +99,11 @@ ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = { @@ -76,7 +76,7 @@ index 8370216f..9a26f7f4 100644 }; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 3672420c..bd1c6170 100644 +index 3672420..bd1c617 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -15,6 +15,7 @@ enum mtk_nl80211_vendor_subcmds { diff --git a/feeds/mediatek-sdk/mt76/patches/1029-wifi-mt76-mt7915-disable-SW-ACI-by-default.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1026-wifi-mt76-mt7915-disable-SW-ACI-by-default.patch similarity index 82% rename from feeds/mediatek-sdk/mt76/patches/1029-wifi-mt76-mt7915-disable-SW-ACI-by-default.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1026-wifi-mt76-mt7915-disable-SW-ACI-by-default.patch index 9be39a8bc..a6b71d541 100644 --- a/feeds/mediatek-sdk/mt76/patches/1029-wifi-mt76-mt7915-disable-SW-ACI-by-default.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1026-wifi-mt76-mt7915-disable-SW-ACI-by-default.patch @@ -1,7 +1,7 @@ -From 6007e84ff587eabae0932b6cb5cb128c179cd678 Mon Sep 17 00:00:00 2001 +From 0df14b3d2578681009ca9be604e98bb94ee1186a Mon Sep 17 00:00:00 2001 From: Howard Hsu Date: Fri, 24 Feb 2023 16:29:42 +0800 -Subject: [PATCH 1029/1049] wifi: mt76: mt7915: disable SW-ACI by default +Subject: [PATCH] wifi: mt76: mt7915: disable SW-ACI by default Support to enable/disable SW-ACI by module parameter "sw_aci_enable". SW-ACI feature is disable by default. @@ -13,7 +13,7 @@ SW-ACI feature is disable by default. 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/mt7915/main.c b/mt7915/main.c -index 6192c20c..acb4f44c 100644 +index b80d6fd..2ff7667 100644 --- a/mt7915/main.c +++ b/mt7915/main.c @@ -8,6 +8,10 @@ @@ -39,14 +39,13 @@ index 6192c20c..acb4f44c 100644 if (phy != &dev->phy) { diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 6a3ffe83..04016375 100644 +index 5534603..e95a5d7 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -5212,3 +5212,18 @@ int mt7915_mcu_get_edcca(struct mt7915_phy *phy, u8 mode, s8 *value) - +@@ -5223,6 +5223,21 @@ int mt7915_mcu_get_edcca(struct mt7915_phy *phy, u8 mode, s8 *value) return 0; } -+ + +int mt7915_mcu_sw_aci_set(struct mt7915_dev *dev, bool val) +{ +#define SWLNA_ENABLE 6 @@ -61,11 +60,15 @@ index 6a3ffe83..04016375 100644 + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SWLNA_ACI_CTRL), &req, + sizeof(req), NULL); +} ++ + int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif) + { + #define IP_DSCP_NUM 64 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 36b583e4..19100609 100644 +index 9e7183c..c8b697c 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -768,6 +768,7 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, +@@ -783,6 +783,7 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, #endif int mt7915_mcu_set_edcca(struct mt7915_phy *phy, int mode, u8 *value, s8 compensation); int mt7915_mcu_get_edcca(struct mt7915_phy *phy, u8 mode, s8 *value); @@ -74,10 +77,10 @@ index 36b583e4..19100609 100644 int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool wait_resp); diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 5d10a622..56b9e85e 100644 +index 8f2f496..ad7abda 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c -@@ -3766,16 +3766,12 @@ static int mt7915_show_eeprom_mode(struct seq_file *s, void *data) +@@ -3773,16 +3773,12 @@ static int mt7915_show_eeprom_mode(struct seq_file *s, void *data) static int mt7915_sw_aci_set(void *data, u64 val) { diff --git a/feeds/mediatek-sdk/mt76/patches/1030-wifi-mt76-mt7915-add-muru-user-number-debug-command.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1027-wifi-mt76-mt7915-add-muru-user-number-debug-command.patch similarity index 89% rename from feeds/mediatek-sdk/mt76/patches/1030-wifi-mt76-mt7915-add-muru-user-number-debug-command.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1027-wifi-mt76-mt7915-add-muru-user-number-debug-command.patch index 2e30b4a79..85afdcb9c 100644 --- a/feeds/mediatek-sdk/mt76/patches/1030-wifi-mt76-mt7915-add-muru-user-number-debug-command.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1027-wifi-mt76-mt7915-add-muru-user-number-debug-command.patch @@ -1,7 +1,7 @@ -From 860b187e5bc4f1f25c06fc8d26e48f3fd4e1c1ee Mon Sep 17 00:00:00 2001 +From ed2035d25794352ca10f4cdc04dd931b1ebfac50 Mon Sep 17 00:00:00 2001 From: MeiChia Chiu Date: Thu, 27 Apr 2023 15:37:33 +0800 -Subject: [PATCH 1030/1049] wifi: mt76: mt7915: add muru user number debug +Subject: [PATCH 1027/1053] wifi: mt76: mt7915: add muru user number debug command --- @@ -11,10 +11,10 @@ Subject: [PATCH 1030/1049] wifi: mt76: mt7915: add muru user number debug 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 19100609..34a671fa 100644 +index 44dd0f4..e5a201c 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -631,6 +631,7 @@ int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev, +@@ -645,6 +645,7 @@ int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev, int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index, const struct mt7915_dfs_pattern *pattern); int mt7915_mcu_set_muru_ctrl(struct mt7915_dev *dev, u32 cmd, u32 val); @@ -23,7 +23,7 @@ index 19100609..34a671fa 100644 int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy); int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch); diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index 9a26f7f4..432d7506 100644 +index 9a26f7f..432d750 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -46,6 +46,8 @@ static const struct nla_policy @@ -65,7 +65,7 @@ index 9a26f7f4..432d7506 100644 return 0; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index bd1c6170..03d1660c 100644 +index bd1c617..03d1660 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -103,6 +103,8 @@ enum mtk_vendor_attr_mu_ctrl { diff --git a/feeds/mediatek-sdk/mt76/patches/1031-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1028-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch similarity index 91% rename from feeds/mediatek-sdk/mt76/patches/1031-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1028-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch index 1c12101fa..480d7c676 100644 --- a/feeds/mediatek-sdk/mt76/patches/1031-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1028-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch @@ -1,7 +1,7 @@ -From 1e23798981b41fd30cbbe25259e2091b2aec940e Mon Sep 17 00:00:00 2001 +From 1eedf84cfc86e9b6e9de78509e85789025b1b3ac Mon Sep 17 00:00:00 2001 From: Bo Jiao Date: Mon, 22 May 2023 15:30:21 +0800 -Subject: [PATCH 1031/1049] wifi: mt76: mt7915: add debugfs for fw coredump. +Subject: [PATCH 1028/1053] wifi: mt76: mt7915: add debugfs for fw coredump. Signed-off-by: Bo Jiao --- @@ -12,7 +12,7 @@ Signed-off-by: Bo Jiao 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c -index c7002ee0..4c48b197 100644 +index fa1d2ac..3044557 100644 --- a/mt7915/debugfs.c +++ b/mt7915/debugfs.c @@ -82,8 +82,10 @@ mt7915_sys_recovery_set(struct file *file, const char __user *user_buf, @@ -67,10 +67,10 @@ index c7002ee0..4c48b197 100644 /* SER statistics */ desc += scnprintf(buff + desc, bufsz - desc, diff --git a/mt7915/mac.c b/mt7915/mac.c -index 0c55259a..7f4778f0 100644 +index 1e39ad2..14367fd 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c -@@ -1730,10 +1730,34 @@ void mt7915_mac_dump_work(struct work_struct *work) +@@ -1728,10 +1728,34 @@ void mt7915_mac_dump_work(struct work_struct *work) dev = container_of(work, struct mt7915_dev, dump_work); @@ -107,7 +107,7 @@ index 0c55259a..7f4778f0 100644 } void mt7915_reset(struct mt7915_dev *dev) -@@ -1752,7 +1776,7 @@ void mt7915_reset(struct mt7915_dev *dev) +@@ -1750,7 +1774,7 @@ void mt7915_reset(struct mt7915_dev *dev) wiphy_name(dev->mt76.hw->wiphy)); mt7915_irq_disable(dev, MT_INT_MCU_CMD); @@ -117,7 +117,7 @@ index 0c55259a..7f4778f0 100644 } diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 6ebcce0d..035ad97d 100644 +index 6ebcce0..035ad97 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -760,8 +760,12 @@ enum { @@ -135,7 +135,7 @@ index 6ebcce0d..035ad97d 100644 SER_ENABLE = 2, SER_RECOVER diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 34a671fa..e21a7a6a 100644 +index e5a201c..ea91611 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h @@ -91,6 +91,13 @@ struct mt7915_sta; @@ -152,7 +152,7 @@ index 34a671fa..e21a7a6a 100644 enum mt7915_txq_id { MT7915_TXQ_FWDL = 16, MT7915_TXQ_MCU_WM, -@@ -379,6 +386,7 @@ struct mt7915_dev { +@@ -387,6 +394,7 @@ struct mt7915_dev { /* protects coredump data */ struct mutex dump_mutex; @@ -160,7 +160,7 @@ index 34a671fa..e21a7a6a 100644 #ifdef CONFIG_DEV_COREDUMP struct { struct mt7915_crash_data *crash_data[__MT76_RAM_TYPE_MAX]; -@@ -569,6 +577,7 @@ int mt7915_txbf_init(struct mt7915_dev *dev); +@@ -583,6 +591,7 @@ int mt7915_txbf_init(struct mt7915_dev *dev); void mt7915_init_txpower(struct mt7915_phy *phy); int mt7915_init_vif(struct mt7915_phy *phy, struct ieee80211_vif *vif, bool bf_en); void mt7915_reset(struct mt7915_dev *dev); diff --git a/feeds/mediatek-sdk/mt76/patches/1032-wifi-mt76-mt7915-remove-BW160-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1029-wifi-mt76-mt7915-remove-BW160-support.patch similarity index 88% rename from feeds/mediatek-sdk/mt76/patches/1032-wifi-mt76-mt7915-remove-BW160-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1029-wifi-mt76-mt7915-remove-BW160-support.patch index ad704e89d..12435fbb5 100644 --- a/feeds/mediatek-sdk/mt76/patches/1032-wifi-mt76-mt7915-remove-BW160-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1029-wifi-mt76-mt7915-remove-BW160-support.patch @@ -1,7 +1,7 @@ -From d7e885e617734df7699e53ce07a8e639b946584d Mon Sep 17 00:00:00 2001 +From 42cbeac3362b0d1ca2c513b4bcb850a73afafb94 Mon Sep 17 00:00:00 2001 From: MeiChia Chiu Date: Wed, 24 May 2023 22:35:54 +0800 -Subject: [PATCH 1032/1049] wifi: mt76: mt7915: remove BW160 support +Subject: [PATCH 1029/1053] wifi: mt76: mt7915: remove BW160 support Remove BW160 capability in mt7915. --- @@ -9,7 +9,7 @@ Remove BW160 capability in mt7915. 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/mt7915/init.c b/mt7915/init.c -index 11598983..d6902b06 100644 +index b32e213..decccc0 100644 --- a/mt7915/init.c +++ b/mt7915/init.c @@ -439,11 +439,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy) @@ -41,7 +41,7 @@ index 11598983..d6902b06 100644 #ifdef CONFIG_MAC80211_MESH if (vif == NL80211_IFTYPE_MESH_POINT) -@@ -985,15 +976,10 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, +@@ -989,15 +980,10 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask); u16 mcs_map = 0; u16 mcs_map_160 = 0; diff --git a/feeds/mediatek-sdk/mt76/patches/1033-wifi-mt76-mt7915-add-txpower-info-dump-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1030-wifi-mt76-mt7915-add-txpower-info-dump-support.patch similarity index 91% rename from feeds/mediatek-sdk/mt76/patches/1033-wifi-mt76-mt7915-add-txpower-info-dump-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1030-wifi-mt76-mt7915-add-txpower-info-dump-support.patch index 0b9fa6fac..20c8bd33f 100644 --- a/feeds/mediatek-sdk/mt76/patches/1033-wifi-mt76-mt7915-add-txpower-info-dump-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1030-wifi-mt76-mt7915-add-txpower-info-dump-support.patch @@ -1,7 +1,7 @@ -From 70bec5f54af56ee2806f09ec14d035e4391dc7d7 Mon Sep 17 00:00:00 2001 +From cc213fc945f430c8767ee6984741c3cf9a030d9c Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Tue, 11 Jul 2023 17:06:04 +0800 -Subject: [PATCH 1033/1049] wifi: mt76: mt7915: add txpower info dump support +Subject: [PATCH 1030/1053] wifi: mt76: mt7915: add txpower info dump support Signed-off-by: StanleyYP Wang --- @@ -11,10 +11,10 @@ Signed-off-by: StanleyYP Wang 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c -index 4c48b197..86cbef33 100644 +index 3044557..24e88f7 100644 --- a/mt7915/debugfs.c +++ b/mt7915/debugfs.c -@@ -1258,6 +1258,91 @@ mt7915_txpower_path_show(struct seq_file *file, void *data) +@@ -1259,6 +1259,91 @@ mt7915_txpower_path_show(struct seq_file *file, void *data) DEFINE_SHOW_ATTRIBUTE(mt7915_txpower_path); @@ -106,7 +106,7 @@ index 4c48b197..86cbef33 100644 static int mt7915_twt_stats(struct seq_file *s, void *data) { -@@ -1387,6 +1472,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) +@@ -1388,6 +1473,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) &mt7915_txpower_fops); debugfs_create_file("txpower_path", 0400, dir, phy, &mt7915_txpower_path_fops); @@ -116,10 +116,10 @@ index 4c48b197..86cbef33 100644 mt7915_twt_stats); debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 04016375..609eb5b3 100644 +index 45b0907..b9beb4f 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -3607,6 +3607,8 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len, +@@ -3624,6 +3624,8 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len, txpower[i] = res[i][req.band_idx]; } else if (category == TX_POWER_INFO_PATH) { memcpy(txpower, skb->data + 4, len); @@ -129,7 +129,7 @@ index 04016375..609eb5b3 100644 dev_kfree_skb(skb); diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 035ad97d..3089fb64 100644 +index 035ad97..3089fb6 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -525,7 +525,8 @@ enum { diff --git a/feeds/mediatek-sdk/mt76/patches/1034-wifi-mt76-mt7915-report-tx-and-rx-byte-to-tpt_led-wh.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1031-wifi-mt76-mt7915-report-tx-and-rx-byte-to-tpt_led-wh.patch similarity index 92% rename from feeds/mediatek-sdk/mt76/patches/1034-wifi-mt76-mt7915-report-tx-and-rx-byte-to-tpt_led-wh.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1031-wifi-mt76-mt7915-report-tx-and-rx-byte-to-tpt_led-wh.patch index 3c7a76131..4c42bbdb8 100644 --- a/feeds/mediatek-sdk/mt76/patches/1034-wifi-mt76-mt7915-report-tx-and-rx-byte-to-tpt_led-wh.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1031-wifi-mt76-mt7915-report-tx-and-rx-byte-to-tpt_led-wh.patch @@ -1,7 +1,7 @@ -From 0b7455686081e8e744e4d5a0b9c556958a7571a0 Mon Sep 17 00:00:00 2001 +From 539de29220ad63d73fdb1ff86d63014b4e246e3a Mon Sep 17 00:00:00 2001 From: Yi-Chia Hsieh Date: Fri, 23 Jun 2023 06:06:21 +0800 -Subject: [PATCH 1034/1049] wifi: mt76: mt7915: report tx and rx byte to +Subject: [PATCH 1031/1053] wifi: mt76: mt7915: report tx and rx byte to tpt_led when wed is enabled Signed-off-by: Yi-Chia Hsieh @@ -11,7 +11,7 @@ Signed-off-by: Yi-Chia Hsieh 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c -index 630c6402..949df63f 100644 +index 630c640..949df63 100644 --- a/mt76_connac_mac.c +++ b/mt76_connac_mac.c @@ -597,9 +597,15 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, @@ -42,7 +42,7 @@ index 630c6402..949df63f 100644 sband = &mphy->sband_5g.sband; else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) diff --git a/mt7915/mmio.c b/mt7915/mmio.c -index ddf1b72a..437a9b0e 100644 +index ddf1b72..437a9b0 100644 --- a/mt7915/mmio.c +++ b/mt7915/mmio.c @@ -588,6 +588,7 @@ static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed, diff --git a/feeds/mediatek-sdk/mt76/patches/1035-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1032-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch similarity index 77% rename from feeds/mediatek-sdk/mt76/patches/1035-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1032-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch index 7a6326964..3e8500fa8 100644 --- a/feeds/mediatek-sdk/mt76/patches/1035-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1032-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch @@ -1,14 +1,14 @@ -From 4b81c1fac62fc68ae2698b3ae4151ee22202fabf Mon Sep 17 00:00:00 2001 +From d588c607b158e13343964b451d1de5b98bba7feb Mon Sep 17 00:00:00 2001 From: MeiChia Chiu Date: Tue, 8 Aug 2023 11:20:58 +0800 -Subject: [PATCH 1035/1049] wifi: mt76: mt7915: Establish BA in VO queue +Subject: [PATCH 1032/1053] wifi: mt76: mt7915: Establish BA in VO queue --- mt76_connac_mac.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c -index 949df63f..d036047a 100644 +index 949df63..d036047 100644 --- a/mt76_connac_mac.c +++ b/mt76_connac_mac.c @@ -1115,8 +1115,6 @@ void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) diff --git a/feeds/mediatek-sdk/mt76/patches/1036-wifi-mt76-mt7915-Disable-RegDB-when-enable-single-sk.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1033-wifi-mt76-mt7915-Disable-RegDB-when-enable-single-sk.patch similarity index 89% rename from feeds/mediatek-sdk/mt76/patches/1036-wifi-mt76-mt7915-Disable-RegDB-when-enable-single-sk.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1033-wifi-mt76-mt7915-Disable-RegDB-when-enable-single-sk.patch index 43c8e6f0d..09fda9134 100644 --- a/feeds/mediatek-sdk/mt76/patches/1036-wifi-mt76-mt7915-Disable-RegDB-when-enable-single-sk.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1033-wifi-mt76-mt7915-Disable-RegDB-when-enable-single-sk.patch @@ -1,7 +1,7 @@ -From 66900882a026f06c914625760e3a8d3f95081a9a Mon Sep 17 00:00:00 2001 +From ee3f33638400dfe0306ed5d12f1e2c1840632cea Mon Sep 17 00:00:00 2001 From: "Allen.Ye" Date: Fri, 11 Aug 2023 16:46:53 +0800 -Subject: [PATCH 1036/1049] wifi: mt76: mt7915: Disable RegDB when enable +Subject: [PATCH 1033/1053] wifi: mt76: mt7915: Disable RegDB when enable single sku --- @@ -11,10 +11,10 @@ Subject: [PATCH 1036/1049] wifi: mt76: mt7915: Disable RegDB when enable 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c -index 86cbef33..ead0f985 100644 +index 24e88f7..502b493 100644 --- a/mt7915/debugfs.c +++ b/mt7915/debugfs.c -@@ -1019,10 +1019,16 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, +@@ -1020,10 +1020,16 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, { struct mt7915_phy *phy = file->private_data; struct mt7915_dev *dev = phy->dev; @@ -32,7 +32,7 @@ index 86cbef33..ead0f985 100644 ssize_t ret; char *buf; u32 reg; -@@ -1081,11 +1087,38 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, +@@ -1082,11 +1088,38 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf, len += scnprintf(buf + len, sz - len, "BW160/"); mt7915_txpower_puts(HE_RU2x996, 17); @@ -75,7 +75,7 @@ index 86cbef33..ead0f985 100644 ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); -@@ -1262,6 +1295,8 @@ static int +@@ -1263,6 +1296,8 @@ static int mt7915_txpower_info_show(struct seq_file *file, void *data) { struct mt7915_phy *phy = file->private; @@ -84,7 +84,7 @@ index 86cbef33..ead0f985 100644 struct { u8 category; u8 rsv1; -@@ -1303,6 +1338,7 @@ mt7915_txpower_info_show(struct seq_file *file, void *data) +@@ -1304,6 +1339,7 @@ mt7915_txpower_info_show(struct seq_file *file, void *data) s8 mu_tx_power_manual; u8 rsv3; } __packed basic_info = {}; @@ -92,7 +92,7 @@ index 86cbef33..ead0f985 100644 int ret; ret = mt7915_mcu_get_txpower_sku(phy, (s8 *)&basic_info, sizeof(basic_info), -@@ -1337,6 +1373,9 @@ mt7915_txpower_info_show(struct seq_file *file, void *data) +@@ -1338,6 +1374,9 @@ mt7915_txpower_info_show(struct seq_file *file, void *data) seq_printf(file, " Theraml Compensation Value: %d\n", basic_info.thermal_compensate_value); @@ -103,7 +103,7 @@ index 86cbef33..ead0f985 100644 return ret; } diff --git a/mt7915/init.c b/mt7915/init.c -index d6902b06..84f2986a 100644 +index decccc0..a5b38c8 100644 --- a/mt7915/init.c +++ b/mt7915/init.c @@ -283,9 +283,11 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy, @@ -135,10 +135,10 @@ index d6902b06..84f2986a 100644 } } diff --git a/mt7915/regs.h b/mt7915/regs.h -index 1f1f8b9c..3c2fd2d6 100644 +index 4d05e39..ca355d1 100644 --- a/mt7915/regs.h +++ b/mt7915/regs.h -@@ -1213,6 +1213,10 @@ enum offs_rev { +@@ -1215,6 +1215,10 @@ enum offs_rev { #define MT_WF_IRPI_NSS(phy, nss) MT_WF_IRPI(0x6000 + ((phy) << 20) + ((nss) << 16)) #define MT_WF_IRPI_NSS_MT7916(phy, nss) MT_WF_IRPI(0x1000 + ((phy) << 20) + ((nss) << 16)) @@ -149,7 +149,7 @@ index 1f1f8b9c..3c2fd2d6 100644 #define MT_WF_IPI_RESET 0x831a3008 /* PHY */ -@@ -1229,10 +1233,6 @@ enum offs_rev { +@@ -1231,10 +1235,6 @@ enum offs_rev { #define MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY BIT(18) #define MT_WF_PHY_RXTD12_IRPI_SW_CLR BIT(29) diff --git a/feeds/mediatek-sdk/mt76/patches/1037-wifi-mt76-mt7915-enable-the-mac80211-hw-bmc-ps-buffe.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1034-wifi-mt76-mt7915-enable-the-mac80211-hw-bmc-ps-buffe.patch similarity index 70% rename from feeds/mediatek-sdk/mt76/patches/1037-wifi-mt76-mt7915-enable-the-mac80211-hw-bmc-ps-buffe.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1034-wifi-mt76-mt7915-enable-the-mac80211-hw-bmc-ps-buffe.patch index 8a649d21c..8467fb709 100644 --- a/feeds/mediatek-sdk/mt76/patches/1037-wifi-mt76-mt7915-enable-the-mac80211-hw-bmc-ps-buffe.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1034-wifi-mt76-mt7915-enable-the-mac80211-hw-bmc-ps-buffe.patch @@ -1,15 +1,15 @@ -From c9a03e54936df5c888a2312e3b4ff15d89eccea7 Mon Sep 17 00:00:00 2001 +From 20c497b434dc4555210ea64cde38dd86817d8891 Mon Sep 17 00:00:00 2001 From: Evelyn Tsai Date: Thu, 24 Aug 2023 03:01:27 +0800 -Subject: [PATCH 1037/1049] wifi: mt76: mt7915: enable the mac80211 hw bmc ps - buffer function. +Subject: [PATCH] wifi: mt76: mt7915: enable the mac80211 hw bmc ps buffer + function. --- mt7915/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mt7915/init.c b/mt7915/init.c -index 84f2986a..df83ca3c 100644 +index 35aefca..545afe7 100644 --- a/mt7915/init.c +++ b/mt7915/init.c @@ -413,6 +413,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy) @@ -17,9 +17,9 @@ index 84f2986a..df83ca3c 100644 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, SUPPORTS_TX_FRAG); hw->max_tx_fragments = 4; - -- 2.18.0 diff --git a/feeds/mediatek-sdk/mt76/patches/1038-wifi-mt76-update-debugfs-knob-for-tx-tokens.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1035-wifi-mt76-update-debugfs-knob-for-tx-tokens.patch similarity index 90% rename from feeds/mediatek-sdk/mt76/patches/1038-wifi-mt76-update-debugfs-knob-for-tx-tokens.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1035-wifi-mt76-update-debugfs-knob-for-tx-tokens.patch index 1bff9a759..5c46d2929 100644 --- a/feeds/mediatek-sdk/mt76/patches/1038-wifi-mt76-update-debugfs-knob-for-tx-tokens.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1035-wifi-mt76-update-debugfs-knob-for-tx-tokens.patch @@ -1,7 +1,7 @@ -From ea03566cfd54a952576c0f21e157854803e04963 Mon Sep 17 00:00:00 2001 +From e9cf08519595e2d8c5c227486948d8cb00db626a Mon Sep 17 00:00:00 2001 From: Evelyn Tsai Date: Thu, 24 Aug 2023 03:01:27 +0800 -Subject: [PATCH 1038/1049] wifi: mt76: update debugfs knob for tx tokens +Subject: [PATCH 1035/1053] wifi: mt76: update debugfs knob for tx tokens 1. dump token pending time 2. dump per-band token counts @@ -14,7 +14,7 @@ Signed-off-by: Peter Chiu 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/mt76.h b/mt76.h -index 051afa76..d7eb6c8f 100644 +index 5c26715..6f78c07 100644 --- a/mt76.h +++ b/mt76.h @@ -403,6 +403,7 @@ struct mt76_txwi_cache { @@ -26,7 +26,7 @@ index 051afa76..d7eb6c8f 100644 union { struct sk_buff *skb; diff --git a/mt7915/mac.c b/mt7915/mac.c -index 7f4778f0..763e1fb3 100644 +index 14367fd..71b4e2d 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c @@ -811,6 +811,8 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -39,7 +39,7 @@ index 7f4778f0..763e1fb3 100644 mt7915_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, pid, key, qid, 0); diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 56b9e85e..6db22704 100644 +index f00ac10..3c248ee 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c @@ -2203,17 +2203,31 @@ static int mt7915_mibinfo_band1(struct seq_file *s, void *data) diff --git a/feeds/mediatek-sdk/mt76/patches/1039-wifi-mt76-mt7915-support-enable-disable-spatial-reus.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1036-wifi-mt76-mt7915-support-enable-disable-spatial-reus.patch similarity index 80% rename from feeds/mediatek-sdk/mt76/patches/1039-wifi-mt76-mt7915-support-enable-disable-spatial-reus.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1036-wifi-mt76-mt7915-support-enable-disable-spatial-reus.patch index 920ad4b11..4306c68de 100644 --- a/feeds/mediatek-sdk/mt76/patches/1039-wifi-mt76-mt7915-support-enable-disable-spatial-reus.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1036-wifi-mt76-mt7915-support-enable-disable-spatial-reus.patch @@ -1,7 +1,7 @@ -From dc09a9d745be397176d150c51d918c8dfcfc2114 Mon Sep 17 00:00:00 2001 +From e81df1a68b96bc91891c9c097db376a1890450ae Mon Sep 17 00:00:00 2001 From: Howard Hsu Date: Tue, 5 Sep 2023 20:17:19 +0800 -Subject: [PATCH 1039/1049] wifi: mt76: mt7915: support enable/disable spatial +Subject: [PATCH 1036/1053] wifi: mt76: mt7915: support enable/disable spatial reuse through debugfs Signed-off-by: Howard Hsu @@ -12,10 +12,10 @@ Signed-off-by: Howard Hsu 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 609eb5b3..1eb19bad 100644 +index b9beb4f..4b5fb53 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -3739,8 +3739,7 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action) +@@ -3756,8 +3756,7 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action) sizeof(req), true); } @@ -26,10 +26,10 @@ index 609eb5b3..1eb19bad 100644 struct mt7915_dev *dev = phy->dev; struct mt7915_mcu_sr_ctrl req = { diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index e21a7a6a..ffc2e0bc 100644 +index ea91611..bfd87bc 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -781,6 +781,7 @@ int mt7915_mcu_get_edcca(struct mt7915_phy *phy, u8 mode, s8 *value); +@@ -795,6 +795,7 @@ int mt7915_mcu_get_edcca(struct mt7915_phy *phy, u8 mode, s8 *value); int mt7915_mcu_sw_aci_set(struct mt7915_dev *dev, bool val); int mt7915_mcu_ipi_hist_ctrl(struct mt7915_phy *phy, void *data, u8 cmd, bool wait_resp); int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool wait_resp); @@ -38,10 +38,10 @@ index e21a7a6a..ffc2e0bc 100644 #ifdef MTK_DEBUG int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir); diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 6db22704..926316d3 100644 +index 3c248ee..9bbe50d 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c -@@ -3792,6 +3792,17 @@ mt7915_sw_aci_set(void *data, u64 val) +@@ -3799,6 +3799,17 @@ mt7915_sw_aci_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(fops_sw_aci, NULL, mt7915_sw_aci_set, "%llx\n"); @@ -59,7 +59,7 @@ index 6db22704..926316d3 100644 int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) { struct mt7915_dev *dev = phy->dev; -@@ -3882,6 +3893,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3889,6 +3900,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) mt7915_show_eeprom_mode); debugfs_create_file("sw_aci", 0600, dir, dev, &fops_sw_aci); diff --git a/feeds/mediatek-sdk/mt76/patches/1040-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1037-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch similarity index 75% rename from feeds/mediatek-sdk/mt76/patches/1040-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1037-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch index 3ab2d9165..d61c1fba0 100644 --- a/feeds/mediatek-sdk/mt76/patches/1040-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1037-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch @@ -1,7 +1,7 @@ -From 88d02cd37e4f01d540cb971c16f027829900b1e9 Mon Sep 17 00:00:00 2001 +From b8b4b5abf0dce8bedfca44e1a7871c119f2b92e6 Mon Sep 17 00:00:00 2001 From: Bo Jiao Date: Mon, 11 Sep 2023 17:11:24 +0800 -Subject: [PATCH 1040/1049] wifi: mt76: mt7915: add debug log for SER flow. +Subject: [PATCH 1037/1053] wifi: mt76: mt7915: add debug log for SER flow. Signed-off-by: Bo Jiao --- @@ -9,10 +9,10 @@ Signed-off-by: Bo Jiao 1 file changed, 9 insertions(+) diff --git a/mt7915/mac.c b/mt7915/mac.c -index 763e1fb3..1d83fbd0 100644 +index 71b4e2d..b0ddb10 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c -@@ -1574,6 +1574,9 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1572,6 +1572,9 @@ void mt7915_mac_reset_work(struct work_struct *work) if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) return; @@ -22,7 +22,7 @@ index 763e1fb3..1d83fbd0 100644 ieee80211_stop_queues(mt76_hw(dev)); if (ext_phy) ieee80211_stop_queues(ext_phy->hw); -@@ -1649,6 +1652,9 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1647,6 +1650,9 @@ void mt7915_mac_reset_work(struct work_struct *work) ieee80211_queue_delayed_work(ext_phy->hw, &phy2->mt76->mac_work, MT7915_WATCHDOG_TIME); @@ -32,7 +32,7 @@ index 763e1fb3..1d83fbd0 100644 } /* firmware coredump */ -@@ -1764,6 +1770,9 @@ void mt7915_coredump(struct mt7915_dev *dev, u8 state) +@@ -1762,6 +1768,9 @@ void mt7915_coredump(struct mt7915_dev *dev, u8 state) void mt7915_reset(struct mt7915_dev *dev) { diff --git a/feeds/mediatek-sdk/mt76/patches/1041-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1038-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch similarity index 83% rename from feeds/mediatek-sdk/mt76/patches/1041-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1038-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch index e4f63279b..0113d3711 100644 --- a/feeds/mediatek-sdk/mt76/patches/1041-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1038-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch @@ -1,7 +1,7 @@ -From 148c6a19f9b5ee7667606c779028192e80ac3c3c Mon Sep 17 00:00:00 2001 +From eaa1c8b40685b56c6298c85cb0a44c7b97c62e8c Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Wed, 20 Sep 2023 11:10:57 +0800 -Subject: [PATCH 1041/1049] wifi: mt76: mt7915: add additional chain signal +Subject: [PATCH 1038/1053] wifi: mt76: mt7915: add additional chain signal info to station dump Signed-off-by: StanleyYP Wang @@ -10,7 +10,7 @@ Signed-off-by: StanleyYP Wang 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mt7915/mac.c b/mt7915/mac.c -index 1d83fbd0..53f4c764 100644 +index b0ddb10..9a49375 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c @@ -442,7 +442,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, diff --git a/feeds/mediatek-sdk/mt76/patches/1042-wifi-mt76-mt7915-add-debuffs-knob-for-protect-thresh.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1039-wifi-mt76-mt7915-add-debuffs-knob-for-protect-thresh.patch similarity index 85% rename from feeds/mediatek-sdk/mt76/patches/1042-wifi-mt76-mt7915-add-debuffs-knob-for-protect-thresh.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1039-wifi-mt76-mt7915-add-debuffs-knob-for-protect-thresh.patch index f2d72ac19..422582573 100644 --- a/feeds/mediatek-sdk/mt76/patches/1042-wifi-mt76-mt7915-add-debuffs-knob-for-protect-thresh.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1039-wifi-mt76-mt7915-add-debuffs-knob-for-protect-thresh.patch @@ -1,7 +1,7 @@ -From 80ee94c36a64c80874efece56fd4623d7b55ce32 Mon Sep 17 00:00:00 2001 +From 2674288ca511860d73b068f73c14d864de13653f Mon Sep 17 00:00:00 2001 From: Peter Chiu Date: Mon, 2 Oct 2023 14:00:13 +0800 -Subject: [PATCH 1042/1049] wifi: mt76: mt7915: add debuffs knob for protect +Subject: [PATCH 1039/1053] wifi: mt76: mt7915: add debuffs knob for protect threshold --- @@ -10,10 +10,10 @@ Subject: [PATCH 1042/1049] wifi: mt76: mt7915: add debuffs knob for protect 2 files changed, 12 insertions(+) diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index ffc2e0bc..f3d9ee57 100644 +index bfd87bc..1b43c54 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -761,6 +761,7 @@ void mt7915_mcu_set_rfeature_starec(void *data, struct mt7915_dev *dev, +@@ -775,6 +775,7 @@ void mt7915_mcu_set_rfeature_starec(void *data, struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int mt7915_mcu_set_rfeature_trig_type(struct mt7915_phy *phy, u8 enable, u8 trig_type); int mt7915_mcu_set_mu_dl_ack_policy(struct mt7915_phy *phy, u8 policy_num); @@ -22,7 +22,7 @@ index ffc2e0bc..f3d9ee57 100644 void mt7915_mcu_set_nusers_ofdma(struct mt7915_phy *phy, u8 type, u8 ofdma_user_cnt); void mt7915_mcu_set_mimo(struct mt7915_phy *phy, u8 direction); diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 926316d3..69fdb93f 100644 +index 9bbe50d..2b59e35 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c @@ -2852,6 +2852,16 @@ static int mt7915_sta_tx_amsdu_set(void *data, u64 tx_amsdu) @@ -42,7 +42,7 @@ index 926316d3..69fdb93f 100644 static int mt7915_red_enable_set(void *data, u64 en) { struct mt7915_dev *dev = data; -@@ -3872,6 +3882,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3879,6 +3889,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) debugfs_create_devm_seqfile(dev->mt76.dev, "fw_wm_info", dir, mt7915_fw_wm_info_read); diff --git a/feeds/mediatek-sdk/mt76/patches/1044-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1040-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch similarity index 80% rename from feeds/mediatek-sdk/mt76/patches/1044-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1040-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch index 178f4dfb3..b1594a10d 100644 --- a/feeds/mediatek-sdk/mt76/patches/1044-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1040-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch @@ -1,7 +1,7 @@ -From 98e4056558cace50ec05c4077326275b12d3bb20 Mon Sep 17 00:00:00 2001 +From 45752d6719ee863fe80d2821f9ff6176e6a2497d Mon Sep 17 00:00:00 2001 From: "Henry.Yen" Date: Mon, 11 Dec 2023 16:01:55 +0800 -Subject: [PATCH 1044/1049] wifi: mt76: mt7915 add mt7981 efuse variants +Subject: [PATCH 1040/1053] wifi: mt76: mt7915 add mt7981 efuse variants support --- @@ -10,10 +10,10 @@ Subject: [PATCH 1044/1049] wifi: mt76: mt7915 add mt7981 efuse variants 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mt7915/eeprom.c b/mt7915/eeprom.c -index 96b1ea3d..79d6fe90 100644 +index 6133c20..df5e396 100644 --- a/mt7915/eeprom.c +++ b/mt7915/eeprom.c -@@ -179,6 +179,21 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) +@@ -193,6 +193,21 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev) return mt7915_check_eeprom(dev); } @@ -35,7 +35,7 @@ index 96b1ea3d..79d6fe90 100644 static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; -@@ -229,6 +244,13 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, +@@ -243,6 +258,13 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, u8 path, nss, nss_max = 4, *eeprom = dev->mt76.eeprom.data; struct mt76_phy *mphy = phy->mt76; u8 band = phy->mt76->band_idx; @@ -50,10 +50,10 @@ index 96b1ea3d..79d6fe90 100644 mt7915_eeprom_parse_band_config(phy); diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index f3d9ee57..45e04afb 100644 +index 1b43c54..c6150c8 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -399,6 +399,7 @@ struct mt7915_dev { +@@ -407,6 +407,7 @@ struct mt7915_dev { u32 hw_pattern; @@ -61,7 +61,7 @@ index f3d9ee57..45e04afb 100644 bool dbdc_support; bool flash_mode; bool bin_file_mode; -@@ -667,7 +668,11 @@ void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb); +@@ -681,7 +682,11 @@ void mt7915_tm_rf_test_event(struct mt7915_dev *dev, struct sk_buff *skb); static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev) { diff --git a/feeds/mediatek-sdk/mt76/patches/1045-wifi-mt76-mt7915-support-scs-feature.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1041-wifi-mt76-mt7915-support-scs-feature.patch similarity index 89% rename from feeds/mediatek-sdk/mt76/patches/1045-wifi-mt76-mt7915-support-scs-feature.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1041-wifi-mt76-mt7915-support-scs-feature.patch index fd77e4231..aa6ba21f1 100644 --- a/feeds/mediatek-sdk/mt76/patches/1045-wifi-mt76-mt7915-support-scs-feature.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1041-wifi-mt76-mt7915-support-scs-feature.patch @@ -1,7 +1,7 @@ -From 1ed6238a487b565e854c417df4c45a17f6df1bd8 Mon Sep 17 00:00:00 2001 +From 9c8dcebc80801b77b23b0a2af28a3d51662c164f Mon Sep 17 00:00:00 2001 From: Howard Hsu Date: Wed, 6 Dec 2023 08:53:03 +0800 -Subject: [PATCH 1045/1049] wifi: mt76: mt7915: support scs feature +Subject: [PATCH] wifi: mt76: mt7915: support scs feature Add support scs feature for connac2 codebase. This commit includes three parts. @@ -29,7 +29,7 @@ Signed-off-by: Howard Hsu 9 files changed, 188 insertions(+) diff --git a/mt76.h b/mt76.h -index d7eb6c8f..16c6a31a 100644 +index cff22f5..7ffba7d 100644 --- a/mt76.h +++ b/mt76.h @@ -311,6 +311,7 @@ struct mt76_sta_stats { @@ -49,10 +49,10 @@ index d7eb6c8f..16c6a31a 100644 enum mt76_wcid_flags { diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 12654017..5be93f6a 100644 +index 94fcf32..247b520 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1228,6 +1228,7 @@ enum { +@@ -1236,6 +1236,7 @@ enum { MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, MCU_EXT_CMD_MWDS_SUPPORT = 0x80, MCU_EXT_CMD_SET_SER_TRIGGER = 0x81, @@ -61,10 +61,10 @@ index 12654017..5be93f6a 100644 MCU_EXT_CMD_FW_DBG_CTRL = 0x95, MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a, diff --git a/mt7915/init.c b/mt7915/init.c -index df83ca3c..6eaf7b7a 100644 +index 545afe7..074f247 100644 --- a/mt7915/init.c +++ b/mt7915/init.c -@@ -1243,6 +1243,7 @@ int mt7915_register_device(struct mt7915_dev *dev) +@@ -1248,6 +1248,7 @@ int mt7915_register_device(struct mt7915_dev *dev) spin_lock_init(&dev->phy.stats_lock); INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work); INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work); @@ -73,10 +73,10 @@ index df83ca3c..6eaf7b7a 100644 INIT_LIST_HEAD(&dev->twt_list); diff --git a/mt7915/mac.c b/mt7915/mac.c -index 53f4c764..1e37ff48 100644 +index 9a49375..2e4a8f8 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c -@@ -1506,6 +1506,8 @@ mt7915_mac_full_reset(struct mt7915_dev *dev) +@@ -1504,6 +1504,8 @@ mt7915_mac_full_reset(struct mt7915_dev *dev) if (ext_phy) cancel_delayed_work_sync(&ext_phy->mac_work); @@ -85,7 +85,7 @@ index 53f4c764..1e37ff48 100644 mutex_lock(&dev->mt76.mutex); for (i = 0; i < 10; i++) { if (!mt7915_mac_restart(dev)) -@@ -1531,6 +1533,10 @@ mt7915_mac_full_reset(struct mt7915_dev *dev) +@@ -1529,6 +1531,10 @@ mt7915_mac_full_reset(struct mt7915_dev *dev) ieee80211_queue_delayed_work(ext_phy->hw, &ext_phy->mac_work, MT7915_WATCHDOG_TIME); @@ -96,7 +96,7 @@ index 53f4c764..1e37ff48 100644 } /* system error recovery */ -@@ -1589,6 +1595,7 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1587,6 +1593,7 @@ void mt7915_mac_reset_work(struct work_struct *work) set_bit(MT76_RESET, &phy2->mt76->state); cancel_delayed_work_sync(&phy2->mt76->mac_work); } @@ -104,7 +104,7 @@ index 53f4c764..1e37ff48 100644 mt76_worker_disable(&dev->mt76.tx_worker); mt76_for_each_q_rx(&dev->mt76, i) napi_disable(&dev->mt76.napi[i]); -@@ -1653,6 +1660,10 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1651,6 +1658,10 @@ void mt7915_mac_reset_work(struct work_struct *work) &phy2->mt76->mac_work, MT7915_WATCHDOG_TIME); @@ -116,7 +116,7 @@ index 53f4c764..1e37ff48 100644 wiphy_name(dev->mt76.hw->wiphy)); } diff --git a/mt7915/main.c b/mt7915/main.c -index acb4f44c..5316225e 100644 +index 2ff7667..2750e60 100644 --- a/mt7915/main.c +++ b/mt7915/main.c @@ -89,12 +89,24 @@ int mt7915_run(struct ieee80211_hw *hw) @@ -153,14 +153,13 @@ index acb4f44c..5316225e 100644 mt7915_mcu_set_mac(dev, dev->phy.mt76->band_idx, false, false); } diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 6cee6b62..5672e449 100644 +index 1af6dac..aa3f9ad 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -5245,3 +5245,121 @@ int mt7915_mcu_sw_aci_set(struct mt7915_dev *dev, bool val) - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SWLNA_ACI_CTRL), &req, +@@ -5239,6 +5239,124 @@ int mt7915_mcu_sw_aci_set(struct mt7915_dev *dev, bool val) sizeof(req), NULL); } -+ + +int mt7915_mcu_set_scs_en(struct mt7915_phy *phy, u8 enable) +{ + struct mt7915_dev *dev = phy->dev; @@ -278,8 +277,12 @@ index 6cee6b62..5672e449 100644 + if (scs_enable_flag) + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); +} ++ + int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif) + { + #define IP_DSCP_NUM 64 diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 3089fb64..742a7855 100644 +index 3089fb6..742a785 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -1200,4 +1200,8 @@ struct mt7915_mcu_edcca_info { @@ -292,7 +295,7 @@ index 3089fb64..742a7855 100644 +}; #endif diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 45e04afb..05a3bd51 100644 +index 03ec7e2..3daec29 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h @@ -270,6 +270,15 @@ struct mt7915_air_monitor_ctrl { @@ -318,17 +321,17 @@ index 45e04afb..05a3bd51 100644 + struct mt7915_scs_ctrl scs_ctrl; }; - struct mt7915_dev { -@@ -463,6 +473,8 @@ struct mt7915_dev { - const struct mt7915_dbg_reg_desc *dbg_reg; + #ifdef MTK_DEBUG +@@ -476,6 +486,8 @@ struct mt7915_dev { + } adie[ADIE_MAX_CNT]; #endif + struct delayed_work scs_work; + bool wmm_pbc_enable; struct work_struct wmm_pbc_work; - }; -@@ -788,6 +800,8 @@ int mt7915_mcu_sw_aci_set(struct mt7915_dev *dev, bool val); + u32 adie_type; +@@ -803,6 +815,8 @@ int mt7915_mcu_sw_aci_set(struct mt7915_dev *dev, bool val); int mt7915_mcu_ipi_hist_ctrl(struct mt7915_phy *phy, void *data, u8 cmd, bool wait_resp); int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool wait_resp); int mt7915_mcu_enable_obss_spr(struct mt7915_phy *phy, u8 action, u8 val); @@ -338,10 +341,10 @@ index 45e04afb..05a3bd51 100644 #ifdef MTK_DEBUG int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir); diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 69fdb93f..2011fc98 100644 +index dad5ed7..0953223 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c -@@ -3813,6 +3813,29 @@ mt7915_sr_enable_set(void *data, u64 val) +@@ -3820,6 +3820,29 @@ mt7915_sr_enable_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(fops_sr_enable, NULL, mt7915_sr_enable_set, "%llx\n"); @@ -371,7 +374,7 @@ index 69fdb93f..2011fc98 100644 int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) { struct mt7915_dev *dev = phy->dev; -@@ -3905,6 +3928,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3912,6 +3935,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) debugfs_create_file("sw_aci", 0600, dir, dev, &fops_sw_aci); debugfs_create_file("sr_enable", 0200, dir, phy, &fops_sr_enable); diff --git a/feeds/mediatek-sdk/mt76/patches/1046-wifi-mt76-mt7915-support-thermal-recal-debug-commnad.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1042-wifi-mt76-mt7915-support-thermal-recal-debug-commnad.patch similarity index 80% rename from feeds/mediatek-sdk/mt76/patches/1046-wifi-mt76-mt7915-support-thermal-recal-debug-commnad.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1042-wifi-mt76-mt7915-support-thermal-recal-debug-commnad.patch index c307132ef..7358d2751 100644 --- a/feeds/mediatek-sdk/mt76/patches/1046-wifi-mt76-mt7915-support-thermal-recal-debug-commnad.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1042-wifi-mt76-mt7915-support-thermal-recal-debug-commnad.patch @@ -1,8 +1,7 @@ -From 8b6ebb1bfeb7b430a2ff32b5384173b18b46ad84 Mon Sep 17 00:00:00 2001 +From e9f5c9f345503c5653d1a5fd5bedd69cd1bc48f1 Mon Sep 17 00:00:00 2001 From: Howard Hsu Date: Thu, 21 Dec 2023 20:35:36 +0800 -Subject: [PATCH 1046/1049] wifi: mt76: mt7915: support thermal recal debug - commnad +Subject: [PATCH] wifi: mt76: mt7915: support thermal recal debug commnad Add thermal recal debug command: $ echo val > debugfs/thermal_recal @@ -21,26 +20,25 @@ Signed-off-by: Howard Hsu 4 files changed, 35 insertions(+) diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 5be93f6a..4e1006db 100644 +index 247b520..e445046 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1224,6 +1224,7 @@ enum { - MCU_EXT_CMD_CAL_CACHE = 0x67, +@@ -1232,6 +1232,7 @@ enum { MCU_EXT_CMD_RED_ENABLE = 0x68, MCU_EXT_CMD_PKT_BUDGET_CTRL = 0x6c, + MCU_EXT_CMD_CP_SUPPORT = 0x75, + MCU_EXT_CMD_THERMAL_DEBUG = 0x79, MCU_EXT_CMD_SET_RADAR_TH = 0x7c, MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, MCU_EXT_CMD_MWDS_SUPPORT = 0x80, diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 5672e449..7e0e2774 100644 +index aa3f9ad..2417251 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -5363,3 +5363,18 @@ void mt7915_mcu_scs_sta_poll(struct work_struct *work) - if (scs_enable_flag) +@@ -5357,6 +5357,21 @@ void mt7915_mcu_scs_sta_poll(struct work_struct *work) ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); } -+ + +int mt7915_mcu_thermal_debug(struct mt7915_dev *dev, u8 mode, u8 action) +{ + struct { @@ -55,11 +53,15 @@ index 5672e449..7e0e2774 100644 + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_DEBUG), &req, + sizeof(req), true); +} ++ + int mt7915_mcu_set_qos_map(struct mt7915_dev *dev, struct ieee80211_vif *vif) + { + #define IP_DSCP_NUM 64 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 05a3bd51..38a9db44 100644 +index 3daec29..9b52ec4 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -802,6 +802,7 @@ int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool w +@@ -817,6 +817,7 @@ int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool w int mt7915_mcu_enable_obss_spr(struct mt7915_phy *phy, u8 action, u8 val); int mt7915_mcu_set_scs_en(struct mt7915_phy *phy, u8 enable); void mt7915_mcu_scs_sta_poll(struct work_struct *work); @@ -68,10 +70,10 @@ index 05a3bd51..38a9db44 100644 #ifdef MTK_DEBUG int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir); diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 2011fc98..383ebdc9 100644 +index 0953223..53294c1 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c -@@ -3836,6 +3836,22 @@ mt7915_scs_enable_set(void *data, u64 val) +@@ -3843,6 +3843,22 @@ mt7915_scs_enable_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(fops_scs_enable, NULL, mt7915_scs_enable_set, "%lld\n"); @@ -94,7 +96,7 @@ index 2011fc98..383ebdc9 100644 int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) { struct mt7915_dev *dev = phy->dev; -@@ -3929,6 +3945,8 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3936,6 +3952,8 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) &fops_sw_aci); debugfs_create_file("sr_enable", 0200, dir, phy, &fops_sr_enable); debugfs_create_file("scs_enable", 0200, dir, phy, &fops_scs_enable); diff --git a/feeds/mediatek-sdk/mt76/patches/1047-wifi-mt76-mt7915-Add-support-for-lpi-and-duplicate-m.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1043-wifi-mt76-mt7915-Add-support-for-lpi-and-duplicate-m.patch similarity index 93% rename from feeds/mediatek-sdk/mt76/patches/1047-wifi-mt76-mt7915-Add-support-for-lpi-and-duplicate-m.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1043-wifi-mt76-mt7915-Add-support-for-lpi-and-duplicate-m.patch index 255270438..c91ad4457 100644 --- a/feeds/mediatek-sdk/mt76/patches/1047-wifi-mt76-mt7915-Add-support-for-lpi-and-duplicate-m.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1043-wifi-mt76-mt7915-Add-support-for-lpi-and-duplicate-m.patch @@ -1,8 +1,7 @@ -From cf3aa890a3ade3f8105e9d5e1ed8d449ce288024 Mon Sep 17 00:00:00 2001 +From 771d717a6bce6c6a7f7bb06599b42fa3994b560e Mon Sep 17 00:00:00 2001 From: Allen Ye Date: Fri, 15 Dec 2023 14:03:11 +0800 -Subject: [PATCH 1047/1049] wifi: mt76: mt7915: Add support for lpi and - duplicate mode +Subject: [PATCH] wifi: mt76: mt7915: Add support for lpi and duplicate mode Add support lpi and duplicate mode. 1. lpi_enable: lpi fw cmd and set psd flag to fw by the country setting. @@ -31,7 +30,7 @@ Signed-off-by: Allen Ye 12 files changed, 210 insertions(+), 17 deletions(-) diff --git a/eeprom.c b/eeprom.c -index 4213e444..2ee262a0 100644 +index 4213e44..2ee262a 100644 --- a/eeprom.c +++ b/eeprom.c @@ -224,8 +224,9 @@ static bool mt76_string_prop_find(struct property *prop, const char *str) @@ -95,7 +94,7 @@ index 4213e444..2ee262a0 100644 return target_power; diff --git a/mt76.h b/mt76.h -index 16c6a31a..65d36cd7 100644 +index c011812..b023f38 100644 --- a/mt76.h +++ b/mt76.h @@ -853,6 +853,9 @@ struct mt76_phy { @@ -118,10 +117,10 @@ index 16c6a31a..65d36cd7 100644 mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan); diff --git a/mt76_connac2_mac.h b/mt76_connac2_mac.h -index 5f132115..c49a3300 100644 +index eb47653..49ba39f 100644 --- a/mt76_connac2_mac.h +++ b/mt76_connac2_mac.h -@@ -355,4 +355,11 @@ enum tx_port_idx { +@@ -355,6 +355,13 @@ enum tx_port_idx { MT_TX_PORT_IDX_MCU }; @@ -132,12 +131,14 @@ index 5f132115..c49a3300 100644 + MT_TX_BW_IDX_160, +}; + - #endif /* __MT76_CONNAC2_MAC_H */ + enum tx_frag_idx { + MT_TX_FRAG_NONE, + MT_TX_FRAG_FIRST, diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c -index d036047a..d41f0040 100644 +index 5ba0255..5f705bb 100644 --- a/mt76_connac_mac.c +++ b/mt76_connac_mac.c -@@ -564,7 +564,8 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, +@@ -572,7 +572,8 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, multicast); u32 val = MT_TXD6_FIXED_BW; @@ -147,7 +148,7 @@ index d036047a..d41f0040 100644 /* hardware won't add HTC for mgmt/ctrl frame */ txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD); -@@ -577,7 +578,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, +@@ -585,7 +586,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, if (!spe_idx) spe_idx = 24 + phy_idx; @@ -159,10 +160,10 @@ index d036047a..d41f0040 100644 txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU); diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index 4e1006db..e581084e 100644 +index cbe8da5..c96621f 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1249,6 +1249,7 @@ enum { +@@ -1257,6 +1257,7 @@ enum { MCU_EXT_CMD_SWLNA_ACI_CTRL = 0xc0, MCU_EXT_CMD_CSI_CTRL = 0xc2, MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5, @@ -171,10 +172,10 @@ index 4e1006db..e581084e 100644 enum { diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c -index ead0f985..017d43d7 100644 +index 502b493..b2a4ff4 100644 --- a/mt7915/debugfs.c +++ b/mt7915/debugfs.c -@@ -1296,7 +1296,6 @@ mt7915_txpower_info_show(struct seq_file *file, void *data) +@@ -1297,7 +1297,6 @@ mt7915_txpower_info_show(struct seq_file *file, void *data) { struct mt7915_phy *phy = file->private; struct mt76_phy *mphy = phy->mt76; @@ -182,7 +183,7 @@ index ead0f985..017d43d7 100644 struct { u8 category; u8 rsv1; -@@ -1373,7 +1372,7 @@ mt7915_txpower_info_show(struct seq_file *file, void *data) +@@ -1374,7 +1373,7 @@ mt7915_txpower_info_show(struct seq_file *file, void *data) seq_printf(file, " Theraml Compensation Value: %d\n", basic_info.thermal_compensate_value); @@ -192,7 +193,7 @@ index ead0f985..017d43d7 100644 out: diff --git a/mt7915/init.c b/mt7915/init.c -index 6eaf7b7a..849ee450 100644 +index 373f4f5..b53075b 100644 --- a/mt7915/init.c +++ b/mt7915/init.c @@ -287,7 +287,7 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy, @@ -217,7 +218,7 @@ index 6eaf7b7a..849ee450 100644 static void diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 7e0e2774..ba47d0d0 100644 +index c5f60c0..e17c61d 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c @@ -1522,7 +1522,8 @@ mt7915_mcu_set_spe_idx(struct mt7915_dev *dev, struct ieee80211_vif *vif, @@ -353,10 +354,10 @@ index 7e0e2774..ba47d0d0 100644 u8 en) { diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 38a9db44..23ee118f 100644 +index 1b2f584..ff08d25 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -793,6 +793,7 @@ int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode, +@@ -807,6 +807,7 @@ int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode, void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb); int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, struct ieee80211_sta *sta); @@ -365,10 +366,10 @@ index 38a9db44..23ee118f 100644 int mt7915_mcu_set_edcca(struct mt7915_phy *phy, int mode, u8 *value, s8 compensation); int mt7915_mcu_get_edcca(struct mt7915_phy *phy, u8 mode, s8 *value); diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 383ebdc9..1ed7bb2c 100644 +index 53294c1..352b8e9 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c -@@ -3938,6 +3938,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3945,6 +3945,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) &fops_txbf_sta_rec); debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable); @@ -377,7 +378,7 @@ index 383ebdc9..1ed7bb2c 100644 debugfs_create_devm_seqfile(dev->mt76.dev, "eeprom_mode", dir, mt7915_show_eeprom_mode); diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index 432d7506..566fec01 100644 +index 432d750..566fec0 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -106,6 +106,13 @@ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL] = { @@ -477,7 +478,7 @@ index 432d7506..566fec01 100644 }; diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 03d1660c..5b8a1fb3 100644 +index 03d1660..5b8a1fb 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -16,6 +16,7 @@ enum mtk_nl80211_vendor_subcmds { diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1044-wifi-mt76-testmode-add-cheetah-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1044-wifi-mt76-testmode-add-cheetah-support.patch new file mode 100644 index 000000000..fa23d7d98 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1044-wifi-mt76-testmode-add-cheetah-support.patch @@ -0,0 +1,58 @@ +From e9b737f036595d84f680ff9ee15cfffe5cd08efc Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Tue, 31 Oct 2023 16:29:13 +0800 +Subject: [PATCH 1044/1053] wifi: mt76: testmode: add cheetah support + +Signed-off-by: StanleyYP Wang +--- + mt7915/testmode.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/mt7915/testmode.c b/mt7915/testmode.c +index faf6014..ecd6271 100644 +--- a/mt7915/testmode.c ++++ b/mt7915/testmode.c +@@ -2151,7 +2151,7 @@ mt7915_tm_group_prek(struct mt7915_phy *phy, enum mt76_testmode_state state) + eeprom = mdev->eeprom.data; + dev->cur_prek_offset = 0; + group_size = mt7915_get_cal_group_size(dev); +- dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2; ++ dpd_size = mt7915_get_cal_dpd_size(dev); + size = group_size + dpd_size; + offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2; + +@@ -2233,11 +2233,11 @@ mt7915_tm_dpd_prek(struct mt7915_phy *phy, enum mt76_testmode_state state) + eeprom = mdev->eeprom.data; + dev->cur_prek_offset = 0; + group_size = mt7915_get_cal_group_size(dev); ++ dpd_size = mt7915_get_cal_dpd_size(dev); + dev->dpd_chan_num_2g = hweight32(DPD_2G_CH_BW20_BITMAP_0); + if (is_mt7915(&dev->mt76)) { + dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_7915_0); + dev->dpd_chan_num_6g = 0; +- dpd_size = MT_EE_CAL_DPD_SIZE_V1; + offs = MT_EE_DO_PRE_CAL; + } else { + dev->dpd_chan_num_5g = hweight32(DPD_5G_CH_BW20_BITMAP_0) + +@@ -2246,7 +2246,8 @@ mt7915_tm_dpd_prek(struct mt7915_phy *phy, enum mt76_testmode_state state) + dev->dpd_chan_num_6g = hweight32(DPD_6G_CH_BW20_BITMAP_0) + + hweight32(DPD_6G_CH_BW20_BITMAP_1) + + ARRAY_SIZE(bw160_6g_freq); +- dpd_size = MT_EE_CAL_DPD_SIZE_V2; ++ if (is_mt7981(&dev->mt76)) ++ dev->dpd_chan_num_6g = 0; + offs = MT_EE_DO_PRE_CAL_V2; + } + size = group_size + dpd_size; +@@ -2711,7 +2712,7 @@ mt7915_tm_dump_precal(struct mt76_phy *mphy, struct sk_buff *msg, int flag, int + } + + group_size = mt7915_get_cal_group_size(dev); +- dpd_size = is_mt7915(&dev->mt76) ? MT_EE_CAL_DPD_SIZE_V1 : MT_EE_CAL_DPD_SIZE_V2; ++ dpd_size = mt7915_get_cal_dpd_size(dev); + dpd_per_chan_size = is_mt7915(&dev->mt76) ? 2 : 3; + total_size = group_size + dpd_size; + pre_cal = dev->cal; +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/patches/1048-wifi-mt76-mt7915-add-no_beacon-vendor-command-for-ce.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1045-wifi-mt76-mt7915-add-no_beacon-vendor-command-for-ce.patch similarity index 91% rename from feeds/mediatek-sdk/mt76/patches/1048-wifi-mt76-mt7915-add-no_beacon-vendor-command-for-ce.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1045-wifi-mt76-mt7915-add-no_beacon-vendor-command-for-ce.patch index 747ad3279..d0fd257aa 100644 --- a/feeds/mediatek-sdk/mt76/patches/1048-wifi-mt76-mt7915-add-no_beacon-vendor-command-for-ce.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1045-wifi-mt76-mt7915-add-no_beacon-vendor-command-for-ce.patch @@ -1,7 +1,7 @@ -From d9f388ece4275ee2ff5102825110dc9c7557b1a1 Mon Sep 17 00:00:00 2001 +From 966bba87073d983aa136f1f762d1b787a81ec767 Mon Sep 17 00:00:00 2001 From: MeiChia Chiu Date: Wed, 24 Jan 2024 14:39:14 +0800 -Subject: [PATCH 1048/1049] wifi: mt76: mt7915: add no_beacon vendor command +Subject: [PATCH 1045/1053] wifi: mt76: mt7915: add no_beacon vendor command for cert Add the vendor command to disable/enable beacon @@ -21,10 +21,10 @@ Signed-off-by: MeiChia Chiu 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index ba47d0d0..3b214a23 100644 +index e17c61d..ddb738c 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -5107,6 +5107,17 @@ int mt7915_mcu_set_rfeature_trig_type(struct mt7915_phy *phy, u8 enable, u8 trig +@@ -5101,6 +5101,17 @@ int mt7915_mcu_set_rfeature_trig_type(struct mt7915_phy *phy, u8 enable, u8 trig return 0; } } @@ -43,10 +43,10 @@ index ba47d0d0..3b214a23 100644 #ifdef MTK_DEBUG diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 23ee118f..3a596dad 100644 +index ff08d25..34f1a35 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h -@@ -794,6 +794,7 @@ void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb); +@@ -808,6 +808,7 @@ void mt7915_vendor_amnt_fill_rx(struct mt7915_phy *phy, struct sk_buff *skb); int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy, struct ieee80211_sta *sta); int mt7915_mcu_set_lpi(struct mt7915_phy *phy, bool en); @@ -55,7 +55,7 @@ index 23ee118f..3a596dad 100644 int mt7915_mcu_set_edcca(struct mt7915_phy *phy, int mode, u8 *value, s8 compensation); int mt7915_mcu_get_edcca(struct mt7915_phy *phy, u8 mode, s8 *value); diff --git a/mt7915/vendor.c b/mt7915/vendor.c -index 566fec01..6154d1a0 100644 +index 566fec0..6154d1a 100644 --- a/mt7915/vendor.c +++ b/mt7915/vendor.c @@ -113,6 +113,11 @@ txpower_ctrl_policy[NUM_MTK_VENDOR_ATTRS_TXPOWER_CTRL] = { @@ -122,7 +122,7 @@ index 566fec01..6154d1a0 100644 void mt7915_vendor_register(struct mt7915_phy *phy) diff --git a/mt7915/vendor.h b/mt7915/vendor.h -index 5b8a1fb3..661d636f 100644 +index 5b8a1fb..661d636 100644 --- a/mt7915/vendor.h +++ b/mt7915/vendor.h @@ -16,6 +16,7 @@ enum mtk_nl80211_vendor_subcmds { diff --git a/feeds/mediatek-sdk/mt76/patches/1049-wifi-mt76-mt7915-support-spatial-reuse-debug-command.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1046-wifi-mt76-mt7915-support-spatial-reuse-debug-command.patch similarity index 89% rename from feeds/mediatek-sdk/mt76/patches/1049-wifi-mt76-mt7915-support-spatial-reuse-debug-command.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1046-wifi-mt76-mt7915-support-spatial-reuse-debug-command.patch index 1a411ec4a..65882778c 100644 --- a/feeds/mediatek-sdk/mt76/patches/1049-wifi-mt76-mt7915-support-spatial-reuse-debug-command.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1046-wifi-mt76-mt7915-support-spatial-reuse-debug-command.patch @@ -1,7 +1,7 @@ -From d2e1eed3bc308df82e7866b40c54a7f42934ce66 Mon Sep 17 00:00:00 2001 +From 3a8ffe4b10bd9949dcd689406d5378a1b93c201d Mon Sep 17 00:00:00 2001 From: Howard Hsu Date: Thu, 15 Feb 2024 11:16:16 +0800 -Subject: [PATCH 1049/1049] wifi: mt76: mt7915: support spatial reuse debug +Subject: [PATCH 1046/1053] wifi: mt76: mt7915: support spatial reuse debug commands Support 3 spatial reuse debug commands: @@ -12,17 +12,17 @@ Support 3 spatial reuse debug commands: Signed-off-by: Howard Hsu --- mt76_connac_mcu.h | 1 + - mt7915/mcu.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ + mt7915/mcu.c | 95 ++++++++++++++++++++++++++++++++++++++++++++ mt7915/mcu.h | 48 ++++++++++++++++++++++ mt7915/mt7915.h | 3 ++ mt7915/mtk_debugfs.c | 48 ++++++++++++++++++++-- - 5 files changed, 190 insertions(+), 4 deletions(-) + 5 files changed, 191 insertions(+), 4 deletions(-) diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h -index e581084e..791dc1d4 100644 +index c96621f..dc60e35 100644 --- a/mt76_connac_mcu.h +++ b/mt76_connac_mcu.h -@@ -1024,6 +1024,7 @@ enum { +@@ -1031,6 +1031,7 @@ enum { MCU_EXT_EVENT_WA_TX_STAT = 0x74, MCU_EXT_EVENT_BCC_NOTIFY = 0x75, MCU_EXT_EVENT_MURU_CTRL = 0x9f, @@ -31,10 +31,10 @@ index e581084e..791dc1d4 100644 }; diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 3b214a23..4bd7a3bf 100644 +index ddb738c..b3faf77 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c -@@ -452,6 +452,90 @@ mt7915_mcu_rx_bss_acq_pkt_cnt(struct mt7915_dev *dev, struct sk_buff * skb) +@@ -452,6 +452,91 @@ mt7915_mcu_rx_bss_acq_pkt_cnt(struct mt7915_dev *dev, struct sk_buff * skb) } } @@ -44,7 +44,8 @@ index 3b214a23..4bd7a3bf 100644 +#define SR_SCENE_DETECTION_TIMER_PERIOD_MS 500 + struct mt7915_mcu_sr_swsd_event *event; + static const char * const rules[] = {"NO CONNECTED", "NO CONGESTION", -+ "NO INTERFERENCE", "SR ON"}; ++ "NO INTERFERENCE", "MESH ILLEGAL APCLI", ++ "SR ON"}; + u8 idx; + + event = (struct mt7915_mcu_sr_swsd_event *)skb->data; @@ -125,7 +126,7 @@ index 3b214a23..4bd7a3bf 100644 static void mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) { -@@ -479,6 +563,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) +@@ -479,6 +564,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) case MCU_EXT_EVENT_BCC_NOTIFY: mt7915_mcu_rx_bcc_notify(dev, skb); break; @@ -137,7 +138,7 @@ index 3b214a23..4bd7a3bf 100644 #if defined CONFIG_NL80211_TESTMODE || defined MTK_DEBUG case MCU_EXT_EVENT_BF_STATUS_READ: mt7915_mcu_txbf_status_read(dev, skb); -@@ -524,6 +613,7 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb) +@@ -524,6 +614,7 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb) rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC || rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY || rxd->ext_eid == MCU_EXT_EVENT_BF_STATUS_READ || @@ -145,7 +146,7 @@ index 3b214a23..4bd7a3bf 100644 !rxd->seq) && !(rxd->eid == MCU_CMD_EXT_CID && rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT)) -@@ -4002,6 +4092,10 @@ int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif, +@@ -4002,6 +4093,10 @@ int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif, if (ret) return ret; @@ -157,7 +158,7 @@ index 3b214a23..4bd7a3bf 100644 return 0; diff --git a/mt7915/mcu.h b/mt7915/mcu.h -index 742a7855..f4767671 100644 +index 742a785..f476767 100644 --- a/mt7915/mcu.h +++ b/mt7915/mcu.h @@ -42,6 +42,45 @@ struct mt7915_mcu_thermal_notify { @@ -232,7 +233,7 @@ index 742a7855..f4767671 100644 THERMAL_PROTECT_PARAMETER_CTRL, THERMAL_PROTECT_BASIC_INFO, diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h -index 3a596dad..2ec2c77f 100644 +index 34f1a35..47f7d16 100644 --- a/mt7915/mt7915.h +++ b/mt7915/mt7915.h @@ -354,6 +354,9 @@ struct mt7915_phy { @@ -244,12 +245,12 @@ index 3a596dad..2ec2c77f 100644 +#endif }; - struct mt7915_dev { + #ifdef MTK_DEBUG diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c -index 1ed7bb2c..e479157f 100644 +index d3d3b17..78ac4e5 100644 --- a/mt7915/mtk_debugfs.c +++ b/mt7915/mtk_debugfs.c -@@ -3802,16 +3802,34 @@ mt7915_sw_aci_set(void *data, u64 val) +@@ -3809,16 +3809,34 @@ mt7915_sw_aci_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(fops_sw_aci, NULL, mt7915_sw_aci_set, "%llx\n"); @@ -287,7 +288,7 @@ index 1ed7bb2c..e479157f 100644 static int mt7915_scs_enable_set(void *data, u64 val) -@@ -3852,6 +3870,26 @@ mt7915_thermal_recal_set(void *data, u64 val) +@@ -3859,6 +3877,26 @@ mt7915_thermal_recal_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(fops_thermal_recal, NULL, mt7915_thermal_recal_set, "%llu\n"); @@ -314,7 +315,7 @@ index 1ed7bb2c..e479157f 100644 int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) { struct mt7915_dev *dev = phy->dev; -@@ -3944,9 +3982,11 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) +@@ -3951,9 +3989,11 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir) mt7915_show_eeprom_mode); debugfs_create_file("sw_aci", 0600, dir, dev, &fops_sw_aci); diff --git a/feeds/mediatek-sdk/mt76/patches/1050-wifi-mt76-try-more-times-when-send-message-timeout.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1047-wifi-mt76-try-more-times-when-send-message-timeout.patch similarity index 88% rename from feeds/mediatek-sdk/mt76/patches/1050-wifi-mt76-try-more-times-when-send-message-timeout.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1047-wifi-mt76-try-more-times-when-send-message-timeout.patch index 9dd4eeeec..ed1ac982f 100644 --- a/feeds/mediatek-sdk/mt76/patches/1050-wifi-mt76-try-more-times-when-send-message-timeout.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1047-wifi-mt76-try-more-times-when-send-message-timeout.patch @@ -1,18 +1,19 @@ -From 6095169dd81a2dc26314ded00075544ff2717350 Mon Sep 17 00:00:00 2001 +From b0e4d25607d3a52f93139919c85482f87087f145 Mon Sep 17 00:00:00 2001 From: Bo Jiao -Date: Tue, 6 Feb 2024 14:32:46 +0800 -Subject: [PATCH 1/2] wifi: mt76: try more times when send message timeout. +Date: Thu, 7 Mar 2024 11:13:45 +0800 +Subject: [PATCH 1047/1053] wifi: mt76: try more times when send message + timeout. CR-Id: WCNCR00334773 Signed-off-by: Bo Jiao --- dma.c | 7 ++++-- mcu.c | 66 ++++++++++++++++++++++++++++++++++++---------------- - mt7915/mac.c | 45 +++++++++++------------------------ - 3 files changed, 64 insertions(+), 54 deletions(-) + mt7915/mac.c | 43 +++++++++++----------------------- + 3 files changed, 64 insertions(+), 52 deletions(-) diff --git a/dma.c b/dma.c -index bbae84f..11de65c 100644 +index bc8afcf..133a50d 100644 --- a/dma.c +++ b/dma.c @@ -504,9 +504,12 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, @@ -132,25 +133,23 @@ index fa4b054..de185cc 100644 return ret; diff --git a/mt7915/mac.c b/mt7915/mac.c -index aebfaf2..dd15d88 100644 +index 2e4a8f8..dbc1095 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c -@@ -1392,14 +1392,6 @@ mt7915_mac_restart(struct mt7915_dev *dev) +@@ -1389,12 +1389,6 @@ mt7915_mac_restart(struct mt7915_dev *dev) } } - set_bit(MT76_RESET, &dev->mphy.state); - set_bit(MT76_MCU_RESET, &dev->mphy.state); - wake_up(&dev->mt76.mcu.wait); -- if (ext_phy) { +- if (ext_phy) - set_bit(MT76_RESET, &ext_phy->state); -- set_bit(MT76_MCU_RESET, &ext_phy->state); -- } - /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); if (ext_phy) -@@ -1500,11 +1492,18 @@ mt7915_mac_full_reset(struct mt7915_dev *dev) +@@ -1495,11 +1489,18 @@ mt7915_mac_full_reset(struct mt7915_dev *dev) dev->recovery.hw_full_reset = true; @@ -170,7 +169,7 @@ index aebfaf2..dd15d88 100644 cancel_delayed_work_sync(&dev->mphy.mac_work); if (ext_phy) cancel_delayed_work_sync(&ext_phy->mac_work); -@@ -1592,20 +1591,15 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1587,20 +1588,15 @@ void mt7915_mac_reset_work(struct work_struct *work) set_bit(MT76_RESET, &dev->mphy.state); set_bit(MT76_MCU_RESET, &dev->mphy.state); @@ -194,7 +193,7 @@ index aebfaf2..dd15d88 100644 if (mtk_wed_device_active(&dev->mt76.mmio.wed)) mtk_wed_device_stop(&dev->mt76.mmio.wed); -@@ -1629,8 +1623,8 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1624,8 +1620,8 @@ void mt7915_mac_reset_work(struct work_struct *work) clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); @@ -205,7 +204,7 @@ index aebfaf2..dd15d88 100644 local_bh_disable(); mt76_for_each_q_rx(&dev->mt76, i) { -@@ -1652,21 +1646,8 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1647,21 +1643,8 @@ void mt7915_mac_reset_work(struct work_struct *work) if (ext_phy) ieee80211_wake_queues(ext_phy->hw); diff --git a/feeds/mediatek-sdk/mt76/patches/1051-wifi-mt76-mt7915-add-SER-overlap-handle.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1048-wifi-mt76-mt7915-add-SER-overlap-handle.patch similarity index 87% rename from feeds/mediatek-sdk/mt76/patches/1051-wifi-mt76-mt7915-add-SER-overlap-handle.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1048-wifi-mt76-mt7915-add-SER-overlap-handle.patch index b40ebde7e..28a07af25 100644 --- a/feeds/mediatek-sdk/mt76/patches/1051-wifi-mt76-mt7915-add-SER-overlap-handle.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1048-wifi-mt76-mt7915-add-SER-overlap-handle.patch @@ -1,7 +1,7 @@ -From d9ec9b87f64abcfec2a8ae78648a30f4c120842d Mon Sep 17 00:00:00 2001 +From 6b84e5955fac1b324c5ad7bf2ea585e6531697a7 Mon Sep 17 00:00:00 2001 From: Bo Jiao Date: Tue, 6 Feb 2024 14:46:59 +0800 -Subject: [PATCH 2/2] wifi: mt76: mt7915: add SER overlap handle +Subject: [PATCH 1048/1053] wifi: mt76: mt7915: add SER overlap handle CR-ID: WCNCR00355921 Signed-off-by: Bo Jiao @@ -14,7 +14,7 @@ Signed-off-by: Bo Jiao 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/dma.c b/dma.c -index 11de65c..cb26dc3 100644 +index 133a50d..100d2af 100644 --- a/dma.c +++ b/dma.c @@ -506,7 +506,8 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, @@ -53,10 +53,10 @@ index de185cc..1bc94e8 100644 dev_err(dev->dev, "send message %08x timeout, try again(%d).\n", cmd, (MT76_MSG_MAX_RETRY_CNT - retry_cnt)); diff --git a/mt76.h b/mt76.h -index 4291acd..484fc5b 100644 +index b023f38..fb50d88 100644 --- a/mt76.h +++ b/mt76.h -@@ -477,6 +477,14 @@ enum { +@@ -478,6 +478,14 @@ enum { MT76_STATE_WED_RESET, }; @@ -71,7 +71,7 @@ index 4291acd..484fc5b 100644 struct mt76_hw_cap { bool has_2ghz; bool has_5ghz; -@@ -940,6 +948,7 @@ struct mt76_dev { +@@ -944,6 +952,7 @@ struct mt76_dev { wait_queue_head_t tx_wait; /* spinclock used to protect wcid pktid linked list */ spinlock_t status_lock; @@ -80,10 +80,10 @@ index 4291acd..484fc5b 100644 u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; diff --git a/mt7915/mac.c b/mt7915/mac.c -index dd15d88..c1df503 100644 +index dbc1095..e9f50a3 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c -@@ -1582,6 +1582,7 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1579,6 +1579,7 @@ void mt7915_mac_reset_work(struct work_struct *work) if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) return; @@ -91,7 +91,7 @@ index dd15d88..c1df503 100644 dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.", wiphy_name(dev->mt76.hw->wiphy)); -@@ -1648,6 +1649,7 @@ void mt7915_mac_reset_work(struct work_struct *work) +@@ -1645,6 +1646,7 @@ void mt7915_mac_reset_work(struct work_struct *work) mt7915_update_beacons(dev); @@ -99,7 +99,7 @@ index dd15d88..c1df503 100644 dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.", wiphy_name(dev->mt76.hw->wiphy)); } -@@ -1786,6 +1788,15 @@ void mt7915_reset(struct mt7915_dev *dev) +@@ -1783,6 +1785,15 @@ void mt7915_reset(struct mt7915_dev *dev) return; } @@ -116,7 +116,7 @@ index dd15d88..c1df503 100644 wake_up(&dev->reset_wait); } diff --git a/mt7915/mcu.c b/mt7915/mcu.c -index 4bd7a3b..d80a61a 100644 +index b3faf77..f71688e 100644 --- a/mt7915/mcu.c +++ b/mt7915/mcu.c @@ -198,6 +198,13 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, diff --git a/feeds/mediatek-sdk/mt76/patches/1052-wifi-mt76-mt7915-add-background-radar-hw-cap-check.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1049-wifi-mt76-mt7915-add-background-radar-hw-cap-check.patch similarity index 93% rename from feeds/mediatek-sdk/mt76/patches/1052-wifi-mt76-mt7915-add-background-radar-hw-cap-check.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1049-wifi-mt76-mt7915-add-background-radar-hw-cap-check.patch index d24abe0ca..bfd88aa25 100644 --- a/feeds/mediatek-sdk/mt76/patches/1052-wifi-mt76-mt7915-add-background-radar-hw-cap-check.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1049-wifi-mt76-mt7915-add-background-radar-hw-cap-check.patch @@ -1,7 +1,8 @@ -From 775d8a30a7e0564ce77cc8a048045212d667e059 Mon Sep 17 00:00:00 2001 +From 016069539c9436262f37516462e9396e6f63b550 Mon Sep 17 00:00:00 2001 From: StanleyYP Wang Date: Mon, 4 Mar 2024 11:29:06 +0800 -Subject: [PATCH] wifi: mt76: mt7915: add background radar hw cap check +Subject: [PATCH 1049/1053] wifi: mt76: mt7915: add background radar hw cap + check Signed-off-by: StanleyYP Wang --- @@ -11,7 +12,7 @@ Signed-off-by: StanleyYP Wang 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c -index 017d43d..599a794 100644 +index b2a4ff4..03daf44 100644 --- a/mt7915/debugfs.c +++ b/mt7915/debugfs.c @@ -459,6 +459,11 @@ mt7915_rdd_monitor(struct seq_file *s, void *data) @@ -75,7 +76,7 @@ index 70fca0b..adeee10 100644 #endif diff --git a/mt7915/init.c b/mt7915/init.c -index 32bbd6c..872e615 100644 +index b53075b..26ae63f 100644 --- a/mt7915/init.c +++ b/mt7915/init.c @@ -404,9 +404,10 @@ mt7915_init_wiphy(struct mt7915_phy *phy) diff --git a/feeds/mediatek-sdk/mt76/patches/1052-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1050-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch similarity index 94% rename from feeds/mediatek-sdk/mt76/patches/1052-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch rename to feeds/mediatek-sdk/mt76/mt76/patches/1050-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch index 48bab63b9..840d787b7 100644 --- a/feeds/mediatek-sdk/mt76/patches/1052-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1050-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch @@ -1,7 +1,8 @@ -From faaaf4ee3fc3f230cc3c039f114296f12e00e98c Mon Sep 17 00:00:00 2001 +From 1e641bcbd21de95f4719063eecde6df206e2cf55 Mon Sep 17 00:00:00 2001 From: Henry Yen Date: Wed, 6 Mar 2024 12:42:06 +0800 -Subject: [PATCH] wifi: mt76: mt7915: remove unnecessary register settings +Subject: [PATCH 1050/1053] wifi: mt76: mt7915: remove unnecessary register + settings Remove unnecessary register settings from the driver layer, and let firmware take over the configuration control. @@ -13,7 +14,7 @@ Signed-off-by: Henry.Yen 2 files changed, 1 insertion(+), 77 deletions(-) diff --git a/mt7915/init.c b/mt7915/init.c -index bb6b746..3f7a5ff 100644 +index 26ae63f..9ffeca5 100644 --- a/mt7915/init.c +++ b/mt7915/init.c @@ -488,30 +488,6 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) @@ -72,10 +73,10 @@ index bb6b746..3f7a5ff 100644 mt7915_mac_wtbl_update(dev, i, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); diff --git a/mt7915/mac.c b/mt7915/mac.c -index ac45e1b..ec8bdd4 100644 +index e9f50a3..c84b957 100644 --- a/mt7915/mac.c +++ b/mt7915/mac.c -@@ -1241,61 +1241,20 @@ void mt7915_mac_reset_counters(struct mt7915_phy *phy) +@@ -1202,61 +1202,20 @@ void mt7915_mac_reset_counters(struct mt7915_phy *phy) void mt7915_mac_set_timing(struct mt7915_phy *phy) { diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1051-wifi-mt76-mt7915-add-foolproof-mechanism-for-ZWDFS-d.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1051-wifi-mt76-mt7915-add-foolproof-mechanism-for-ZWDFS-d.patch new file mode 100644 index 000000000..5c966ecdf --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1051-wifi-mt76-mt7915-add-foolproof-mechanism-for-ZWDFS-d.patch @@ -0,0 +1,45 @@ +From 25eef0359cbdfb1a1e7730da256ac35a943242ea Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Wed, 6 Mar 2024 11:30:34 +0800 +Subject: [PATCH 1051/1053] wifi: mt76: mt7915: add foolproof mechanism for + ZWDFS during radar detected & triggered + +Signed-off-by: StanleyYP Wang +--- + mt7915/debugfs.c | 5 +++++ + mt7915/mcu.c | 3 +++ + 2 files changed, 8 insertions(+) + +diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c +index 03daf44..d8ca90a 100644 +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -231,6 +231,11 @@ mt7915_radar_trigger(void *data, u64 val) + if (val > MT_RX_SEL2) + return -EINVAL; + ++ if (val == MT_RX_SEL2 && !dev->rdd2_phy) { ++ dev_err(dev->mt76.dev, "Background radar is not enabled\n"); ++ return -EINVAL; ++ } ++ + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_RADAR_EMULATE, + val, 0, 0); + } +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index f71688e..d857658 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -302,6 +302,9 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) + if (r->band_idx > MT_RX_SEL2) + return; + ++ if (r->band_idx == MT_RX_SEL2 && !dev->rdd2_phy) ++ return; ++ + if ((r->band_idx && !dev->phy.mt76->band_idx) && + dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1052-mtk-wifi-mt76-mt7915-assign-DEAUTH-to-ALTX-queue-for.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1052-mtk-wifi-mt76-mt7915-assign-DEAUTH-to-ALTX-queue-for.patch new file mode 100644 index 000000000..8f766d065 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1052-mtk-wifi-mt76-mt7915-assign-DEAUTH-to-ALTX-queue-for.patch @@ -0,0 +1,42 @@ +From 93810a9bad2fd59c8e4742195a3b5c53878116ef Mon Sep 17 00:00:00 2001 +From: Michael-CY Lee +Date: Tue, 19 Mar 2024 08:35:26 +0800 +Subject: [PATCH 1052/1053] mtk: wifi: mt76: mt7915: assign DEAUTH to ALTX + queue for CERT + +Signed-off-by: Michael-CY Lee +--- + mt76_connac_mac.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c +index d41f004..0510296 100644 +--- a/mt76_connac_mac.c ++++ b/mt76_connac_mac.c +@@ -385,6 +385,8 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, + struct sk_buff *skb, + struct ieee80211_key_conf *key) + { ++ struct mt76_phy *mphy = ++ mt76_dev_phy(dev, le32_get_bits(txwi[1], MT_TXD1_TGID)); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +@@ -394,6 +396,14 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, + u8 fc_type, fc_stype; + u32 val; + ++ if (ieee80211_is_cert_mode(mphy->hw) && ieee80211_is_deauth(fc)) { ++ /* In WPA3 cert TC-4.8.1, the deauth must be transmitted without ++ * considering PSM bit ++ */ ++ txwi[0] &= ~cpu_to_le32(MT_TXD0_Q_IDX); ++ txwi[0] |= cpu_to_le32(FIELD_PREP(MT_TXD0_Q_IDX, MT_LMAC_ALTX0)); ++ } ++ + if (ieee80211_is_action(fc) && + mgmt->u.action.category == WLAN_CATEGORY_BACK && + mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/1053-wifi-mt76-mt7915-set-channel-after-sta-is-associated.patch b/feeds/mediatek-sdk/mt76/mt76/patches/1053-wifi-mt76-mt7915-set-channel-after-sta-is-associated.patch new file mode 100644 index 000000000..e9c88e1a0 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/1053-wifi-mt76-mt7915-set-channel-after-sta-is-associated.patch @@ -0,0 +1,64 @@ +From 124ffa4206375bcbcb8bfaa0032045e3063ad286 Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Thu, 21 Mar 2024 16:52:34 +0800 +Subject: [PATCH 1053/1053] wifi: mt76: mt7915: set channel after sta is + associated to adjust switch reason + +when sta is associated to AP operating in DFS channel, a channel +setting operation is required to change the channel switch reason +from CH_SWTICH_DFS to CH_SWITCH_NORMAL. +Note that the switch reason for DFS channel during authentication is +CH_SWITCH_DFS since the DFS state is still USABLE at that point + +Signed-off-by: StanleyYP Wang +--- + mt7915/main.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/mt7915/main.c b/mt7915/main.c +index 69fcf4c..41fa450 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -792,6 +792,31 @@ out: + return ret; + } + ++static void ++mt7915_event_callback(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ const struct ieee80211_event *event) ++{ ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ int ret; ++ ++ switch (event->type) { ++ case MLME_EVENT: ++ if (event->u.mlme.data == ASSOC_EVENT && ++ event->u.mlme.status == MLME_SUCCESS) { ++ ieee80211_stop_queues(hw); ++ ret = mt7915_set_channel(phy); ++ if (ret) ++ return; ++ ieee80211_wake_queues(hw); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return; ++} ++ + int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +@@ -1771,6 +1796,7 @@ const struct ieee80211_ops mt7915_ops = { + .set_sar_specs = mt7915_set_sar_specs, + .channel_switch_beacon = mt7915_channel_switch_beacon, + .post_channel_switch = mt7915_post_channel_switch, ++ .event_callback = mt7915_event_callback, + .get_stats = mt7915_get_stats, + .get_et_sset_count = mt7915_get_et_sset_count, + .get_et_stats = mt7915_get_et_stats, +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/2000-wifi-mt76-mt7915-wed-add-wed-tx-support.patch b/feeds/mediatek-sdk/mt76/mt76/patches/2000-wifi-mt76-mt7915-wed-add-wed-tx-support.patch new file mode 100644 index 000000000..8d6705ef5 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/2000-wifi-mt76-mt7915-wed-add-wed-tx-support.patch @@ -0,0 +1,139 @@ +From 86f4aafcab8e833c7009e453e97adc254628d4d1 Mon Sep 17 00:00:00 2001 +From: Sujuan Chen +Date: Fri, 25 Nov 2022 10:38:53 +0800 +Subject: [PATCH 2000/2014] wifi: mt76: mt7915: wed: add wed tx support + +Signed-off-by: Sujuan Chen +--- + mt76_connac.h | 1 + + mt7915/mac.c | 10 +++++++--- + mt7915/main.c | 4 ++-- + mt7915/mmio.c | 3 ++- + mt7915/mt7915.h | 2 +- + wed.c | 2 +- + 6 files changed, 14 insertions(+), 8 deletions(-) + +diff --git a/mt76_connac.h b/mt76_connac.h +index 8e7068c..e1d6ca2 100644 +--- a/mt76_connac.h ++++ b/mt76_connac.h +@@ -130,6 +130,7 @@ struct mt76_connac_sta_key_conf { + }; + + #define MT_TXP_MAX_BUF_NUM 6 ++#define MT_TXD_TXP_BUF_SIZE 128 + + struct mt76_connac_fw_txp { + __le16 flags; +diff --git a/mt7915/mac.c b/mt7915/mac.c +index c84b957..1c8b873 100644 +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -878,9 +878,9 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id) + + txp->token = cpu_to_le16(token_id); + txp->nbuf = 1; +- txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp)); ++ txp->buf[0] = cpu_to_le32(phys + MT_TXD_TXP_BUF_SIZE); + +- return MT_TXD_SIZE + sizeof(*txp); ++ return MT_TXD_TXP_BUF_SIZE; + } + + static void +@@ -929,6 +929,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) + LIST_HEAD(free_list); + void *end = data + len; + bool v3, wake = false; ++ bool with_txwi = true; + u16 total, count = 0; + u32 txd = le32_to_cpu(free->txd); + __le32 *cur_info; +@@ -1010,12 +1011,15 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) + txwi = mt76_token_release(mdev, msdu, &wake); + if (!txwi) + continue; ++ else ++ with_txwi = false; + + mt76_connac2_txwi_free(mdev, txwi, sta, &free_list); + } + } + +- mt7915_mac_tx_free_done(dev, &free_list, wake); ++ if (!with_txwi) ++ mt7915_mac_tx_free_done(dev, &free_list, wake); + } + + static void +diff --git a/mt7915/main.c b/mt7915/main.c +index 41fa450..332b087 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -1753,14 +1753,14 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, + if (!mtk_wed_device_active(wed)) + return -ENODEV; + +- if (msta->wcid.idx > 0xff) ++ if (msta->wcid.idx > MT7915_WTBL_STA) + return -EIO; + + path->type = DEV_PATH_MTK_WDMA; + path->dev = ctx->dev; + path->mtk_wdma.wdma_idx = wed->wdma_idx; + path->mtk_wdma.bss = mvif->mt76.idx; +- path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; ++ path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? 0xff : 0x3ff; + path->mtk_wdma.queue = phy != &dev->phy; + + ctx->dev = NULL; +diff --git a/mt7915/mmio.c b/mt7915/mmio.c +index 437a9b0..91100f1 100644 +--- a/mt7915/mmio.c ++++ b/mt7915/mmio.c +@@ -13,7 +13,7 @@ + #include "../trace.h" + #include "../dma.h" + +-static bool wed_enable; ++static bool wed_enable = true; + module_param(wed_enable, bool, 0644); + MODULE_PARM_DESC(wed_enable, "Enable Wireless Ethernet Dispatch support"); + +@@ -732,6 +732,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, + + *irq = wed->irq; + dev->mt76.dma_dev = wed->dev; ++ dev->mt76.token_size = wed->wlan.token_start; + + ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32)); + if (ret) +diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h +index 47f7d16..1d0188d 100644 +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -62,7 +62,7 @@ + #define MT7916_EEPROM_SIZE 4096 + + #define MT7915_EEPROM_BLOCK_SIZE 16 +-#define MT7915_HW_TOKEN_SIZE 4096 ++#define MT7915_HW_TOKEN_SIZE 7168 + #define MT7915_TOKEN_SIZE 8192 + + #define MT7915_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ +diff --git a/wed.c b/wed.c +index f7a3f1b..47c81a2 100644 +--- a/wed.c ++++ b/wed.c +@@ -187,7 +187,7 @@ void mt76_wed_offload_disable(struct mtk_wed_device *wed) + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + + spin_lock_bh(&dev->token_lock); +- dev->token_size = dev->drv->token_size; ++ dev->token_size = wed->wlan.token_start; + spin_unlock_bh(&dev->token_lock); + } + EXPORT_SYMBOL_GPL(mt76_wed_offload_disable); +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/2001-wifi-mt76-mt7915-wed-add-wds-support-when-wed-is-ena.patch b/feeds/mediatek-sdk/mt76/mt76/patches/2001-wifi-mt76-mt7915-wed-add-wds-support-when-wed-is-ena.patch new file mode 100644 index 000000000..9ddec3e60 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/2001-wifi-mt76-mt7915-wed-add-wds-support-when-wed-is-ena.patch @@ -0,0 +1,210 @@ +From ab7172fb880f05bc6005a78982278c5b365055b4 Mon Sep 17 00:00:00 2001 +From: Sujuan Chen +Date: Tue, 13 Dec 2022 17:51:26 +0800 +Subject: [PATCH 2001/2014] wifi: mt76: mt7915: wed: add wds support when wed + is enabled + +Signed-off-by: Sujuan Chen +--- + mt76.h | 6 ++++++ + mt7915/main.c | 22 ++++++++++++++++++++-- + mt7915/mcu.c | 16 ++++++++++++---- + mt7915/mcu.h | 1 + + util.c | 40 +++++++++++++++++++++++++++++++++++++--- + util.h | 7 ++++++- + 6 files changed, 82 insertions(+), 10 deletions(-) + +diff --git a/mt76.h b/mt76.h +index fb50d88..d3c6ac0 100644 +--- a/mt76.h ++++ b/mt76.h +@@ -78,6 +78,12 @@ enum mt76_wed_type { + MT76_WED_RRO_Q_IND, + }; + ++enum mt76_wed_state { ++ MT76_WED_DEFAULT, ++ MT76_WED_ACTIVE, ++ MT76_WED_WDS_ACTIVE, ++}; ++ + struct mt76_bus_ops { + u32 (*rr)(struct mt76_dev *dev, u32 offset); + void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); +diff --git a/mt7915/main.c b/mt7915/main.c +index 332b087..ab60159 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -829,8 +829,15 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + #endif + int ret, idx; + u32 addr; ++ u8 flags = MT76_WED_DEFAULT; + +- idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); ++ if (mtk_wed_device_active(&dev->mt76.mmio.wed) && ++ !is_mt7915(&dev->mt76)) { ++ flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ? ++ MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE; ++ } ++ ++ idx = __mt76_wcid_alloc(mdev->wcid_mask, MT7915_WTBL_STA, flags); + if (idx < 0) + return -ENOSPC; + +@@ -1321,6 +1328,13 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, + else + clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); + ++ if (mtk_wed_device_active(&dev->mt76.mmio.wed) && ++ !is_mt7915(&dev->mt76)) { ++ mt7915_sta_remove(hw, vif, sta); ++ mt76_sta_pre_rcu_remove(hw, vif, sta); ++ mt7915_sta_add(hw, vif, sta); ++ } ++ + mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); + } + +@@ -1760,8 +1774,12 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, + path->dev = ctx->dev; + path->mtk_wdma.wdma_idx = wed->wdma_idx; + path->mtk_wdma.bss = mvif->mt76.idx; +- path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? 0xff : 0x3ff; + path->mtk_wdma.queue = phy != &dev->phy; ++ if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) || ++ is_mt7915(&dev->mt76)) ++ path->mtk_wdma.wcid = msta->wcid.idx; ++ else ++ path->mtk_wdma.wcid = 0x3ff; + + ctx->dev = NULL; + +diff --git a/mt7915/mcu.c b/mt7915/mcu.c +index d857658..b42afe8 100644 +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -2588,10 +2588,18 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) + if (ret) + return ret; + +- if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && +- is_mt7915(&dev->mt76)) || +- !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) +- mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); ++ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { ++ if (is_mt7915(&dev->mt76) || ++ !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) ++ ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), ++ 0, 0, 0); ++ else ++ ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), ++ MCU_WA_PARAM_WED_VERSION, ++ dev->mt76.mmio.wed.rev_id, 0); ++ if (ret) ++ return ret; ++ } + + ret = mt7915_mcu_set_mwds(dev, 1); + if (ret) +diff --git a/mt7915/mcu.h b/mt7915/mcu.h +index f476767..52baaa7 100644 +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -392,6 +392,7 @@ enum { + MCU_WA_PARAM_PDMA_RX = 0x04, + MCU_WA_PARAM_CPU_UTIL = 0x0b, + MCU_WA_PARAM_RED = 0x0e, ++ MCU_WA_PARAM_WED_VERSION = 0x32, + #ifdef MTK_DEBUG + MCU_WA_PARAM_RED_SHOW_STA = 0xf, + MCU_WA_PARAM_RED_TARGET_DELAY = 0x10, +diff --git a/util.c b/util.c +index fc76c66..61b2d30 100644 +--- a/util.c ++++ b/util.c +@@ -42,9 +42,14 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, + } + EXPORT_SYMBOL_GPL(____mt76_poll_msec); + +-int mt76_wcid_alloc(u32 *mask, int size) ++int __mt76_wcid_alloc(u32 *mask, int size, u8 flag) + { ++#define MT76_WED_WDS_MIN 256 ++#define MT76_WED_WDS_CNT 16 ++ + int i, idx = 0, cur; ++ int min = MT76_WED_WDS_MIN; ++ int max = min + MT76_WED_WDS_CNT; + + for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { + idx = ffs(~mask[i]); +@@ -53,16 +58,45 @@ int mt76_wcid_alloc(u32 *mask, int size) + + idx--; + cur = i * 32 + idx; +- if (cur >= size) ++ ++ switch (flag) { ++ case MT76_WED_ACTIVE: ++ if (cur >= min && cur < max) ++ continue; ++ ++ if (cur >= size) { ++ u32 end = MT76_WED_WDS_CNT - 1; ++ ++ i = min / 32; ++ idx = ffs(~mask[i] & GENMASK(end, 0)); ++ if (!idx) ++ goto error; ++ idx--; ++ cur = min + idx; ++ } ++ + break; ++ case MT76_WED_WDS_ACTIVE: ++ if (cur < min) ++ continue; ++ if (cur >= max) ++ goto error; ++ ++ break; ++ default: ++ if (cur >= size) ++ goto error; ++ break; ++ } + + mask[i] |= BIT(idx); + return cur; + } + ++error: + return -1; + } +-EXPORT_SYMBOL_GPL(mt76_wcid_alloc); ++EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); + + int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy) + { +diff --git a/util.h b/util.h +index 260965d..99b7263 100644 +--- a/util.h ++++ b/util.h +@@ -27,7 +27,12 @@ enum { + #define MT76_INCR(_var, _size) \ + (_var = (((_var) + 1) % (_size))) + +-int mt76_wcid_alloc(u32 *mask, int size); ++int __mt76_wcid_alloc(u32 *mask, int size, u8 flags); ++ ++static inline int mt76_wcid_alloc(u32 *mask, int size) ++{ ++ return __mt76_wcid_alloc(mask, size, 0); ++} + + static inline void + mt76_wcid_mask_set(u32 *mask, int idx) +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/2002-wifi-mt76-mt7915-wed-add-fill-receive-path-to-report.patch b/feeds/mediatek-sdk/mt76/mt76/patches/2002-wifi-mt76-mt7915-wed-add-fill-receive-path-to-report.patch new file mode 100644 index 000000000..98ec448c6 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/2002-wifi-mt76-mt7915-wed-add-fill-receive-path-to-report.patch @@ -0,0 +1,50 @@ +From 6fa429e617e59379bd82c8dbef851e99954676ed Mon Sep 17 00:00:00 2001 +From: Evelyn Tsai +Date: Fri, 19 May 2023 07:05:22 +0800 +Subject: [PATCH 2002/2014] wifi: mt76: mt7915: wed: add fill receive path to + report wed idx + +Signed-off-by: Sujuan Chen +--- + mt7915/main.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/mt7915/main.c b/mt7915/main.c +index ab60159..b3e06aa 100644 +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -1785,6 +1785,23 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, + + return 0; + } ++ ++static int ++mt7915_net_fill_receive_path(struct ieee80211_hw *hw, ++ struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ struct mt7915_dev *dev = mt7915_hw_dev(hw); ++ struct mtk_wed_device *wed = &dev->mt76.mmio.wed; ++ ++ if (!mtk_wed_device_active(wed)) ++ return -ENODEV; ++ ++ path->dev = ctx->dev; ++ path->mtk_wdma.wdma_idx = wed->wdma_idx; ++ ++ return 0; ++} + #endif + + const struct ieee80211_ops mt7915_ops = { +@@ -1841,6 +1858,7 @@ const struct ieee80211_ops mt7915_ops = { + .set_radar_background = mt7915_set_radar_background, + #ifdef CONFIG_NET_MEDIATEK_SOC_WED + .net_fill_forward_path = mt7915_net_fill_forward_path, ++ .net_fill_receive_path = mt7915_net_fill_receive_path, + .net_setup_tc = mt76_wed_net_setup_tc, + #endif + }; +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/2003-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch b/feeds/mediatek-sdk/mt76/mt76/patches/2003-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch new file mode 100644 index 000000000..54c520ece --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/2003-wifi-mt76-mt7915-wed-find-rx-token-by-physical-addre.patch @@ -0,0 +1,55 @@ +From 79d00e5e7ff7653dc6839551f33a5b36d6291169 Mon Sep 17 00:00:00 2001 +From: Sujuan Chen +Date: Fri, 25 Nov 2022 14:32:35 +0800 +Subject: [PATCH 2003/2014] wifi: mt76: mt7915: wed: find rx token by physical + address + +The token id in RxDMAD may be incorrect when it is not the last frame due to +WED HW bug. Lookup correct token id by physical address in sdp0. + +Signed-off-by: Peter Chiu +--- + dma.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git a/dma.c b/dma.c +index 100d2af..185c6f1 100644 +--- a/dma.c ++++ b/dma.c +@@ -444,9 +444,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, + mt76_dma_should_drop_buf(drop, ctrl, buf1, desc_info); + + if (mt76_queue_is_wed_rx(q)) { ++ u32 id, find = 0; + u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1); +- struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token); ++ struct mt76_txwi_cache *t; ++ ++ if (*more) { ++ spin_lock_bh(&dev->rx_token_lock); ++ ++ idr_for_each_entry(&dev->rx_token, t, id) { ++ if (t->dma_addr == le32_to_cpu(desc->buf0)) { ++ find = 1; ++ token = id; ++ ++ /* Write correct id back to DMA*/ ++ u32p_replace_bits(&buf1, id, ++ MT_DMA_CTL_TOKEN); ++ WRITE_ONCE(desc->buf1, cpu_to_le32(buf1)); ++ break; ++ } ++ } ++ ++ spin_unlock_bh(&dev->rx_token_lock); ++ if (!find) ++ return NULL; ++ } + ++ t = mt76_rx_token_release(dev, token); + if (!t) + return NULL; + +-- +2.18.0 + diff --git a/feeds/mediatek-sdk/mt76/mt76/patches/2004-wifi-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch b/feeds/mediatek-sdk/mt76/mt76/patches/2004-wifi-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch new file mode 100644 index 000000000..936d19d43 --- /dev/null +++ b/feeds/mediatek-sdk/mt76/mt76/patches/2004-wifi-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch @@ -0,0 +1,999 @@ +From f4c4eda21841dae1229e6f7942d4a74f385d87a5 Mon Sep 17 00:00:00 2001 +From: Lian Chen +Date: Mon, 7 Nov 2022 14:47:44 +0800 +Subject: [PATCH 2004/2014] wifi: mt76: mt7915: wed: HW ATF support for mt7986 + +Signed-off-by: Lian Chen +Signed-off-by: Benjamin Lin +--- + mt76_connac_mcu.h | 2 + + mt7915/debugfs.c | 357 +++++++++++++++++++++++++++++++++++++++++++ + mt7915/init.c | 58 +++++++ + mt7915/main.c | 14 ++ + mt7915/mcu.c | 169 +++++++++++++++++++- + mt7915/mt7915.h | 69 +++++++++ + mt7915/mtk_debugfs.c | 130 ++++++++++++++++ + 7 files changed, 796 insertions(+), 3 deletions(-) + +diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h +index dc60e35..03d6a2b 100644 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1209,6 +1209,7 @@ enum { + MCU_EXT_CMD_THERMAL_CTRL = 0x2c, + MCU_EXT_CMD_WTBL_UPDATE = 0x32, + MCU_EXT_CMD_SET_DRR_CTRL = 0x36, ++ MCU_EXT_CMD_SET_FEATURE_CTRL = 0x38, + MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, + MCU_EXT_CMD_ATE_CTRL = 0x3d, + MCU_EXT_CMD_PROTECT_CTRL = 0x3e, +@@ -1218,6 +1219,7 @@ enum { + MCU_EXT_CMD_MUAR_UPDATE = 0x48, + MCU_EXT_CMD_BCN_OFFLOAD = 0x49, + MCU_EXT_CMD_RX_AIRTIME_CTRL = 0x4a, ++ MCU_EXT_CMD_AT_PROC_MODULE = 0x4b, + MCU_EXT_CMD_SET_RX_PATH = 0x4e, + MCU_EXT_CMD_EFUSE_FREE_BLOCK = 0x4f, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, +diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c +index d8ca90a..3ae4aca 100644 +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -12,6 +12,10 @@ + #define FW_BIN_LOG_MAGIC_V2 0x44d9c99a + #endif + ++#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] ++#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" ++ ++ + /** global debugfs **/ + + struct hw_queue_map { +@@ -223,6 +227,358 @@ static const struct file_operations mt7915_sys_recovery_ops = { + .llseek = default_llseek, + }; + ++static ssize_t mt7915_vow_get(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ char *buff; ++ int desc = 0; ++ ssize_t ret; ++ static const size_t bufsz = 1000; ++ ++ buff = kmalloc(bufsz, GFP_KERNEL); ++ if (!buff) ++ return -ENOMEM; ++ ++ desc += scnprintf(buff + desc, bufsz - desc, ++ "======== Control =============\n" ++ "vow_atf_en=<0/1> 0:disable, 1:enable\n" ++ "vow_watf_en=<0/1> 0:disable, 1:enable\n" ++ "vow_watf_quantum=- unit 256us\n" ++ "======== Station table =============\n" ++ "vow_sta_dwrr_quantum_id=--\n" ++ "vow_dwrr_max_wait_time=