diff --git a/include/package-defaults.mk b/include/package-defaults.mk index 2fed72b1a4..2a04bc17e9 100644 --- a/include/package-defaults.mk +++ b/include/package-defaults.mk @@ -59,6 +59,7 @@ define Package/Default ALTERNATIVES:= LICENSE:=$(PKG_LICENSE) LICENSE_FILES:=$(PKG_LICENSE_FILES) + FILE_MODES:=$(PKG_FILE_MODES) endef Build/Patch:=$(Build/Patch/Default) diff --git a/include/package-ipkg.mk b/include/package-ipkg.mk index 62cda5b936..0bca8ae84d 100644 --- a/include/package-ipkg.mk +++ b/include/package-ipkg.mk @@ -260,7 +260,7 @@ $(_endef) endif $(INSTALL_DIR) $$(PDIR_$(1)) - $(FAKEROOT) $(SCRIPT_DIR)/ipkg-build -m "$(PKG_FILE_MODES)" $$(IDIR_$(1)) $$(PDIR_$(1)) + $(FAKEROOT) $(SCRIPT_DIR)/ipkg-build -m "$(FILE_MODES)" $$(IDIR_$(1)) $$(PDIR_$(1)) @[ -f $$(IPKG_$(1)) ] $(1)-clean: diff --git a/package/firmware/wireless-regdb/patches/600-custom-change-txpower-and-dfs.patch b/package/firmware/wireless-regdb/patches/600-custom-change-txpower-and-dfs.patch deleted file mode 100644 index 0435d4e75b..0000000000 --- a/package/firmware/wireless-regdb/patches/600-custom-change-txpower-and-dfs.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/db.txt b/db.txt -index 90d3bc9..cc2a595 100644 ---- a/db.txt -+++ b/db.txt -@@ -347,9 +347,9 @@ country CL: DFS-JP - (5735 - 5835 @ 80), (20) - - country CN: DFS-FCC -- (2402 - 2482 @ 40), (20) -- (5170 - 5250 @ 80), (23), AUTO-BW -- (5250 - 5330 @ 80), (23), DFS, AUTO-BW -+ (2402 - 2482 @ 40), (30) -+ (5170 - 5250 @ 80), (30), AUTO-BW -+ (5250 - 5330 @ 80), (30), AUTO-BW - (5735 - 5835 @ 80), (30) - # 60 GHz band channels 1,4: 28dBm, channels 2,3: 44dBm - # ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf -@@ -1571,13 +1571,13 @@ country UG: DFS-FCC - country US: DFS-FCC - (2400 - 2483.5 @ 40), (30) - # 5.15 ~ 5.25 GHz: 30 dBm for master mode, 23 dBm for clients -- (5150 - 5250 @ 80), (23), AUTO-BW -- (5250 - 5350 @ 80), (23), DFS, AUTO-BW -+ (5150 - 5250 @ 80), (30), AUTO-BW -+ (5250 - 5350 @ 80), (30), AUTO-BW - # This range ends at 5725 MHz, but channel 144 extends to 5730 MHz. - # Since 5725 ~ 5730 MHz belongs to the next range which has looser - # requirements, we can extend the range by 5 MHz to make the kernel - # happy and be able to use channel 144. -- (5470 - 5730 @ 160), (23), DFS -+ (5470 - 5730 @ 160), (30) - (5730 - 5850 @ 80), (30) - # 60g band - # reference: section IV-D https://docs.fcc.gov/public/attachments/FCC-16-89A1.pdf diff --git a/package/kernel/mac80211/patches/subsys/320-mac80211-add-missing-queue-hash-initialization-to-80.patch b/package/kernel/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch similarity index 97% rename from package/kernel/mac80211/patches/subsys/320-mac80211-add-missing-queue-hash-initialization-to-80.patch rename to package/kernel/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch index d9d3fded75..eb56a2cac5 100644 --- a/package/kernel/mac80211/patches/subsys/320-mac80211-add-missing-queue-hash-initialization-to-80.patch +++ b/package/kernel/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch @@ -1,7 +1,7 @@ From: Felix Fietkau Date: Mon, 17 Aug 2020 13:55:56 +0200 -Subject: [PATCH] mac80211: add missing queue/hash initialization to 802.3 - xmit +Subject: [PATCH] mac80211: add missing queue/hash initialization to + 802.3 xmit Fixes AQL for encap-offloaded tx diff --git a/package/kernel/mac80211/patches/subsys/321-mac80211-check-and-refresh-aggregation-session-in-en.patch b/package/kernel/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch similarity index 98% rename from package/kernel/mac80211/patches/subsys/321-mac80211-check-and-refresh-aggregation-session-in-en.patch rename to package/kernel/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch index 0188e19b71..e411d59722 100644 --- a/package/kernel/mac80211/patches/subsys/321-mac80211-check-and-refresh-aggregation-session-in-en.patch +++ b/package/kernel/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch @@ -1,7 +1,7 @@ From: Felix Fietkau Date: Mon, 17 Aug 2020 21:11:25 +0200 -Subject: [PATCH] mac80211: check and refresh aggregation session in encap - offload tx +Subject: [PATCH] mac80211: check and refresh aggregation session in + encap offload tx Update the last_tx timestamp to avoid tearing down the aggregation session early. Fall back to the slow path if the session setup is still running diff --git a/package/kernel/mac80211/patches/subsys/325-mac80211-skip-encap-offload-for-tx-multicast-control.patch b/package/kernel/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch similarity index 77% rename from package/kernel/mac80211/patches/subsys/325-mac80211-skip-encap-offload-for-tx-multicast-control.patch rename to package/kernel/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch index a32075768a..6dce21db1e 100644 --- a/package/kernel/mac80211/patches/subsys/325-mac80211-skip-encap-offload-for-tx-multicast-control.patch +++ b/package/kernel/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch @@ -10,28 +10,6 @@ using an AP_VLAN. Signed-off-by: Felix Fietkau --- ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -378,7 +378,8 @@ static bool ieee80211_set_sdata_offload_ - if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC || - key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || - key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || -- key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) -+ key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256 || -+ !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) - continue; - if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP || - !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) -@@ -1448,7 +1449,8 @@ static void ieee80211_set_vif_encap_ops( - if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC || - key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || - key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || -- key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) -+ key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256 || -+ !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) - continue; - if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) - enabled = false; --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -4184,88 +4184,47 @@ static void ieee80211_8023_xmit(struct i @@ -144,8 +122,8 @@ Signed-off-by: Felix Fietkau + struct ethhdr *ehdr = (struct ethhdr *)skb->data; struct sta_info *sta; - if (unlikely(skb->len < ETH_HLEN)) { -@@ -4297,6 +4257,10 @@ netdev_tx_t ieee80211_subif_start_xmit_8 + if (WARN_ON(!sdata->hw_80211_encap)) { +@@ -4302,6 +4262,10 @@ netdev_tx_t ieee80211_subif_start_xmit_8 if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) kfree_skb(skb); diff --git a/package/kernel/mac80211/patches/subsys/326-mac80211-set-info-control.hw_key-for-encap-offload-p.patch b/package/kernel/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch similarity index 93% rename from package/kernel/mac80211/patches/subsys/326-mac80211-set-info-control.hw_key-for-encap-offload-p.patch rename to package/kernel/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch index 421d18f2c2..cb5a986312 100644 --- a/package/kernel/mac80211/patches/subsys/326-mac80211-set-info-control.hw_key-for-encap-offload-p.patch +++ b/package/kernel/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau u8 tid; @@ -4233,6 +4234,10 @@ static void ieee80211_8023_xmit(struct i - info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; + info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP; info->control.vif = &sdata->vif; + key = rcu_dereference(sta->ptk[sta->ptk_idx]); diff --git a/package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch b/package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch similarity index 82% rename from package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch rename to package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch index 4f0d264947..7593c41da0 100644 --- a/package/kernel/mac80211/patches/subsys/314-mac80211-rework-tx-encapsulation-offload-API.patch +++ b/package/kernel/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch @@ -198,34 +198,6 @@ Signed-off-by: Felix Fietkau }; /** ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -504,6 +504,7 @@ static int ieee80211_del_key(struct wiph - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - struct ieee80211_key *key = NULL; -+ bool recalc_offload = false; - int ret; - - mutex_lock(&local->sta_mtx); -@@ -528,6 +529,7 @@ static int ieee80211_del_key(struct wiph - goto out_unlock; - } - -+ recalc_offload = key->conf.cipher == WLAN_CIPHER_SUITE_TKIP; - ieee80211_key_free(key, sdata->vif.type == NL80211_IFTYPE_STATION); - - ret = 0; -@@ -535,6 +537,9 @@ static int ieee80211_del_key(struct wiph - mutex_unlock(&local->key_mtx); - mutex_unlock(&local->sta_mtx); - -+ if (recalc_offload) -+ ieee80211_recalc_offload(local); -+ - return ret; - } - --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -408,6 +408,7 @@ static const char *hw_flag_names[] = { @@ -287,16 +259,15 @@ Signed-off-by: Felix Fietkau bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) { -@@ -348,6 +349,99 @@ static int ieee80211_check_queues(struct +@@ -348,6 +349,85 @@ static int ieee80211_check_queues(struct return 0; } +static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype) +{ + switch (iftype) { ++ /* P2P GO and client are mapped to AP/STATION types */ + case NL80211_IFTYPE_AP: -+ case NL80211_IFTYPE_P2P_GO: -+ case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + return true; + default: @@ -307,7 +278,6 @@ Signed-off-by: Felix Fietkau +static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; -+ struct ieee80211_key *key; + u32 flags; + + flags = sdata->vif.offload_flags; @@ -315,18 +285,6 @@ Signed-off-by: Felix Fietkau + if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) && + ieee80211_iftype_supports_encap_offload(sdata->vif.type)) { + flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED; -+ mutex_lock(&local->key_mtx); -+ list_for_each_entry(key, &sdata->key_list, list) { -+ if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC || -+ key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || -+ key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || -+ key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) -+ continue; -+ if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP || -+ !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) -+ flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; -+ } -+ mutex_unlock(&local->key_mtx); + + if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) && + local->hw.wiphy->frag_threshold != (u32)-1) @@ -387,7 +345,7 @@ Signed-off-by: Felix Fietkau void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, const int offset) { -@@ -587,6 +681,7 @@ int ieee80211_do_open(struct wireless_de +@@ -587,6 +667,7 @@ int ieee80211_do_open(struct wireless_de if (rtnl_dereference(sdata->bss->beacon)) { ieee80211_vif_vlan_copy_chanctx(sdata); netif_carrier_on(dev); @@ -395,7 +353,7 @@ Signed-off-by: Felix Fietkau } else { netif_carrier_off(dev); } -@@ -616,6 +711,7 @@ int ieee80211_do_open(struct wireless_de +@@ -616,6 +697,7 @@ int ieee80211_do_open(struct wireless_de ieee80211_adjust_monitor_flags(sdata, 1); ieee80211_configure_filter(local); @@ -403,7 +361,7 @@ Signed-off-by: Felix Fietkau mutex_lock(&local->mtx); ieee80211_recalc_idle(local); mutex_unlock(&local->mtx); -@@ -625,10 +721,13 @@ int ieee80211_do_open(struct wireless_de +@@ -625,10 +707,13 @@ int ieee80211_do_open(struct wireless_de default: if (coming_up) { ieee80211_del_virtual_monitor(local); @@ -417,7 +375,7 @@ Signed-off-by: Felix Fietkau res = ieee80211_check_queues(sdata, ieee80211_vif_type_p2p(&sdata->vif)); if (res) -@@ -1286,61 +1385,6 @@ static const struct net_device_ops ieee8 +@@ -1286,61 +1371,6 @@ static const struct net_device_ops ieee8 }; @@ -479,7 +437,7 @@ Signed-off-by: Felix Fietkau static void ieee80211_if_free(struct net_device *dev) { free_percpu(netdev_tstats(dev)); -@@ -1371,6 +1415,51 @@ static void ieee80211_if_setup_no_queue( +@@ -1371,6 +1401,32 @@ static void ieee80211_if_setup_no_queue( #endif } @@ -487,7 +445,6 @@ Signed-off-by: Felix Fietkau +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_sub_if_data *bss = sdata; -+ struct ieee80211_key *key; + bool enabled; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { @@ -506,24 +463,6 @@ Signed-off-by: Felix Fietkau + !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) + enabled = false; + -+ /* -+ * Encapsulation offload cannot be used with software crypto, and a per-VLAN -+ * key may have been set -+ */ -+ if (enabled && sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { -+ mutex_lock(&local->key_mtx); -+ list_for_each_entry(key, &sdata->key_list, list) { -+ if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC || -+ key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || -+ key->conf.cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || -+ key->conf.cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) -+ continue; -+ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) -+ enabled = false; -+ } -+ mutex_unlock(&local->key_mtx); -+ } -+ + sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : + &ieee80211_dataif_ops; +} @@ -531,7 +470,7 @@ Signed-off-by: Felix Fietkau static void ieee80211_iface_work(struct work_struct *work) { struct ieee80211_sub_if_data *sdata = -@@ -1553,7 +1642,6 @@ static void ieee80211_setup_sdata(struct +@@ -1553,7 +1609,6 @@ static void ieee80211_setup_sdata(struct sdata->vif.bss_conf.txpower = INT_MIN; /* unset */ sdata->noack_map = 0; @@ -539,7 +478,7 @@ Signed-off-by: Felix Fietkau /* only monitor/p2p-device differ */ if (sdata->dev) { -@@ -1688,6 +1776,7 @@ static int ieee80211_runtime_change_ifty +@@ -1688,6 +1743,7 @@ static int ieee80211_runtime_change_ifty ieee80211_teardown_sdata(sdata); @@ -547,7 +486,7 @@ Signed-off-by: Felix Fietkau ret = drv_change_interface(local, sdata, internal_type, p2p); if (ret) type = ieee80211_vif_type_p2p(&sdata->vif); -@@ -1700,6 +1789,7 @@ static int ieee80211_runtime_change_ifty +@@ -1700,6 +1756,7 @@ static int ieee80211_runtime_change_ifty ieee80211_check_queues(sdata, type); ieee80211_setup_sdata(sdata, type); @@ -586,40 +525,6 @@ Signed-off-by: Felix Fietkau case WLAN_CIPHER_SUITE_AES_CMAC: case WLAN_CIPHER_SUITE_BIP_CMAC_256: case WLAN_CIPHER_SUITE_BIP_GMAC_128: -@@ -824,6 +809,7 @@ int ieee80211_key_link(struct ieee80211_ - */ - bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; - int ret = -EOPNOTSUPP; -+ bool recalc_offload = false; - - mutex_lock(&sdata->local->key_mtx); - -@@ -864,11 +850,15 @@ int ieee80211_key_link(struct ieee80211_ - key->local = sdata->local; - key->sdata = sdata; - key->sta = sta; -+ recalc_offload = !old_key && key->conf.cipher == WLAN_CIPHER_SUITE_TKIP; - - increment_tailroom_need_count(sdata); - - ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key); - -+ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) -+ recalc_offload = true; -+ - if (!ret) { - ieee80211_debugfs_key_add(key); - ieee80211_key_destroy(old_key, delay_tailroom); -@@ -879,6 +869,9 @@ int ieee80211_key_link(struct ieee80211_ - out: - mutex_unlock(&sdata->local->key_mtx); - -+ if (recalc_offload) -+ ieee80211_recalc_offload(sdata->local); -+ - return ret; - } - --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -2733,6 +2733,12 @@ TRACE_EVENT(drv_get_ftm_responder_stats, @@ -637,15 +542,72 @@ Signed-off-by: Felix Fietkau #undef TRACE_INCLUDE_PATH --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4264,11 +4264,6 @@ netdev_tx_t ieee80211_subif_start_xmit_8 - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct sta_info *sta; +@@ -4181,11 +4181,10 @@ static bool ieee80211_tx_8023(struct iee + static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, + struct net_device *dev, struct sta_info *sta, +- struct sk_buff *skb) ++ struct ieee80211_key *key, struct sk_buff *skb) + { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_local *local = sdata->local; +- struct ieee80211_key *key; + struct tid_ampdu_tx *tid_tx; + u8 tid; + +@@ -4234,7 +4233,6 @@ static void ieee80211_8023_xmit(struct i + info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP; + info->control.vif = &sdata->vif; + +- key = rcu_dereference(sta->ptk[sta->ptk_idx]); + if (key) + info->control.hw_key = &key->conf; + +@@ -4251,12 +4249,9 @@ netdev_tx_t ieee80211_subif_start_xmit_8 + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ethhdr *ehdr = (struct ethhdr *)skb->data; ++ struct ieee80211_key *key; + struct sta_info *sta; +- - if (WARN_ON(!sdata->hw_80211_encap)) { - kfree_skb(skb); - return NETDEV_TX_OK; - } -- ++ bool offload = true; + if (unlikely(skb->len < ETH_HLEN)) { kfree_skb(skb); - return NETDEV_TX_OK; +@@ -4265,15 +4260,26 @@ netdev_tx_t ieee80211_subif_start_xmit_8 + + rcu_read_lock(); + +- if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) ++ if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { + kfree_skb(skb); +- else if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded || +- !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || +- sdata->control_port_protocol == ehdr->h_proto)) +- ieee80211_subif_start_xmit(skb, dev); ++ goto out; ++ } ++ ++ if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded || ++ !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || ++ sdata->control_port_protocol == ehdr->h_proto)) ++ offload = false; ++ else if ((key = rcu_dereference(sta->ptk[sta->ptk_idx])) && ++ (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) || ++ key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)) ++ offload = false; ++ ++ if (offload) ++ ieee80211_8023_xmit(sdata, dev, sta, key, skb); + else +- ieee80211_8023_xmit(sdata, dev, sta, skb); ++ ieee80211_subif_start_xmit(skb, dev); + ++out: + rcu_read_unlock(); + + return NETDEV_TX_OK; diff --git a/package/kernel/mac80211/patches/subsys/315-mac80211-reduce-duplication-in-tx-status-functions.patch b/package/kernel/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/315-mac80211-reduce-duplication-in-tx-status-functions.patch rename to package/kernel/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch diff --git a/package/kernel/mac80211/patches/subsys/316-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch b/package/kernel/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/316-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch rename to package/kernel/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch diff --git a/package/kernel/mac80211/patches/subsys/317-mac80211-optimize-station-connection-monitor.patch b/package/kernel/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/317-mac80211-optimize-station-connection-monitor.patch rename to package/kernel/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch diff --git a/package/kernel/mac80211/patches/subsys/318-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch b/package/kernel/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch similarity index 97% rename from package/kernel/mac80211/patches/subsys/318-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch rename to package/kernel/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch index 85287a6ef1..b9069ef9b8 100644 --- a/package/kernel/mac80211/patches/subsys/318-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch +++ b/package/kernel/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch @@ -198,7 +198,7 @@ Signed-off-by: Felix Fietkau goto encap_out; if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) { -@@ -4247,7 +4247,7 @@ static void ieee80211_8023_xmit(struct i +@@ -4230,7 +4230,7 @@ static void ieee80211_8023_xmit(struct i sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); @@ -206,8 +206,8 @@ Signed-off-by: Felix Fietkau + info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; info->control.vif = &sdata->vif; - ieee80211_tx_8023(sdata, skb, skb->len, sta, false); -@@ -4351,7 +4351,7 @@ static bool ieee80211_tx_pending_skb(str + if (key) +@@ -4355,7 +4355,7 @@ static bool ieee80211_tx_pending_skb(str sdata = vif_to_sdata(info->control.vif); @@ -216,7 +216,7 @@ Signed-off-by: Felix Fietkau chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (unlikely(!chanctx_conf)) { dev_kfree_skb(skb); -@@ -4359,7 +4359,7 @@ static bool ieee80211_tx_pending_skb(str +@@ -4363,7 +4363,7 @@ static bool ieee80211_tx_pending_skb(str } info->band = chanctx_conf->def.chan->band; result = ieee80211_tx(sdata, NULL, skb, true, 0); diff --git a/package/kernel/mac80211/patches/subsys/319-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch b/package/kernel/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/319-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch rename to package/kernel/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch diff --git a/package/kernel/mac80211/patches/subsys/322-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch b/package/kernel/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/322-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch rename to package/kernel/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch diff --git a/package/kernel/mac80211/patches/subsys/323-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch b/package/kernel/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch similarity index 98% rename from package/kernel/mac80211/patches/subsys/323-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch rename to package/kernel/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch index c0f2b7b10a..e8b29bb4c5 100644 --- a/package/kernel/mac80211/patches/subsys/323-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch +++ b/package/kernel/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch @@ -1,7 +1,7 @@ From: Felix Fietkau Date: Fri, 21 Aug 2020 05:49:07 +0200 -Subject: [PATCH] mac80211: extend ieee80211_tx_status_ext to support bulk - free +Subject: [PATCH] mac80211: extend ieee80211_tx_status_ext to support + bulk free Store processed skbs ready to be freed in a list so the driver bulk free them diff --git a/package/kernel/mac80211/patches/subsys/324-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch b/package/kernel/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch similarity index 97% rename from package/kernel/mac80211/patches/subsys/324-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch rename to package/kernel/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch index abfb5b76d0..5ad5ac6a78 100644 --- a/package/kernel/mac80211/patches/subsys/324-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch +++ b/package/kernel/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau /** --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1698,6 +1698,7 @@ static int ieee80211_change_station(stru +@@ -1693,6 +1693,7 @@ static int ieee80211_change_station(stru rcu_assign_pointer(vlansdata->u.vlan.sta, sta); __ieee80211_check_fast_rx_iface(vlansdata); diff --git a/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch b/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch new file mode 100644 index 0000000000..a3d600152c --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch @@ -0,0 +1,1110 @@ +From: Felix Fietkau +Date: Tue, 8 Sep 2020 12:16:26 +0200 +Subject: [PATCH] mac80211: reorganize code to remove a forward + declaration + +Remove the newly added ieee80211_set_vif_encap_ops declaration. +No further code changes + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -43,7 +43,6 @@ + */ + + static void ieee80211_iface_work(struct work_struct *work); +-static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata); + + bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) + { +@@ -349,6 +348,511 @@ static int ieee80211_check_queues(struct + return 0; + } + ++static int ieee80211_open(struct net_device *dev) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ int err; ++ ++ /* fail early if user set an invalid address */ ++ if (!is_valid_ether_addr(dev->dev_addr)) ++ return -EADDRNOTAVAIL; ++ ++ err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); ++ if (err) ++ return err; ++ ++ return ieee80211_do_open(&sdata->wdev, true); ++} ++ ++static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ++ bool going_down) ++{ ++ struct ieee80211_local *local = sdata->local; ++ unsigned long flags; ++ struct sk_buff *skb, *tmp; ++ u32 hw_reconf_flags = 0; ++ int i, flushed; ++ struct ps_data *ps; ++ struct cfg80211_chan_def chandef; ++ bool cancel_scan; ++ struct cfg80211_nan_func *func; ++ ++ clear_bit(SDATA_STATE_RUNNING, &sdata->state); ++ ++ cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; ++ if (cancel_scan) ++ ieee80211_scan_cancel(local); ++ ++ /* ++ * Stop TX on this interface first. ++ */ ++ if (sdata->dev) ++ netif_tx_stop_all_queues(sdata->dev); ++ ++ ieee80211_roc_purge(local, sdata); ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_STATION: ++ ieee80211_mgd_stop(sdata); ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ ieee80211_ibss_stop(sdata); ++ break; ++ case NL80211_IFTYPE_MONITOR: ++ if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) ++ break; ++ list_del_rcu(&sdata->u.mntr.list); ++ break; ++ default: ++ break; ++ } ++ ++ /* ++ * Remove all stations associated with this interface. ++ * ++ * This must be done before calling ops->remove_interface() ++ * because otherwise we can later invoke ops->sta_notify() ++ * whenever the STAs are removed, and that invalidates driver ++ * assumptions about always getting a vif pointer that is valid ++ * (because if we remove a STA after ops->remove_interface() ++ * the driver will have removed the vif info already!) ++ * ++ * In WDS mode a station must exist here and be flushed, for ++ * AP_VLANs stations may exist since there's nothing else that ++ * would have removed them, but in other modes there shouldn't ++ * be any stations. ++ */ ++ flushed = sta_info_flush(sdata); ++ WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && ++ ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || ++ (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); ++ ++ /* don't count this interface for allmulti while it is down */ ++ if (sdata->flags & IEEE80211_SDATA_ALLMULTI) ++ atomic_dec(&local->iff_allmultis); ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP) { ++ local->fif_pspoll--; ++ local->fif_probe_req--; ++ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { ++ local->fif_probe_req--; ++ } ++ ++ if (sdata->dev) { ++ netif_addr_lock_bh(sdata->dev); ++ spin_lock_bh(&local->filter_lock); ++ __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, ++ sdata->dev->addr_len); ++ spin_unlock_bh(&local->filter_lock); ++ netif_addr_unlock_bh(sdata->dev); ++ } ++ ++ del_timer_sync(&local->dynamic_ps_timer); ++ cancel_work_sync(&local->dynamic_ps_enable_work); ++ ++ cancel_work_sync(&sdata->recalc_smps); ++ sdata_lock(sdata); ++ mutex_lock(&local->mtx); ++ sdata->vif.csa_active = false; ++ if (sdata->vif.type == NL80211_IFTYPE_STATION) ++ sdata->u.mgd.csa_waiting_bcn = false; ++ if (sdata->csa_block_tx) { ++ ieee80211_wake_vif_queues(local, sdata, ++ IEEE80211_QUEUE_STOP_REASON_CSA); ++ sdata->csa_block_tx = false; ++ } ++ mutex_unlock(&local->mtx); ++ sdata_unlock(sdata); ++ ++ cancel_work_sync(&sdata->csa_finalize_work); ++ ++ cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); ++ ++ if (sdata->wdev.cac_started) { ++ chandef = sdata->vif.bss_conf.chandef; ++ WARN_ON(local->suspended); ++ mutex_lock(&local->mtx); ++ ieee80211_vif_release_channel(sdata); ++ mutex_unlock(&local->mtx); ++ cfg80211_cac_event(sdata->dev, &chandef, ++ NL80211_RADAR_CAC_ABORTED, ++ GFP_KERNEL); ++ } ++ ++ /* APs need special treatment */ ++ if (sdata->vif.type == NL80211_IFTYPE_AP) { ++ struct ieee80211_sub_if_data *vlan, *tmpsdata; ++ ++ /* down all dependent devices, that is VLANs */ ++ list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, ++ u.vlan.list) ++ dev_close(vlan->dev); ++ WARN_ON(!list_empty(&sdata->u.ap.vlans)); ++ } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { ++ /* remove all packets in parent bc_buf pointing to this dev */ ++ ps = &sdata->bss->ps; ++ ++ spin_lock_irqsave(&ps->bc_buf.lock, flags); ++ skb_queue_walk_safe(&ps->bc_buf, skb, tmp) { ++ if (skb->dev == sdata->dev) { ++ __skb_unlink(skb, &ps->bc_buf); ++ local->total_ps_buffered--; ++ ieee80211_free_txskb(&local->hw, skb); ++ } ++ } ++ spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ } ++ ++ if (going_down) ++ local->open_count--; ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ mutex_lock(&local->mtx); ++ list_del(&sdata->u.vlan.list); ++ mutex_unlock(&local->mtx); ++ RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); ++ /* see comment in the default case below */ ++ ieee80211_free_keys(sdata, true); ++ /* no need to tell driver */ ++ break; ++ case NL80211_IFTYPE_MONITOR: ++ if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { ++ local->cooked_mntrs--; ++ break; ++ } ++ ++ local->monitors--; ++ if (local->monitors == 0) { ++ local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; ++ hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; ++ } ++ ++ ieee80211_adjust_monitor_flags(sdata, -1); ++ break; ++ case NL80211_IFTYPE_NAN: ++ /* clean all the functions */ ++ spin_lock_bh(&sdata->u.nan.func_lock); ++ ++ idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) { ++ idr_remove(&sdata->u.nan.function_inst_ids, i); ++ cfg80211_free_nan_func(func); ++ } ++ idr_destroy(&sdata->u.nan.function_inst_ids); ++ ++ spin_unlock_bh(&sdata->u.nan.func_lock); ++ break; ++ case NL80211_IFTYPE_P2P_DEVICE: ++ /* relies on synchronize_rcu() below */ ++ RCU_INIT_POINTER(local->p2p_sdata, NULL); ++ /* fall through */ ++ default: ++ cancel_work_sync(&sdata->work); ++ /* ++ * When we get here, the interface is marked down. ++ * Free the remaining keys, if there are any ++ * (which can happen in AP mode if userspace sets ++ * keys before the interface is operating, and maybe ++ * also in WDS mode) ++ * ++ * Force the key freeing to always synchronize_net() ++ * to wait for the RX path in case it is using this ++ * interface enqueuing frames at this very time on ++ * another CPU. ++ */ ++ ieee80211_free_keys(sdata, true); ++ skb_queue_purge(&sdata->skb_queue); ++ } ++ ++ spin_lock_irqsave(&local->queue_stop_reason_lock, flags); ++ for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { ++ skb_queue_walk_safe(&local->pending[i], skb, tmp) { ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ if (info->control.vif == &sdata->vif) { ++ __skb_unlink(skb, &local->pending[i]); ++ ieee80211_free_txskb(&local->hw, skb); ++ } ++ } ++ } ++ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ ieee80211_txq_remove_vlan(local, sdata); ++ ++ sdata->bss = NULL; ++ ++ if (local->open_count == 0) ++ ieee80211_clear_tx_pending(local); ++ ++ sdata->vif.bss_conf.beacon_int = 0; ++ ++ /* ++ * If the interface goes down while suspended, presumably because ++ * the device was unplugged and that happens before our resume, ++ * then the driver is already unconfigured and the remainder of ++ * this function isn't needed. ++ * XXX: what about WoWLAN? If the device has software state, e.g. ++ * memory allocated, it might expect teardown commands from ++ * mac80211 here? ++ */ ++ if (local->suspended) { ++ WARN_ON(local->wowlan); ++ WARN_ON(rtnl_dereference(local->monitor_sdata)); ++ return; ++ } ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ break; ++ case NL80211_IFTYPE_MONITOR: ++ if (local->monitors == 0) ++ ieee80211_del_virtual_monitor(local); ++ ++ mutex_lock(&local->mtx); ++ ieee80211_recalc_idle(local); ++ mutex_unlock(&local->mtx); ++ ++ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) ++ break; ++ ++ /* fall through */ ++ default: ++ if (going_down) ++ drv_remove_interface(local, sdata); ++ } ++ ++ ieee80211_recalc_ps(local); ++ ++ if (cancel_scan) ++ flush_delayed_work(&local->scan_work); ++ ++ if (local->open_count == 0) { ++ ieee80211_stop_device(local); ++ ++ /* no reconfiguring after stop! */ ++ return; ++ } ++ ++ /* do after stop to avoid reconfiguring when we stop anyway */ ++ ieee80211_configure_filter(local); ++ ieee80211_hw_config(local, hw_reconf_flags); ++ ++ if (local->monitors == local->open_count) ++ ieee80211_add_virtual_monitor(local); ++} ++ ++static int ieee80211_stop(struct net_device *dev) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ++ ieee80211_do_stop(sdata, true); ++ ++ return 0; ++} ++ ++static void ieee80211_set_multicast_list(struct net_device *dev) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; ++ int allmulti, sdata_allmulti; ++ ++ allmulti = !!(dev->flags & IFF_ALLMULTI); ++ sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); ++ ++ if (allmulti != sdata_allmulti) { ++ if (dev->flags & IFF_ALLMULTI) ++ atomic_inc(&local->iff_allmultis); ++ else ++ atomic_dec(&local->iff_allmultis); ++ sdata->flags ^= IEEE80211_SDATA_ALLMULTI; ++ } ++ ++ spin_lock_bh(&local->filter_lock); ++ __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); ++ spin_unlock_bh(&local->filter_lock); ++ ieee80211_queue_work(&local->hw, &local->reconfig_filter); ++} ++ ++/* ++ * Called when the netdev is removed or, by the code below, before ++ * the interface type changes. ++ */ ++static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) ++{ ++ int i; ++ ++ /* free extra data */ ++ ieee80211_free_keys(sdata, false); ++ ++ ieee80211_debugfs_remove_netdev(sdata); ++ ++ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) ++ __skb_queue_purge(&sdata->fragments[i].skb_list); ++ sdata->fragment_next = 0; ++ ++ if (ieee80211_vif_is_mesh(&sdata->vif)) ++ ieee80211_mesh_teardown_sdata(sdata); ++} ++ ++static void ieee80211_uninit(struct net_device *dev) ++{ ++ ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); ++} ++ ++#if LINUX_VERSION_IS_GEQ(5,2,0) ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev) ++#elif LINUX_VERSION_IS_GEQ(4,19,0) ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev, ++ select_queue_fallback_t fallback) ++#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ ++ (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv, ++ select_queue_fallback_t fallback) ++#elif LINUX_VERSION_IS_GEQ(3,13,0) ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv) ++#else ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb) ++#endif ++{ ++ return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); ++} ++ ++static void ++ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) ++{ ++ int i; ++ ++ for_each_possible_cpu(i) { ++ const struct pcpu_sw_netstats *tstats; ++ u64 rx_packets, rx_bytes, tx_packets, tx_bytes; ++ unsigned int start; ++ ++ tstats = per_cpu_ptr(netdev_tstats(dev), i); ++ ++ do { ++ start = u64_stats_fetch_begin_irq(&tstats->syncp); ++ rx_packets = tstats->rx_packets; ++ tx_packets = tstats->tx_packets; ++ rx_bytes = tstats->rx_bytes; ++ tx_bytes = tstats->tx_bytes; ++ } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); ++ ++ stats->rx_packets += rx_packets; ++ stats->tx_packets += tx_packets; ++ stats->rx_bytes += rx_bytes; ++ stats->tx_bytes += tx_bytes; ++ } ++} ++#if LINUX_VERSION_IS_LESS(4,11,0) ++/* Just declare it here to keep sparse happy */ ++struct rtnl_link_stats64 *bp_ieee80211_get_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *stats); ++struct rtnl_link_stats64 * ++bp_ieee80211_get_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *stats){ ++ ieee80211_get_stats64(dev, stats); ++ return stats; ++} ++#endif ++ ++static const struct net_device_ops ieee80211_dataif_ops = { ++ .ndo_open = ieee80211_open, ++ .ndo_stop = ieee80211_stop, ++ .ndo_uninit = ieee80211_uninit, ++ .ndo_start_xmit = ieee80211_subif_start_xmit, ++ .ndo_set_rx_mode = ieee80211_set_multicast_list, ++ .ndo_set_mac_address = ieee80211_change_mac, ++ .ndo_select_queue = ieee80211_netdev_select_queue, ++#if LINUX_VERSION_IS_GEQ(4,11,0) ++ .ndo_get_stats64 = ieee80211_get_stats64, ++#else ++ .ndo_get_stats64 = bp_ieee80211_get_stats64, ++#endif ++ ++}; ++ ++#if LINUX_VERSION_IS_GEQ(5,2,0) ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev) ++#elif LINUX_VERSION_IS_GEQ(4,19,0) ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev, ++ select_queue_fallback_t fallback) ++#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ ++ (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv, ++ select_queue_fallback_t fallback) ++#elif LINUX_VERSION_IS_GEQ(3,13,0) ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv) ++#else ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb) ++#endif ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_hdr *hdr; ++ struct ieee80211_radiotap_header *rtap = (void *)skb->data; ++ ++ if (local->hw.queues < IEEE80211_NUM_ACS) ++ return 0; ++ ++ if (skb->len < 4 || ++ skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */) ++ return 0; /* doesn't matter, frame will be dropped */ ++ ++ hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); ++ ++ return ieee80211_select_queue_80211(sdata, skb, hdr); ++} ++ ++static const struct net_device_ops ieee80211_monitorif_ops = { ++ .ndo_open = ieee80211_open, ++ .ndo_stop = ieee80211_stop, ++ .ndo_uninit = ieee80211_uninit, ++ .ndo_start_xmit = ieee80211_monitor_start_xmit, ++ .ndo_set_rx_mode = ieee80211_set_multicast_list, ++ .ndo_set_mac_address = ieee80211_change_mac, ++ .ndo_select_queue = ieee80211_monitor_select_queue, ++#if LINUX_VERSION_IS_GEQ(4,11,0) ++ .ndo_get_stats64 = ieee80211_get_stats64, ++#else ++ .ndo_get_stats64 = bp_ieee80211_get_stats64, ++#endif ++ ++}; ++ ++static const struct net_device_ops ieee80211_dataif_8023_ops = { ++ .ndo_open = ieee80211_open, ++ .ndo_stop = ieee80211_stop, ++ .ndo_uninit = ieee80211_uninit, ++ .ndo_start_xmit = ieee80211_subif_start_xmit_8023, ++ .ndo_set_rx_mode = ieee80211_set_multicast_list, ++ .ndo_set_mac_address = ieee80211_change_mac, ++ .ndo_select_queue = ieee80211_netdev_select_queue, ++#if LINUX_VERSION_IS_GEQ(4,11,0) ++ .ndo_get_stats64 = ieee80211_get_stats64, ++#else ++ .ndo_get_stats64 = bp_ieee80211_get_stats64, ++#endif ++ ++}; ++ + static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype) + { + switch (iftype) { +@@ -389,6 +893,31 @@ static bool ieee80211_set_sdata_offload_ + return true; + } + ++static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_sub_if_data *bss = sdata; ++ bool enabled; ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { ++ if (!sdata->bss) ++ return; ++ ++ bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); ++ } ++ ++ if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || ++ !ieee80211_iftype_supports_encap_offload(bss->vif.type)) ++ return; ++ ++ enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ if (sdata->wdev.use_4addr && ++ !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) ++ enabled = false; ++ ++ sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : ++ &ieee80211_dataif_ops; ++} + + static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata) + { +@@ -866,511 +1395,6 @@ int ieee80211_do_open(struct wireless_de + return res; + } + +-static int ieee80211_open(struct net_device *dev) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- int err; +- +- /* fail early if user set an invalid address */ +- if (!is_valid_ether_addr(dev->dev_addr)) +- return -EADDRNOTAVAIL; +- +- err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); +- if (err) +- return err; +- +- return ieee80211_do_open(&sdata->wdev, true); +-} +- +-static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, +- bool going_down) +-{ +- struct ieee80211_local *local = sdata->local; +- unsigned long flags; +- struct sk_buff *skb, *tmp; +- u32 hw_reconf_flags = 0; +- int i, flushed; +- struct ps_data *ps; +- struct cfg80211_chan_def chandef; +- bool cancel_scan; +- struct cfg80211_nan_func *func; +- +- clear_bit(SDATA_STATE_RUNNING, &sdata->state); +- +- cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; +- if (cancel_scan) +- ieee80211_scan_cancel(local); +- +- /* +- * Stop TX on this interface first. +- */ +- if (sdata->dev) +- netif_tx_stop_all_queues(sdata->dev); +- +- ieee80211_roc_purge(local, sdata); +- +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_STATION: +- ieee80211_mgd_stop(sdata); +- break; +- case NL80211_IFTYPE_ADHOC: +- ieee80211_ibss_stop(sdata); +- break; +- case NL80211_IFTYPE_MONITOR: +- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) +- break; +- list_del_rcu(&sdata->u.mntr.list); +- break; +- default: +- break; +- } +- +- /* +- * Remove all stations associated with this interface. +- * +- * This must be done before calling ops->remove_interface() +- * because otherwise we can later invoke ops->sta_notify() +- * whenever the STAs are removed, and that invalidates driver +- * assumptions about always getting a vif pointer that is valid +- * (because if we remove a STA after ops->remove_interface() +- * the driver will have removed the vif info already!) +- * +- * In WDS mode a station must exist here and be flushed, for +- * AP_VLANs stations may exist since there's nothing else that +- * would have removed them, but in other modes there shouldn't +- * be any stations. +- */ +- flushed = sta_info_flush(sdata); +- WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && +- ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || +- (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); +- +- /* don't count this interface for allmulti while it is down */ +- if (sdata->flags & IEEE80211_SDATA_ALLMULTI) +- atomic_dec(&local->iff_allmultis); +- +- if (sdata->vif.type == NL80211_IFTYPE_AP) { +- local->fif_pspoll--; +- local->fif_probe_req--; +- } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { +- local->fif_probe_req--; +- } +- +- if (sdata->dev) { +- netif_addr_lock_bh(sdata->dev); +- spin_lock_bh(&local->filter_lock); +- __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, +- sdata->dev->addr_len); +- spin_unlock_bh(&local->filter_lock); +- netif_addr_unlock_bh(sdata->dev); +- } +- +- del_timer_sync(&local->dynamic_ps_timer); +- cancel_work_sync(&local->dynamic_ps_enable_work); +- +- cancel_work_sync(&sdata->recalc_smps); +- sdata_lock(sdata); +- mutex_lock(&local->mtx); +- sdata->vif.csa_active = false; +- if (sdata->vif.type == NL80211_IFTYPE_STATION) +- sdata->u.mgd.csa_waiting_bcn = false; +- if (sdata->csa_block_tx) { +- ieee80211_wake_vif_queues(local, sdata, +- IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_block_tx = false; +- } +- mutex_unlock(&local->mtx); +- sdata_unlock(sdata); +- +- cancel_work_sync(&sdata->csa_finalize_work); +- +- cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); +- +- if (sdata->wdev.cac_started) { +- chandef = sdata->vif.bss_conf.chandef; +- WARN_ON(local->suspended); +- mutex_lock(&local->mtx); +- ieee80211_vif_release_channel(sdata); +- mutex_unlock(&local->mtx); +- cfg80211_cac_event(sdata->dev, &chandef, +- NL80211_RADAR_CAC_ABORTED, +- GFP_KERNEL); +- } +- +- /* APs need special treatment */ +- if (sdata->vif.type == NL80211_IFTYPE_AP) { +- struct ieee80211_sub_if_data *vlan, *tmpsdata; +- +- /* down all dependent devices, that is VLANs */ +- list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, +- u.vlan.list) +- dev_close(vlan->dev); +- WARN_ON(!list_empty(&sdata->u.ap.vlans)); +- } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +- /* remove all packets in parent bc_buf pointing to this dev */ +- ps = &sdata->bss->ps; +- +- spin_lock_irqsave(&ps->bc_buf.lock, flags); +- skb_queue_walk_safe(&ps->bc_buf, skb, tmp) { +- if (skb->dev == sdata->dev) { +- __skb_unlink(skb, &ps->bc_buf); +- local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); +- } +- } +- spin_unlock_irqrestore(&ps->bc_buf.lock, flags); +- } +- +- if (going_down) +- local->open_count--; +- +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP_VLAN: +- mutex_lock(&local->mtx); +- list_del(&sdata->u.vlan.list); +- mutex_unlock(&local->mtx); +- RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); +- /* see comment in the default case below */ +- ieee80211_free_keys(sdata, true); +- /* no need to tell driver */ +- break; +- case NL80211_IFTYPE_MONITOR: +- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { +- local->cooked_mntrs--; +- break; +- } +- +- local->monitors--; +- if (local->monitors == 0) { +- local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; +- hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; +- } +- +- ieee80211_adjust_monitor_flags(sdata, -1); +- break; +- case NL80211_IFTYPE_NAN: +- /* clean all the functions */ +- spin_lock_bh(&sdata->u.nan.func_lock); +- +- idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) { +- idr_remove(&sdata->u.nan.function_inst_ids, i); +- cfg80211_free_nan_func(func); +- } +- idr_destroy(&sdata->u.nan.function_inst_ids); +- +- spin_unlock_bh(&sdata->u.nan.func_lock); +- break; +- case NL80211_IFTYPE_P2P_DEVICE: +- /* relies on synchronize_rcu() below */ +- RCU_INIT_POINTER(local->p2p_sdata, NULL); +- /* fall through */ +- default: +- cancel_work_sync(&sdata->work); +- /* +- * When we get here, the interface is marked down. +- * Free the remaining keys, if there are any +- * (which can happen in AP mode if userspace sets +- * keys before the interface is operating, and maybe +- * also in WDS mode) +- * +- * Force the key freeing to always synchronize_net() +- * to wait for the RX path in case it is using this +- * interface enqueuing frames at this very time on +- * another CPU. +- */ +- ieee80211_free_keys(sdata, true); +- skb_queue_purge(&sdata->skb_queue); +- } +- +- spin_lock_irqsave(&local->queue_stop_reason_lock, flags); +- for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { +- skb_queue_walk_safe(&local->pending[i], skb, tmp) { +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +- if (info->control.vif == &sdata->vif) { +- __skb_unlink(skb, &local->pending[i]); +- ieee80211_free_txskb(&local->hw, skb); +- } +- } +- } +- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +- +- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +- ieee80211_txq_remove_vlan(local, sdata); +- +- sdata->bss = NULL; +- +- if (local->open_count == 0) +- ieee80211_clear_tx_pending(local); +- +- sdata->vif.bss_conf.beacon_int = 0; +- +- /* +- * If the interface goes down while suspended, presumably because +- * the device was unplugged and that happens before our resume, +- * then the driver is already unconfigured and the remainder of +- * this function isn't needed. +- * XXX: what about WoWLAN? If the device has software state, e.g. +- * memory allocated, it might expect teardown commands from +- * mac80211 here? +- */ +- if (local->suspended) { +- WARN_ON(local->wowlan); +- WARN_ON(rtnl_dereference(local->monitor_sdata)); +- return; +- } +- +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP_VLAN: +- break; +- case NL80211_IFTYPE_MONITOR: +- if (local->monitors == 0) +- ieee80211_del_virtual_monitor(local); +- +- mutex_lock(&local->mtx); +- ieee80211_recalc_idle(local); +- mutex_unlock(&local->mtx); +- +- if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) +- break; +- +- /* fall through */ +- default: +- if (going_down) +- drv_remove_interface(local, sdata); +- } +- +- ieee80211_recalc_ps(local); +- +- if (cancel_scan) +- flush_delayed_work(&local->scan_work); +- +- if (local->open_count == 0) { +- ieee80211_stop_device(local); +- +- /* no reconfiguring after stop! */ +- return; +- } +- +- /* do after stop to avoid reconfiguring when we stop anyway */ +- ieee80211_configure_filter(local); +- ieee80211_hw_config(local, hw_reconf_flags); +- +- if (local->monitors == local->open_count) +- ieee80211_add_virtual_monitor(local); +-} +- +-static int ieee80211_stop(struct net_device *dev) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- +- ieee80211_do_stop(sdata, true); +- +- return 0; +-} +- +-static void ieee80211_set_multicast_list(struct net_device *dev) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- struct ieee80211_local *local = sdata->local; +- int allmulti, sdata_allmulti; +- +- allmulti = !!(dev->flags & IFF_ALLMULTI); +- sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); +- +- if (allmulti != sdata_allmulti) { +- if (dev->flags & IFF_ALLMULTI) +- atomic_inc(&local->iff_allmultis); +- else +- atomic_dec(&local->iff_allmultis); +- sdata->flags ^= IEEE80211_SDATA_ALLMULTI; +- } +- +- spin_lock_bh(&local->filter_lock); +- __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); +- spin_unlock_bh(&local->filter_lock); +- ieee80211_queue_work(&local->hw, &local->reconfig_filter); +-} +- +-/* +- * Called when the netdev is removed or, by the code below, before +- * the interface type changes. +- */ +-static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) +-{ +- int i; +- +- /* free extra data */ +- ieee80211_free_keys(sdata, false); +- +- ieee80211_debugfs_remove_netdev(sdata); +- +- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) +- __skb_queue_purge(&sdata->fragments[i].skb_list); +- sdata->fragment_next = 0; +- +- if (ieee80211_vif_is_mesh(&sdata->vif)) +- ieee80211_mesh_teardown_sdata(sdata); +-} +- +-static void ieee80211_uninit(struct net_device *dev) +-{ +- ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); +-} +- +-#if LINUX_VERSION_IS_GEQ(5,2,0) +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev) +-#elif LINUX_VERSION_IS_GEQ(4,19,0) +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev, +- select_queue_fallback_t fallback) +-#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ +- (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- void *accel_priv, +- select_queue_fallback_t fallback) +-#elif LINUX_VERSION_IS_GEQ(3,13,0) +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- void *accel_priv) +-#else +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb) +-#endif +-{ +- return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); +-} +- +-static void +-ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +-{ +- int i; +- +- for_each_possible_cpu(i) { +- const struct pcpu_sw_netstats *tstats; +- u64 rx_packets, rx_bytes, tx_packets, tx_bytes; +- unsigned int start; +- +- tstats = per_cpu_ptr(netdev_tstats(dev), i); +- +- do { +- start = u64_stats_fetch_begin_irq(&tstats->syncp); +- rx_packets = tstats->rx_packets; +- tx_packets = tstats->tx_packets; +- rx_bytes = tstats->rx_bytes; +- tx_bytes = tstats->tx_bytes; +- } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); +- +- stats->rx_packets += rx_packets; +- stats->tx_packets += tx_packets; +- stats->rx_bytes += rx_bytes; +- stats->tx_bytes += tx_bytes; +- } +-} +-#if LINUX_VERSION_IS_LESS(4,11,0) +-/* Just declare it here to keep sparse happy */ +-struct rtnl_link_stats64 *bp_ieee80211_get_stats64(struct net_device *dev, +- struct rtnl_link_stats64 *stats); +-struct rtnl_link_stats64 * +-bp_ieee80211_get_stats64(struct net_device *dev, +- struct rtnl_link_stats64 *stats){ +- ieee80211_get_stats64(dev, stats); +- return stats; +-} +-#endif +- +-static const struct net_device_ops ieee80211_dataif_ops = { +- .ndo_open = ieee80211_open, +- .ndo_stop = ieee80211_stop, +- .ndo_uninit = ieee80211_uninit, +- .ndo_start_xmit = ieee80211_subif_start_xmit, +- .ndo_set_rx_mode = ieee80211_set_multicast_list, +- .ndo_set_mac_address = ieee80211_change_mac, +- .ndo_select_queue = ieee80211_netdev_select_queue, +-#if LINUX_VERSION_IS_GEQ(4,11,0) +- .ndo_get_stats64 = ieee80211_get_stats64, +-#else +- .ndo_get_stats64 = bp_ieee80211_get_stats64, +-#endif +- +-}; +- +-#if LINUX_VERSION_IS_GEQ(5,2,0) +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev) +-#elif LINUX_VERSION_IS_GEQ(4,19,0) +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev, +- select_queue_fallback_t fallback) +-#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ +- (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- void *accel_priv, +- select_queue_fallback_t fallback) +-#elif LINUX_VERSION_IS_GEQ(3,13,0) +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- void *accel_priv) +-#else +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb) +-#endif +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_hdr *hdr; +- struct ieee80211_radiotap_header *rtap = (void *)skb->data; +- +- if (local->hw.queues < IEEE80211_NUM_ACS) +- return 0; +- +- if (skb->len < 4 || +- skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */) +- return 0; /* doesn't matter, frame will be dropped */ +- +- hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); +- +- return ieee80211_select_queue_80211(sdata, skb, hdr); +-} +- +-static const struct net_device_ops ieee80211_monitorif_ops = { +- .ndo_open = ieee80211_open, +- .ndo_stop = ieee80211_stop, +- .ndo_uninit = ieee80211_uninit, +- .ndo_start_xmit = ieee80211_monitor_start_xmit, +- .ndo_set_rx_mode = ieee80211_set_multicast_list, +- .ndo_set_mac_address = ieee80211_change_mac, +- .ndo_select_queue = ieee80211_monitor_select_queue, +-#if LINUX_VERSION_IS_GEQ(4,11,0) +- .ndo_get_stats64 = ieee80211_get_stats64, +-#else +- .ndo_get_stats64 = bp_ieee80211_get_stats64, +-#endif +- +-}; +- +-static const struct net_device_ops ieee80211_dataif_8023_ops = { +- .ndo_open = ieee80211_open, +- .ndo_stop = ieee80211_stop, +- .ndo_uninit = ieee80211_uninit, +- .ndo_start_xmit = ieee80211_subif_start_xmit_8023, +- .ndo_set_rx_mode = ieee80211_set_multicast_list, +- .ndo_set_mac_address = ieee80211_change_mac, +- .ndo_select_queue = ieee80211_netdev_select_queue, +-#if LINUX_VERSION_IS_GEQ(4,11,0) +- .ndo_get_stats64 = ieee80211_get_stats64, +-#else +- .ndo_get_stats64 = bp_ieee80211_get_stats64, +-#endif +- +-}; +- + static void ieee80211_if_free(struct net_device *dev) + { + free_percpu(netdev_tstats(dev)); +@@ -1401,32 +1425,6 @@ static void ieee80211_if_setup_no_queue( + #endif + } + +-static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata) +-{ +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_sub_if_data *bss = sdata; +- bool enabled; +- +- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +- if (!sdata->bss) +- return; +- +- bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); +- } +- +- if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || +- !ieee80211_iftype_supports_encap_offload(bss->vif.type)) +- return; +- +- enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; +- if (sdata->wdev.use_4addr && +- !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) +- enabled = false; +- +- sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : +- &ieee80211_dataif_ops; +-} +- + static void ieee80211_iface_work(struct work_struct *work) + { + struct ieee80211_sub_if_data *sdata = diff --git a/package/kernel/mac80211/patches/subsys/327-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch b/package/kernel/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/327-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch rename to package/kernel/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch diff --git a/package/kernel/mac80211/patches/subsys/328-mac80211-add-AQL-support-for-VHT160-tx-rates.patch b/package/kernel/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch similarity index 100% rename from package/kernel/mac80211/patches/subsys/328-mac80211-add-AQL-support-for-VHT160-tx-rates.patch rename to package/kernel/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch index 1487e10f42..8db3a758a1 100644 --- a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch @@ -18,7 +18,7 @@ const u8 *addr); --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -1519,6 +1519,7 @@ enum ieee80211_smps_mode { +@@ -1521,6 +1521,7 @@ enum ieee80211_smps_mode { * * @power_level: requested transmit power (in dBm), backward compatibility * value only that is set to the minimum of all interfaces @@ -26,7 +26,7 @@ * * @chandef: the channel definition to tune to * @radar_enabled: whether radar detection is enabled -@@ -1539,6 +1540,7 @@ enum ieee80211_smps_mode { +@@ -1541,6 +1542,7 @@ enum ieee80211_smps_mode { struct ieee80211_conf { u32 flags; int power_level, dynamic_ps_timeout; @@ -57,7 +57,7 @@ __NL80211_ATTR_AFTER_LAST, --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2615,6 +2615,19 @@ static int ieee80211_get_tx_power(struct +@@ -2611,6 +2611,19 @@ static int ieee80211_get_tx_power(struct return 0; } @@ -77,7 +77,7 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, const u8 *addr) { -@@ -4045,6 +4058,7 @@ const struct cfg80211_ops mac80211_confi +@@ -4041,6 +4054,7 @@ const struct cfg80211_ops mac80211_confi .set_wiphy_params = ieee80211_set_wiphy_params, .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index c151bd4227..43fd3be65d 100644 --- a/package/network/config/netifd/Makefile +++ b/package/network/config/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2020-06-06 -PKG_SOURCE_VERSION:=51e9fb8151e8f2c16ac1400bf4d64147ee7e8f5a -PKG_MIRROR_HASH:=d89b76cb28a4c15c044f1b11ae8bc3ef7087a49cafe3dfff191163c6641a74b5 +PKG_SOURCE_DATE:=2020-09-08 +PKG_SOURCE_VERSION:=d7b614a86b815da711b5fecb10687297a70d859e +PKG_MIRROR_HASH:=266bab9e9fecb3ad86b4cea3303765c35d8b4db00274565368f69de0fa6c05df PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile index 5e56a43e9a..8f94dce782 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=hostapd -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_SOURCE_URL:=http://w1.fi/hostap.git PKG_SOURCE_PROTO:=git diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index f01e8596ec..2c647d4405 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -1,4 +1,5 @@ . /lib/functions/network.sh +. /lib/functions.sh wpa_supplicant_add_rate() { local var="$1" @@ -70,6 +71,8 @@ hostapd_append_wpa_key_mgmt() { append wpa_key_mgmt "OWE" ;; esac + + [ "$auth_osen" = "1" ] && append wpa_key_mgmt "OSEN" } hostapd_add_log_config() { @@ -258,10 +261,19 @@ hostapd_common_add_bss_config() { config_add_int mcast_rate config_add_array basic_rate config_add_array supported_rates - + config_add_boolean sae_require_mfp - + config_add_string 'owe_transition_bssid:macaddr' 'owe_transition_ssid:string' + + config_add_boolean hs20 disable_dgaf osen + config_add_int anqp_domain_id + config_add_int hs20_deauth_req_timeout + config_add_array hs20_oper_friendly_name + config_add_array osu_provider + config_add_array operator_icon + config_add_array hs20_conn_capab + config_add_string osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp } hostapd_set_vlan_file() { @@ -297,6 +309,66 @@ hostapd_set_psk() { for_each_station hostapd_set_psk_file ${ifname} } +append_hs20_oper_friendly_name() { + append bss_conf "hs20_oper_friendly_name=$1" "$N" +} + +append_osu_provider_service_desc() { + append bss_conf "osu_service_desc=$1" "$N" +} + +append_hs20_icon() { + local width height lang type path + config_get width "$1" width + config_get height "$1" height + config_get lang "$1" lang + config_get type "$1" type + config_get path "$1" path + + append bss_conf "hs20_icon=$width:$height:$lang:$type:$1:$path" "$N" +} + +append_hs20_icons() { + config_load wireless + config_foreach append_hs20_icon hs20-icon +} + +append_operator_icon() { + append bss_conf "operator_icon=$1" "$N" +} + +append_osu_icon() { + append bss_conf "osu_icon=$1" "$N" +} + +append_osu_provider() { + local cfgtype osu_server_uri osu_friendly_name osu_nai osu_nai2 osu_method_list + + config_load wireless + config_get cfgtype "$1" TYPE + [ "$cfgtype" != "osu-provider" ] && return + + append bss_conf "# provider $1" "$N" + config_get osu_server_uri "$1" osu_server_uri + config_get osu_nai "$1" osu_nai + config_get osu_nai2 "$1" osu_nai2 + config_get osu_method_list "$1" osu_method + + append bss_conf "osu_server_uri=$osu_server_uri" "$N" + append bss_conf "osu_nai=$osu_nai" "$N" + append bss_conf "osu_nai2=$osu_nai2" "$N" + append bss_conf "osu_method_list=$osu_method_list" "$N" + + config_list_foreach "$1" osu_service_desc append_osu_provider_service_desc + config_list_foreach "$1" osu_icon append_osu_icon + + append bss_conf "$N" +} + +append_hs20_conn_capab() { + [ -n "$1" ] && append bss_conf "hs20_conn_capab=$1" "$N" +} + hostapd_set_bss_options() { local var="$1" local phy="$2" @@ -690,6 +762,34 @@ hostapd_set_bss_options() { } } + local hs20 disable_dgaf osen anqp_domain_id hs20_deauth_req_timeout \ + osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp + json_get_vars hs20 disable_dgaf osen anqp_domain_id hs20_deauth_req_timeout \ + osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp + + set_default hs20 0 + set_default disable_dgaf $hs20 + set_default osen 0 + set_default anqp_domain_id 0 + set_default hs20_deauth_req_timeout 60 + if [ "$hs20" = "1" ]; then + append bss_conf "hs20=1" "$N" + append_hs20_icons + append bss_conf "disable_dgaf=$disable_dgaf" "$N" + append bss_conf "osen=$osen" "$N" + append bss_conf "anqp_domain_id=$anqp_domain_id" "$N" + append bss_conf "hs20_deauth_req_timeout=$hs20_deauth_req_timeout" "$N" + [ -n "$osu_ssid" ] && append bss_conf "osu_ssid=$osu_ssid" "$N" + [ -n "$hs20_wan_metrics" ] && append bss_conf "hs20_wan_metrics=$hs20_wan_metrics" "$N" + [ -n "$hs20_operating_class" ] && append bss_conf "hs20_operating_class=$hs20_operating_class" "$N" + [ -n "$hs20_t_c_filename" ] && append bss_conf "hs20_t_c_filename=$hs20_t_c_filename" "$N" + [ -n "$hs20_t_c_timestamp" ] && append bss_conf "hs20_t_c_timestamp=$hs20_t_c_timestamp" "$N" + json_for_each_item append_hs20_conn_capab hs20_conn_capab + json_for_each_item append_hs20_oper_friendly_name hs20_oper_friendly_name + json_for_each_item append_osu_provider osu_provider + json_for_each_item append_operator_icon operator_icon + fi + bss_md5sum=$(echo $bss_conf | md5sum | cut -d" " -f1) append bss_conf "config_id=$bss_md5sum" "$N" diff --git a/package/network/services/hostapd/src/src/utils/build_features.h b/package/network/services/hostapd/src/src/utils/build_features.h index 35356b2323..9856756d95 100644 --- a/package/network/services/hostapd/src/src/utils/build_features.h +++ b/package/network/services/hostapd/src/src/utils/build_features.h @@ -46,6 +46,10 @@ static inline int has_feature(const char *feat) #ifdef CONFIG_WEP if (!strcmp(feat, "wep")) return 1; +#endif +#ifdef CONFIG_HS20 + if (!strcmp(feat, "hs20")) + return 1; #endif return 0; } diff --git a/package/network/services/openvpn/Makefile b/package/network/services/openvpn/Makefile index 9482e9ce39..40570fbdb6 100644 --- a/package/network/services/openvpn/Makefile +++ b/package/network/services/openvpn/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openvpn PKG_VERSION:=2.4.9 -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_SOURCE_URL:=\ https://build.openvpn.net/downloads/releases/ \ diff --git a/package/network/services/openvpn/files/openvpn.init b/package/network/services/openvpn/files/openvpn.init index a454eb4ba0..487a2269e2 100644 --- a/package/network/services/openvpn/files/openvpn.init +++ b/package/network/services/openvpn/files/openvpn.init @@ -43,7 +43,7 @@ append_params() { IFS="$LIST_SEP" for v in $v; do [ -n "$v" ] && [ "$p" != "push" ] && append_param "$s" "$p" && echo " $v" >> "/var/etc/openvpn-$s.conf" - [ -n "$v" ] && [ "$p" == "push" ] && append_param "$s" "$p" && echo " \"$v\"" >> "/var/etc/openvpn-$s.conf" + [ -n "$v" ] && [ "$p" = "push" ] && append_param "$s" "$p" && echo " \"$v\"" >> "/var/etc/openvpn-$s.conf" done unset IFS done diff --git a/package/network/services/wireguard/Makefile b/package/network/services/wireguard/Makefile index 8c408d06a7..7df219f3f7 100644 --- a/package/network/services/wireguard/Makefile +++ b/package/network/services/wireguard/Makefile @@ -11,12 +11,12 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=wireguard -PKG_VERSION:=1.0.20200729 +PKG_VERSION:=1.0.20200908 PKG_RELEASE:=1 PKG_SOURCE:=wireguard-linux-compat-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-linux-compat/snapshot/ -PKG_HASH:=690c7d9e115e2ff27386811cb495c9784678f717c8d6fc4cc7469dce373f252e +PKG_HASH:=ad33b2d2267a37e0f65c97e65e7d4d926d5aef7d530c251b63fbf919048eead9 PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING diff --git a/package/network/utils/rssileds/Makefile b/package/network/utils/rssileds/Makefile index 892b9f2c51..dc2245db02 100644 --- a/package/network/utils/rssileds/Makefile +++ b/package/network/utils/rssileds/Makefile @@ -18,7 +18,7 @@ define Package/rssileds CATEGORY:=Network TITLE:=RSSI real-time LED indicator DEPENDS:=+libiwinfo +libnl-tiny +libubox +libuci - MAINTAINER:=Daniel Golle + MAINTAINER:=Daniel Golle endef define Package/rssileds/description diff --git a/package/network/utils/wireguard-tools/Makefile b/package/network/utils/wireguard-tools/Makefile index 8cb1e46587..a5264a50b4 100644 --- a/package/network/utils/wireguard-tools/Makefile +++ b/package/network/utils/wireguard-tools/Makefile @@ -11,12 +11,12 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=wireguard-tools -PKG_VERSION:=1.0.20200820 -PKG_RELEASE:=1 +PKG_VERSION:=1.0.20200827 +PKG_RELEASE:=2 PKG_SOURCE:=wireguard-tools-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-tools/snapshot/ -PKG_HASH:=7735a04c68fffb101a10a67e3bd97a171f2b8eb47e9ddce2be68eb6538b013d0 +PKG_HASH:=51bc85e33a5b3cf353786ae64b0f1216d7a871447f058b6137f793eb0f53b7fd PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING diff --git a/target/linux/ath79/config-4.19 b/target/linux/ath79/config-4.19 index eaaedd6c51..3679f0c0c9 100644 --- a/target/linux/ath79/config-4.19 +++ b/target/linux/ath79/config-4.19 @@ -168,6 +168,7 @@ CONFIG_MTD_M25P80=y CONFIG_MTD_PARSER_CYBERTAN=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_ELF_FW=y CONFIG_MTD_SPLIT_LZMA_FW=y CONFIG_MTD_SPLIT_SEAMA_FW=y CONFIG_MTD_SPLIT_TPLINK_FW=y diff --git a/target/linux/ath79/config-5.4 b/target/linux/ath79/config-5.4 index 0f5352a921..25c3a08e69 100644 --- a/target/linux/ath79/config-5.4 +++ b/target/linux/ath79/config-5.4 @@ -175,6 +175,7 @@ CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_PARSER_CYBERTAN=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_ELF_FW=y CONFIG_MTD_SPLIT_LZMA_FW=y CONFIG_MTD_SPLIT_SEAMA_FW=y CONFIG_MTD_SPLIT_TPLINK_FW=y diff --git a/target/linux/ath79/dts/qca9563_tplink_eap245-v3.dts b/target/linux/ath79/dts/qca9563_tplink_eap245-v3.dts new file mode 100644 index 0000000000..f9e3f0a696 --- /dev/null +++ b/target/linux/ath79/dts/qca9563_tplink_eap245-v3.dts @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/dts-v1/; + +#include +#include + +#include "qca956x.dtsi" + +/ { + compatible = "tplink,eap245-v3", "qca,qca9563"; + model = "TP-Link EAP245 v3"; + + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_amber; + led-running = &led_status_green; + led-upgrade = &led_status_amber; + label-mac-device = ð0; + }; + + leds { + compatible = "gpio-leds"; + + led_status_green: status_green { + label = "tp-link:green:status"; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + led_status_amber: status_amber { + label = "tp-link:amber:status"; + gpios = <&gpio 9 GPIO_ACTIVE_HIGH>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "Reset button"; + linux,code = ; + gpios = <&gpio 2 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&uart { + status = "okay"; +}; + +&spi { + status = "okay"; + num-cs = <1>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <25000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "factory-boot"; + reg = <0x000000 0x040000>; + read-only; + }; + + partition@40000 { + label = "u-boot"; + reg = <0x040000 0x040000>; + read-only; + }; + + partition@80000 { + label = "partition-table"; + reg = <0x080000 0x010000>; + read-only; + }; + + info: partition@90000 { + label = "info"; + reg = <0x090000 0x010000>; + read-only; + }; + + art: partition@a0000 { + label = "art"; + reg = <0x0a0000 0x010000>; + read-only; + }; + + partition@b0000 { + label = "extra-para"; + reg = <0x0b0000 0x010000>; + read-only; + }; + + partition@c0000 { + compatible = "openwrt,elf"; + label = "firmware"; + reg = <0x0c0000 0xe40000>; + }; + + partition@f00000 { + label = "config"; + reg = <0xf00000 0x030000>; + read-only; + }; + + partition@f30000 { + label = "mutil-log"; + reg = <0xf30000 0x080000>; + read-only; + }; + + partition@fb0000 { + label = "oops"; + reg = <0xfb0000 0x040000>; + read-only; + }; + }; + }; +}; + +&mdio0 { + status = "okay"; + + phy-mask = <0x1>; + + phy0: ethernet-phy@0 { + reg = <0>; + phy-mode = "sgmii"; + qca,ar8327-initvals = < + 0x04 0x00080080 /* PAD0 */ + 0x7c 0x0000007e /* PORT0_STATUS */ + 0xe0 0xc74164de /* SGMII_CTRL */ + >; + }; +}; + +ð0 { + status = "okay"; + + phy-handle = <&phy0>; + phy-mode = "sgmii"; + + mtd-mac-address = <&info 0x8>; +}; + +&wmac { + status = "okay"; + + mtd-cal-data = <&art 0x1000>; + mtd-mac-address = <&info 0x8>; +}; diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network index 34dd975e19..2923ffabeb 100755 --- a/target/linux/ath79/generic/base-files/etc/board.d/02_network +++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network @@ -301,6 +301,10 @@ ath79_setup_interfaces() ucidef_add_switch "switch0" \ "0@eth1" "3:lan:3" "4:lan:2" "5:lan:1" "6@eth0" "2:wan:4" "1:wan:5" ;; + tplink,eap245-v3) + ucidef_add_switch "switch0" \ + "0@eth0" "2:lan:1" "5:lan:2" + ;; tplink,tl-mr6400-v1) ucidef_set_interfaces_lan_wan "eth0.1 eth1" "usb0" ucidef_add_switch "switch0" \ diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index 66777cb9f5..1bfb8c2c61 100644 --- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -206,6 +206,10 @@ case "$FIRMWARE" in ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ /lib/firmware/ath10k/QCA9888/hw2.0/board.bin ;; + tplink,eap245-v3) + caldata_extract "art" 0x5000 0x2f20 + ath10k_patch_mac $(macaddr_add $(mtd_get_mac_binary info 0x8) +1) + ;; yuncore,a782|\ yuncore,xd4200) caldata_extract "art" 0x5000 0x2f20 diff --git a/target/linux/ath79/image/generic-tp-link.mk b/target/linux/ath79/image/generic-tp-link.mk index 7128d853f8..daf793671f 100644 --- a/target/linux/ath79/image/generic-tp-link.mk +++ b/target/linux/ath79/image/generic-tp-link.mk @@ -362,6 +362,26 @@ define Device/tplink_cpe610-v2 endef TARGET_DEVICES += tplink_cpe610-v2 +define Device/tplink-eap2x5 + $(Device/tplink-safeloader) + SOC := qca9563 + LOADER_TYPE := elf + KERNEL := kernel-bin | append-dtb | lzma | loader-kernel + KERNEL_INITRAMFS := $$(KERNEL) + IMAGE/factory.bin := append-rootfs | tplink-safeloader factory | \ + pad-extra 128 +endef + +define Device/tplink_eap245-v3 + $(Device/tplink-eap2x5) + IMAGE_SIZE := 14592k + DEVICE_MODEL := EAP245 + DEVICE_VARIANT := v3 + DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca99x0-ct + TPLINK_BOARD_ID := EAP245-V3 +endef +TARGET_DEVICES += tplink_eap245-v3 + define Device/tplink_re350k-v1 $(Device/tplink-safeloader) SOC := qca9558 diff --git a/target/linux/generic/config-4.19 b/target/linux/generic/config-4.19 index e7e44a9075..96aae25a49 100644 --- a/target/linux/generic/config-4.19 +++ b/target/linux/generic/config-4.19 @@ -3033,6 +3033,7 @@ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096 CONFIG_MTD_SPLIT=y # CONFIG_MTD_SPLIT_BCM_WFI_FW is not set # CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set +# CONFIG_MTD_SPLIT_ELF_FW is not set # CONFIG_MTD_SPLIT_EVA_FW is not set # CONFIG_MTD_SPLIT_FIRMWARE is not set CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware" diff --git a/target/linux/generic/config-5.4 b/target/linux/generic/config-5.4 index 32795851a8..7a4c29070a 100644 --- a/target/linux/generic/config-5.4 +++ b/target/linux/generic/config-5.4 @@ -3260,6 +3260,7 @@ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096 CONFIG_MTD_SPLIT=y # CONFIG_MTD_SPLIT_BCM_WFI_FW is not set # CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set +# CONFIG_MTD_SPLIT_ELF_FW is not set # CONFIG_MTD_SPLIT_EVA_FW is not set # CONFIG_MTD_SPLIT_FIRMWARE is not set CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware" diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig b/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig index 0447df585c..3b7e23af33 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig @@ -79,3 +79,8 @@ config MTD_SPLIT_JIMAGE_FW bool "JBOOT Image based firmware partition parser" depends on MTD_SPLIT_SUPPORT select MTD_SPLIT + +config MTD_SPLIT_ELF_FW + bool "ELF loader firmware partition parser" + depends on MTD_SPLIT_SUPPORT + select MTD_SPLIT diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile b/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile index d3634e78db..8671628e7c 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_MTD_SPLIT_EVA_FW) += mtdsplit_eva.o 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 diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c new file mode 100644 index 0000000000..47818416f6 --- /dev/null +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * MTD splitter for ELF loader firmware partitions + * + * Copyright (C) 2020 Sander Vanheule + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; version 2. + * + * To parse the ELF kernel loader, a small ELF parser is used that can + * handle both ELF32 or ELF64 class loaders. The splitter assumes that the + * kernel is always located before the rootfs, whether it is embedded in the + * loader or not. + * + * The kernel image is preferably embedded inside the ELF loader, so the end + * of the loader equals the end of the kernel partition. This is due to the + * way mtd_find_rootfs_from searches for the the rootfs: + * - if the kernel image is embedded in the loader, the appended rootfs may + * follow the loader immediately, within the same erase block. + * - if the kernel image is not embedded in the loader, but placed at some + * offset behind the loader (OKLI-style loader), the rootfs must be + * aligned to an erase-block after the loader and kernel image. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtdsplit.h" + +#define ELF_NR_PARTS 2 + +#define ELF_MAGIC 0x7f454c46 /* 0x7f E L F */ +#define ELF_CLASS_32 1 +#define ELF_CLASS_64 2 + +struct elf_header_ident { + uint32_t magic; + uint8_t class; + uint8_t data; + uint8_t version; + uint8_t osabi; + uint8_t abiversion; + uint8_t pad[7]; +}; + +struct elf_header_32 { + uint16_t type; + uint16_t machine; + uint32_t version; + uint32_t entry; + uint32_t phoff; + uint32_t shoff; + uint32_t flags; + uint16_t ehsize; + uint16_t phentsize; + uint16_t phnum; + uint16_t shentsize; + uint16_t shnum; + uint16_t shstrndx; +}; + +struct elf_header_64 { + uint16_t type; + uint16_t machine; + uint32_t version; + uint64_t entry; + uint64_t phoff; + uint64_t shoff; + uint32_t flags; + uint16_t ehsize; + uint16_t phentsize; + uint16_t phnum; + uint16_t shentsize; + uint16_t shnum; + uint16_t shstrndx; +}; + +struct elf_header { + struct elf_header_ident ident; + union { + struct elf_header_32 elf32; + struct elf_header_64 elf64; + }; +}; + +struct elf_program_header_32 { + uint32_t type; + uint32_t offset; + uint32_t vaddr; + uint32_t paddr; + uint32_t filesize; + uint32_t memsize; + uint32_t flags; +}; + +struct elf_program_header_64 { + uint32_t type; + uint32_t flags; + uint64_t offset; + uint64_t vaddr; + uint64_t paddr; + uint64_t filesize; + uint64_t memsize; +}; + + +static int mtdsplit_elf_read_mtd(struct mtd_info *mtd, size_t offset, + uint8_t *dst, size_t len) +{ + size_t retlen; + int ret; + + ret = mtd_read(mtd, offset, len, &retlen, dst); + if (ret) { + pr_debug("read error in \"%s\"\n", mtd->name); + return ret; + } + + if (retlen != len) { + pr_debug("short read in \"%s\"\n", mtd->name); + return -EIO; + } + + return 0; +} + +static int elf32_determine_size(struct mtd_info *mtd, struct elf_header *hdr, + size_t *size) +{ + struct elf_header_32 *hdr32 = &(hdr->elf32); + int err; + size_t section_end, ph_table_end, ph_entry; + struct elf_program_header_32 ph; + + *size = 0; + + if (hdr32->shoff > 0) { + *size = hdr32->shoff + hdr32->shentsize * hdr32->shnum; + return 0; + } + + ph_entry = hdr32->phoff; + ph_table_end = hdr32->phoff + hdr32->phentsize * hdr32->phnum; + + while (ph_entry < ph_table_end) { + err = mtdsplit_elf_read_mtd(mtd, ph_entry, (uint8_t *)(&ph), + sizeof(ph)); + if (err) + return err; + + section_end = ph.offset + ph.filesize; + if (section_end > *size) + *size = section_end; + + ph_entry += hdr32->phentsize; + } + + return 0; +} + +static int elf64_determine_size(struct mtd_info *mtd, struct elf_header *hdr, + size_t *size) +{ + struct elf_header_64 *hdr64 = &(hdr->elf64); + int err; + size_t section_end, ph_table_end, ph_entry; + struct elf_program_header_64 ph; + + *size = 0; + + if (hdr64->shoff > 0) { + *size = hdr64->shoff + hdr64->shentsize * hdr64->shnum; + return 0; + } + + ph_entry = hdr64->phoff; + ph_table_end = hdr64->phoff + hdr64->phentsize * hdr64->phnum; + + while (ph_entry < ph_table_end) { + err = mtdsplit_elf_read_mtd(mtd, ph_entry, (uint8_t *)(&ph), + sizeof(ph)); + if (err) + return err; + + section_end = ph.offset + ph.filesize; + if (section_end > *size) + *size = section_end; + + ph_entry += hdr64->phentsize; + } + + return 0; +} + +static int mtdsplit_parse_elf(struct mtd_info *mtd, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct elf_header hdr; + size_t loader_size, rootfs_offset; + enum mtdsplit_part_type type; + struct mtd_partition *parts; + int err; + + err = mtdsplit_elf_read_mtd(mtd, 0, (uint8_t *)&hdr, sizeof(hdr)); + if (err) + return err; + + if (be32_to_cpu(hdr.ident.magic) != ELF_MAGIC) { + pr_debug("invalid ELF magic %08x\n", + be32_to_cpu(hdr.ident.magic)); + return -EINVAL; + } + + switch (hdr.ident.class) { + case ELF_CLASS_32: + err = elf32_determine_size(mtd, &hdr, &loader_size); + break; + case ELF_CLASS_64: + err = elf64_determine_size(mtd, &hdr, &loader_size); + break; + default: + pr_debug("invalid ELF class %i\n", hdr.ident.class); + err = -EINVAL; + } + + if (err) + return err; + + err = mtd_find_rootfs_from(mtd, loader_size, mtd->size, + &rootfs_offset, &type); + if (err) + return err; + + if (rootfs_offset == mtd->size) { + pr_debug("no rootfs found in \"%s\"\n", mtd->name); + return -ENODEV; + } + + parts = kzalloc(ELF_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; + + 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 = mtd->size - rootfs_offset; + + *pparts = parts; + return ELF_NR_PARTS; +} + +static const struct of_device_id mtdsplit_elf_of_match_table[] = { + { .compatible = "openwrt,elf" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mtdsplit_elf_of_match_table); + +static struct mtd_part_parser mtdsplit_elf_parser = { + .owner = THIS_MODULE, + .name = "elf-loader-fw", + .of_match_table = mtdsplit_elf_of_match_table, + .parse_fn = mtdsplit_parse_elf, + .type = MTD_PARSER_TYPE_FIRMWARE, +}; + +static int __init mtdsplit_elf_init(void) +{ + register_mtd_parser(&mtdsplit_elf_parser); + + return 0; +} + +subsys_initcall(mtdsplit_elf_init); diff --git a/target/linux/generic/pending-5.4/770-07-net-ethernet-mtk_eth_soc-drop-descriptor-cpu-own-bit.patch b/target/linux/generic/pending-5.4/770-07-net-ethernet-mtk_eth_soc-drop-descriptor-cpu-own-bit.patch deleted file mode 100644 index 0a9dfd68a1..0000000000 --- a/target/linux/generic/pending-5.4/770-07-net-ethernet-mtk_eth_soc-drop-descriptor-cpu-own-bit.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: Felix Fietkau -Date: Wed, 26 Aug 2020 17:48:14 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: drop descriptor cpu-own bit check - in qdma tx cleanup - -mtk_poll_tx_qdma already checks the MTK_QTX_DRX_PTR register, which points -at the last completed descriptor. -To slightly improve performance, also remove the register bit which forces -the hardware to write back this bit earlier. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1368,9 +1368,6 @@ static int mtk_poll_tx_qdma(struct mtk_e - int mac = 0; - - desc = mtk_qdma_phys_to_virt(ring, desc->txd2); -- if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0) -- break; -- - tx_buf = mtk_desc_to_tx_buf(ring, desc); - if (tx_buf->flags & MTK_TX_FLAGS_FPORT1) - mac = 1; -@@ -2203,7 +2200,7 @@ static int mtk_start_dma(struct mtk_eth - - if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { - mtk_w32(eth, -- MTK_TX_WB_DDONE | MTK_TX_DMA_EN | -+ MTK_TX_DMA_EN | - MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO | - MTK_RX_DMA_EN | MTK_RX_2B_OFFSET | - MTK_RX_BT_32DWORDS, diff --git a/target/linux/generic/pending-5.4/770-08-net-ethernet-mtk_eth_soc-cache-hardware-pointer-of-l.patch b/target/linux/generic/pending-5.4/770-08-net-ethernet-mtk_eth_soc-cache-hardware-pointer-of-l.patch index ddbd751ead..29dfd932e7 100644 --- a/target/linux/generic/pending-5.4/770-08-net-ethernet-mtk_eth_soc-cache-hardware-pointer-of-l.patch +++ b/target/linux/generic/pending-5.4/770-08-net-ethernet-mtk_eth_soc-cache-hardware-pointer-of-l.patch @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau dma = mtk_r32(eth, MTK_QTX_DRX_PTR); desc = mtk_qdma_phys_to_virt(ring, cpu); -@@ -1389,6 +1389,7 @@ static int mtk_poll_tx_qdma(struct mtk_e +@@ -1392,6 +1392,7 @@ static int mtk_poll_tx_qdma(struct mtk_e cpu = next_cpu; } @@ -28,7 +28,7 @@ Signed-off-by: Felix Fietkau mtk_w32(eth, cpu, MTK_QTX_CRX_PTR); return budget; -@@ -1589,6 +1590,7 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -1592,6 +1593,7 @@ static int mtk_tx_alloc(struct mtk_eth * atomic_set(&ring->free_count, MTK_DMA_SIZE - 2); ring->next_free = &ring->dma[0]; ring->last_free = &ring->dma[MTK_DMA_SIZE - 1]; @@ -36,7 +36,7 @@ Signed-off-by: Felix Fietkau ring->thresh = MAX_SKB_FRAGS; /* make sure that all changes to the dma ring are flushed before we -@@ -1602,9 +1604,7 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -1605,9 +1607,7 @@ static int mtk_tx_alloc(struct mtk_eth * mtk_w32(eth, ring->phys + ((MTK_DMA_SIZE - 1) * sz), MTK_QTX_CRX_PTR); diff --git a/target/linux/generic/pending-5.4/770-11-net-ethernet-mtk_eth_soc-avoid-rearming-interrupt-if.pa b/target/linux/generic/pending-5.4/770-11-net-ethernet-mtk_eth_soc-avoid-rearming-interrupt-if.pa index c8d17aefa8..e56799eb16 100644 --- a/target/linux/generic/pending-5.4/770-11-net-ethernet-mtk_eth_soc-avoid-rearming-interrupt-if.pa +++ b/target/linux/generic/pending-5.4/770-11-net-ethernet-mtk_eth_soc-avoid-rearming-interrupt-if.pa @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1512,8 +1512,8 @@ static int mtk_napi_tx(struct napi_struc +@@ -1515,8 +1515,8 @@ static int mtk_napi_tx(struct napi_struc if (status & MTK_TX_DONE_INT) return budget; @@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau return tx_done; } -@@ -1546,8 +1546,9 @@ poll_again: +@@ -1549,8 +1549,9 @@ poll_again: remain_budget -= rx_done; goto poll_again; } diff --git a/target/linux/kirkwood/base-files/etc/uci-defaults/05_fix-compat-version b/target/linux/kirkwood/base-files/etc/uci-defaults/05_fix-compat-version deleted file mode 100644 index d7f8488e88..0000000000 --- a/target/linux/kirkwood/base-files/etc/uci-defaults/05_fix-compat-version +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (C) 2020 OpenWrt.org -# - -. /lib/functions.sh - -case "$(board_name)" in - linksys,e4200-v2|\ - linksys,ea3500|\ - linksys,ea4500) - uci set system.@system[0].compat_version="1.1" - uci commit system - ;; -esac - -exit 0 diff --git a/target/linux/kirkwood/image/Makefile b/target/linux/kirkwood/image/Makefile index 89042d1726..0816add474 100644 --- a/target/linux/kirkwood/image/Makefile +++ b/target/linux/kirkwood/image/Makefile @@ -12,8 +12,7 @@ KERNEL_LOADADDR:=0x8000 define Device/dsa-migration DEVICE_COMPAT_VERSION := 1.1 - DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA \ - (early adopters with DSA already set up may just force-flash keeping existing config) + DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA endef define Device/Default diff --git a/target/linux/mediatek/patches-5.4/0600-1-6-net-dsa-mt7530-Refine-message-in-Kconfig.patch b/target/linux/mediatek/patches-5.4/0600-1-6-net-dsa-mt7530-Refine-message-in-Kconfig.patch deleted file mode 100644 index 5288751e50..0000000000 --- a/target/linux/mediatek/patches-5.4/0600-1-6-net-dsa-mt7530-Refine-message-in-Kconfig.patch +++ /dev/null @@ -1,98 +0,0 @@ -From patchwork Tue Dec 10 08:14:37 2019 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Landen Chao -X-Patchwork-Id: 1206962 -X-Patchwork-Delegate: davem@davemloft.net -Return-Path: -X-Original-To: patchwork-incoming-netdev@ozlabs.org -Delivered-To: patchwork-incoming-netdev@ozlabs.org -Authentication-Results: ozlabs.org; spf=none (no SPF record) - smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; - helo=vger.kernel.org; - envelope-from=netdev-owner@vger.kernel.org; - receiver=) -Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) - header.from=mediatek.com -Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; - unprotected) header.d=mediatek.com header.i=@mediatek.com - header.b="pTp2PPKi"; dkim-atps=neutral -Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) - by ozlabs.org (Postfix) with ESMTP id 47XCY42hJqz9sRf - for ; - Tue, 10 Dec 2019 19:15:20 +1100 (AEDT) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1727061AbfLJIO5 (ORCPT - ); - Tue, 10 Dec 2019 03:14:57 -0500 -Received: from mailgw02.mediatek.com ([210.61.82.184]:45567 "EHLO - mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by - vger.kernel.org with ESMTP id S1726932AbfLJIO4 (ORCPT - ); Tue, 10 Dec 2019 03:14:56 -0500 -X-UUID: f5656f2ff80846ebb40e3da87d60fb90-20191210 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=THbuVAlbiUyMgTyO0rwrKX/mskzsxNwDv9gxXp2O2c8=; - b=pTp2PPKiPwR8QPOOf5yohf9lFERpEDlo/g/t2ChREfzFb9c+wylx++/div4hAB337+Ja2KIzbSu4URgdj5XHXUly8yuxrD8OBvV+ox0jlNLiRIN2dkCgL4fyzPr7ZPSk9lObJW05Yx2LY6Jy6eJZZXSShLlqLd0lDKwy6FT+hSI=; -X-UUID: f5656f2ff80846ebb40e3da87d60fb90-20191210 -Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by - mailgw02.mediatek.com (envelope-from ) - (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) - with ESMTP id 565263134; Tue, 10 Dec 2019 16:14:47 +0800 -Received: from mtkcas08.mediatek.inc (172.21.101.126) by - mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server - (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:38 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via - Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800 -From: Landen Chao -To: , , - , , - , -CC: , , - , - , , - , , - , Landen Chao -Subject: [PATCH net-next 1/6] net: dsa: mt7530: Refine message in Kconfig -Date: Tue, 10 Dec 2019 16:14:37 +0800 -Message-ID: <6ecf6cbf38223f35854bc361c2eefa1d85c724d2.1575914275.git.landen.chao@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: -References: -MIME-Version: 1.0 -X-MTK: N -Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org - -Refine message in Kconfig with fixing typo and an explicit MT7621 support. - -Signed-off-by: Landen Chao -Signed-off-by: Sean Wang -Reviewed-by: Florian Fainelli ---- - drivers/net/dsa/Kconfig | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -33,12 +33,12 @@ config NET_DSA_LANTIQ_GSWIP - the xrx200 / VR9 SoC. - - config NET_DSA_MT7530 -- tristate "Mediatek MT7530 Ethernet switch support" -+ tristate "MediaTek MT7530 and MT7621 Ethernet switch support" - depends on NET_DSA - select NET_DSA_TAG_MTK - ---help--- -- This enables support for the Mediatek MT7530 Ethernet switch -- chip. -+ This enables support for the MediaTek MT7530 and MT7621 Ethernet -+ switch chip. - - config NET_DSA_MV88E6060 - tristate "Marvell 88E6060 ethernet switch chip support" diff --git a/target/linux/mediatek/patches-5.4/0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch b/target/linux/mediatek/patches-5.4/0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch deleted file mode 100644 index c4b117dcb7..0000000000 --- a/target/linux/mediatek/patches-5.4/0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch +++ /dev/null @@ -1,441 +0,0 @@ -From patchwork Tue Dec 10 08:14:38 2019 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Landen Chao -X-Patchwork-Id: 1206963 -X-Patchwork-Delegate: davem@davemloft.net -Return-Path: -X-Original-To: patchwork-incoming-netdev@ozlabs.org -Delivered-To: patchwork-incoming-netdev@ozlabs.org -Authentication-Results: ozlabs.org; spf=none (no SPF record) - smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; - helo=vger.kernel.org; - envelope-from=netdev-owner@vger.kernel.org; - receiver=) -Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) - header.from=mediatek.com -Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; - unprotected) header.d=mediatek.com header.i=@mediatek.com - header.b="UJ5NATux"; dkim-atps=neutral -Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) - by ozlabs.org (Postfix) with ESMTP id 47XCY92tBkz9sR7 - for ; - Tue, 10 Dec 2019 19:15:25 +1100 (AEDT) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1727003AbfLJIO4 (ORCPT - ); - Tue, 10 Dec 2019 03:14:56 -0500 -Received: from mailgw02.mediatek.com ([210.61.82.184]:45567 "EHLO - mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by - vger.kernel.org with ESMTP id S1726071AbfLJIOy (ORCPT - ); Tue, 10 Dec 2019 03:14:54 -0500 -X-UUID: a18674d7b33c423e9e67b7440f4771cf-20191210 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=c2C/fEHYw/8uqadmiP2m2xa2hsUpAd52urXVJTPlYck=; - b=UJ5NATuxMtqHln5i6BTpWiLnxGKgWvp4DpRsKVO2xdnz2cJaT4XL8F/T5fK3CTF4nAai0EKPAcqp+rr8eCLq7uURJv5e5h+ZIzKLSAB4zgnchXesQLo0uFS8vs5w2yp49j6bez1z3v/uN+1+Lpq0uYid9awCqzvbnovrooEysu4=; -X-UUID: a18674d7b33c423e9e67b7440f4771cf-20191210 -Received: from mtkcas09.mediatek.inc [(172.21.101.178)] by - mailgw02.mediatek.com (envelope-from ) - (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) - with ESMTP id 1965641267; Tue, 10 Dec 2019 16:14:46 +0800 -Received: from mtkcas08.mediatek.inc (172.21.101.126) by - mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server - (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:31 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via - Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800 -From: Landen Chao -To: , , - , , - , -CC: , , - , - , , - , , - , Landen Chao -Subject: [PATCH net-next 2/6] net: dsa: mt7530: Extend device data ready for - adding a new hardware -Date: Tue, 10 Dec 2019 16:14:38 +0800 -Message-ID: <2d546d6bb15ff8b4b75af2220e20db4e634f4145.1575914275.git.landen.chao@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: -References: -MIME-Version: 1.0 -X-MTK: N -Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org - -Add a structure holding required operations for each device such as device -initialization, PHY port read or write, a checker whether PHY interface is -supported on a certain port, MAC port setup for either bus pad or a -specific PHY interface. - -The patch is done for ready adding a new hardware MT7531. - -Signed-off-by: Landen Chao -Signed-off-by: Sean Wang ---- - drivers/net/dsa/mt7530.c | 231 +++++++++++++++++++++++++++++---------- - drivers/net/dsa/mt7530.h | 29 ++++- - 2 files changed, 203 insertions(+), 57 deletions(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -373,7 +373,7 @@ mt7530_fdb_write(struct mt7530_priv *pri - } - - static int --mt7530_pad_clk_setup(struct dsa_switch *ds, int mode) -+mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t mode) - { - struct mt7530_priv *priv = ds->priv; - u32 ncpo1, ssc_delta, trgint, i, xtal; -@@ -1355,13 +1355,111 @@ mt7530_setup(struct dsa_switch *ds) - return 0; - } - --static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port, -+static bool mt7530_phy_supported(struct dsa_switch *ds, int port, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_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: /* 2nd cpu port with phy of port 0 or 4 / external phy */ -+ if (!phy_interface_mode_is_rgmii(state->interface) && -+ state->interface != PHY_INTERFACE_MODE_MII && -+ state->interface != PHY_INTERFACE_MODE_GMII) -+ goto unsupported; -+ break; -+ case 6: /* 1st cpu port */ -+ if (state->interface != PHY_INTERFACE_MODE_RGMII && -+ state->interface != PHY_INTERFACE_MODE_TRGMII) -+ goto unsupported; -+ break; -+ default: -+ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, -+ port); -+ goto unsupported; -+ } -+ -+ return true; -+ -+unsupported: -+ return false; -+} -+ -+static bool mt753x_phy_supported(struct dsa_switch *ds, int port, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->phy_supported(ds, port, state); -+} -+ -+static int -+mt7530_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ /* Setup TX circuit incluing relevant PAD and driving */ -+ mt7530_pad_clk_setup(ds, state->interface); -+ -+ if (priv->id == ID_MT7530) { -+ /* Setup RX circuit, relevant PAD and driving on the -+ * host which must be placed after the setup on the -+ * device side is all finished. -+ */ -+ mt7623_pad_clk_setup(ds); -+ } -+ -+ return 0; -+} -+ -+static int -+mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->pad_setup(ds, state); -+} -+ -+static int -+mt7530_mac_setup(struct dsa_switch *ds, int port, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ /* Only need to setup port5. */ -+ if (port != 5) -+ return 0; -+ -+ mt7530_setup_port5(priv->ds, state->interface); -+ -+ return 0; -+} -+ -+static int mt753x_mac_setup(struct dsa_switch *ds, int port, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->mac_setup(ds, port, mode, state); -+} -+ -+static void mt753x_phylink_mac_config(struct dsa_switch *ds, int port, - unsigned int mode, - const struct phylink_link_state *state) - { - struct mt7530_priv *priv = ds->priv; - u32 mcr_cur, mcr_new; - -+ if (!mt753x_phy_supported(ds, port, state)) -+ return; -+ - switch (port) { - case 0: /* Internal phy */ - case 1: -@@ -1374,24 +1472,15 @@ static void mt7530_phylink_mac_config(st - case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ - if (priv->p5_interface == state->interface) - break; -- if (!phy_interface_mode_is_rgmii(state->interface) && -- state->interface != PHY_INTERFACE_MODE_MII && -- state->interface != PHY_INTERFACE_MODE_GMII) -- return; -- -- mt7530_setup_port5(ds, state->interface); -+ if (mt753x_mac_setup(ds, port, mode, state) < 0) -+ goto unsupported; - break; - case 6: /* 1st cpu port */ - if (priv->p6_interface == state->interface) - break; -- -- if (state->interface != PHY_INTERFACE_MODE_RGMII && -- state->interface != PHY_INTERFACE_MODE_TRGMII) -- return; -- -- /* Setup TX circuit incluing relevant PAD and driving */ -- mt7530_pad_clk_setup(ds, state->interface); -- -+ mt753x_pad_setup(ds, state); -+ if (mt753x_mac_setup(ds, port, mode, state) < 0) -+ goto unsupported; - priv->p6_interface = state->interface; - break; - default: -@@ -1459,38 +1548,14 @@ static void mt7530_phylink_mac_link_up(s - mt7530_port_set_status(priv, port, 1); - } - --static void mt7530_phylink_validate(struct dsa_switch *ds, int port, -+static void mt753x_phylink_validate(struct dsa_switch *ds, int port, - unsigned long *supported, - struct phylink_link_state *state) - { - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -- switch (port) { -- case 0: /* Internal phy */ -- case 1: -- case 2: -- case 3: -- case 4: -- if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_GMII) -- goto unsupported; -- break; -- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ -- if (state->interface != PHY_INTERFACE_MODE_NA && -- !phy_interface_mode_is_rgmii(state->interface) && -- state->interface != PHY_INTERFACE_MODE_MII && -- state->interface != PHY_INTERFACE_MODE_GMII) -- goto unsupported; -- break; -- case 6: /* 1st cpu port */ -- if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_RGMII && -- state->interface != PHY_INTERFACE_MODE_TRGMII) -- goto unsupported; -- break; -- default: -- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); --unsupported: -+ if (state->interface != PHY_INTERFACE_MODE_NA && -+ !mt753x_phy_supported(ds, port, state)) { - linkmode_zero(supported); - return; - } -@@ -1609,12 +1674,36 @@ static int mt7530_set_mac_eee(struct dsa - return 0; - } - -+static int -+mt753x_setup(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->setup(ds); -+} -+ -+static int -+mt753x_phy_read(struct dsa_switch *ds, int port, int regnum) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->phy_read(ds, port, regnum); -+} -+ -+static int -+mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->phy_write(ds, port, regnum, val); -+} -+ - static const struct dsa_switch_ops mt7530_switch_ops = { - .get_tag_protocol = mtk_get_tag_protocol, -- .setup = mt7530_setup, -+ .setup = mt753x_setup, - .get_strings = mt7530_get_strings, -- .phy_read = mt7530_phy_read, -- .phy_write = mt7530_phy_write, -+ .phy_read = mt753x_phy_read, -+ .phy_write = mt753x_phy_write, - .get_ethtool_stats = mt7530_get_ethtool_stats, - .get_sset_count = mt7530_get_sset_count, - .port_enable = mt7530_port_enable, -@@ -1631,18 +1720,39 @@ static const struct dsa_switch_ops mt753 - .port_vlan_del = mt7530_port_vlan_del, - .port_mirror_add = mt7530_port_mirror_add, - .port_mirror_del = mt7530_port_mirror_del, -- .phylink_validate = mt7530_phylink_validate, -+ .phylink_validate = mt753x_phylink_validate, - .phylink_mac_link_state = mt7530_phylink_mac_link_state, -- .phylink_mac_config = mt7530_phylink_mac_config, -+ .phylink_mac_config = mt753x_phylink_mac_config, - .phylink_mac_link_down = mt7530_phylink_mac_link_down, - .phylink_mac_link_up = mt7530_phylink_mac_link_up, - .get_mac_eee = mt7530_get_mac_eee, - .set_mac_eee = mt7530_set_mac_eee, - }; - --static const struct of_device_id mt7530_of_match[] = { -- { .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, }, -- { .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, }, -+static const struct mt753x_info mt753x_table[] = { -+ [ID_MT7621] = { -+ .id = ID_MT7621, -+ .setup = mt7530_setup, -+ .phy_read = mt7530_phy_read, -+ .phy_write = mt7530_phy_write, -+ .phy_supported = mt7530_phy_supported, -+ .pad_setup = mt7530_pad_setup, -+ .mac_setup = mt7530_mac_setup, -+ }, -+ [ID_MT7530] = { -+ .id = ID_MT7530, -+ .setup = mt7530_setup, -+ .phy_read = mt7530_phy_read, -+ .phy_write = mt7530_phy_write, -+ .phy_supported = mt7530_phy_supported, -+ .pad_setup = mt7530_pad_setup, -+ .mac_setup = mt7530_mac_setup, -+ }, -+}; -+ -+ static const struct of_device_id mt7530_of_match[] = { -+ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, -+ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, - { /* sentinel */ }, - }; - MODULE_DEVICE_TABLE(of, mt7530_of_match); -@@ -1680,8 +1790,19 @@ mt7530_probe(struct mdio_device *mdiodev - /* Get the hardware identifier from the devicetree node. - * We will need it for some of the clock and regulator setup. - */ -- priv->id = (unsigned int)(unsigned long) -- of_device_get_match_data(&mdiodev->dev); -+ priv->info = of_device_get_match_data(&mdiodev->dev); -+ if (!priv->info) -+ return -EINVAL; -+ -+ /* Sanity check if these required device operstaions are filled -+ * properly. -+ */ -+ if (!priv->info->setup || !priv->info->phy_read || -+ !priv->info->phy_write || !priv->info->phy_supported || -+ !priv->info->pad_setup || !priv->info->mac_setup) -+ return -EINVAL; -+ -+ priv->id = priv->info->id; - - if (priv->id == ID_MT7530) { - priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -11,7 +11,7 @@ - #define MT7530_NUM_FDB_RECORDS 2048 - #define MT7530_ALL_MEMBERS 0xff - --enum { -+enum mt753x_id { - ID_MT7530 = 0, - ID_MT7621 = 1, - }; -@@ -447,6 +447,32 @@ static const char *p5_intf_modes(unsigne - } - } - -+/* struct mt753x_info - This is the main data structure for holding the specific -+ * part for each supported device -+ * @setup: Holding the handler to a device initialization -+ * @phy_read: Holding the way reading PHY port -+ * @phy_write: Holding the way writing PHY port -+ * @phy_supported: Check if the PHY type is being supported on a certain -+ * port -+ * @pad_setup: Holding the way setting up the bus pad for a certain MAC -+ * port -+ * @mac_setup: Holding the way setting up the PHY attribute for a -+ * certain MAC port -+ */ -+struct mt753x_info { -+ enum mt753x_id id; -+ -+ int (*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); -+ bool (*phy_supported)(struct dsa_switch *ds, int port, -+ const struct phylink_link_state *state); -+ int (*pad_setup)(struct dsa_switch *ds, -+ const struct phylink_link_state *state); -+ int (*mac_setup)(struct dsa_switch *ds, int port, unsigned int mode, -+ const struct phylink_link_state *state); -+}; -+ - /* struct mt7530_priv - This is the main data structure for holding the state - * of the driver - * @dev: The device pointer -@@ -472,6 +498,7 @@ struct mt7530_priv { - struct regulator *core_pwr; - struct regulator *io_pwr; - struct gpio_desc *reset; -+ const struct mt753x_info *info; - unsigned int id; - bool mcm; - phy_interface_t p6_interface; diff --git a/target/linux/mediatek/patches-5.4/0600-3-6-dt-bindings-net-dsa-add-new-MT7531-binding-to-support-MT7531.patch b/target/linux/mediatek/patches-5.4/0600-3-6-dt-bindings-net-dsa-add-new-MT7531-binding-to-support-MT7531.patch deleted file mode 100644 index b28f23f573..0000000000 --- a/target/linux/mediatek/patches-5.4/0600-3-6-dt-bindings-net-dsa-add-new-MT7531-binding-to-support-MT7531.patch +++ /dev/null @@ -1,179 +0,0 @@ -From patchwork Tue Dec 10 08:14:39 2019 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Landen Chao -X-Patchwork-Id: 1206955 -X-Patchwork-Delegate: davem@davemloft.net -Return-Path: -X-Original-To: patchwork-incoming-netdev@ozlabs.org -Delivered-To: patchwork-incoming-netdev@ozlabs.org -Authentication-Results: ozlabs.org; spf=none (no SPF record) - smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; - helo=vger.kernel.org; - envelope-from=netdev-owner@vger.kernel.org; - receiver=) -Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) - header.from=mediatek.com -Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; - unprotected) header.d=mediatek.com header.i=@mediatek.com - header.b="SuczJHZp"; dkim-atps=neutral -Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) - by ozlabs.org (Postfix) with ESMTP id 47XCXj3BBNz9sPh - for ; - Tue, 10 Dec 2019 19:15:01 +1100 (AEDT) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1727133AbfLJIPA (ORCPT - ); - Tue, 10 Dec 2019 03:15:00 -0500 -Received: from mailgw02.mediatek.com ([210.61.82.184]:45567 "EHLO - mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by - vger.kernel.org with ESMTP id S1727022AbfLJIO7 (ORCPT - ); Tue, 10 Dec 2019 03:14:59 -0500 -X-UUID: a1d9a42928d44d63b201d5ad84c05baa-20191210 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=KJqQ2m7z9H4vre+SZyxgKEGRWb9Edp5pJlYnepJNMyM=; - b=SuczJHZpeY7vF8UsCGorYUAcT2lEUX2E0ciiyQBS1rDLPzTYnufK8OXyAw5Uq8U1m72TGWYCaq1o0VWtI1meJpEmCL2TVK/d+Y+IaacHlO716BmX77+0MU0crczE8zx1Nz2pNh+GicsB6AoC9qbBU+p5egbKDMBhpRaGQNAeBww=; -X-UUID: a1d9a42928d44d63b201d5ad84c05baa-20191210 -Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by - mailgw02.mediatek.com (envelope-from ) - (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) - with ESMTP id 297826603; Tue, 10 Dec 2019 16:14:47 +0800 -Received: from mtkcas08.mediatek.inc (172.21.101.126) by - mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server - (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:38 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via - Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800 -From: Landen Chao -To: , , - , , - , -CC: , , - , - , , - , , - , Landen Chao -Subject: [PATCH net-next 3/6] dt-bindings: net: dsa: add new MT7531 binding - to support MT7531 -Date: Tue, 10 Dec 2019 16:14:39 +0800 -Message-ID: <1c382fd916b66bfe3ce8ef18c12f954dbcbddbbc.1575914275.git.landen.chao@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: -References: -MIME-Version: 1.0 -X-MTK: N -Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org - -Add devicetree binding to support the compatible mt7531 switch as used -in the MediaTek MT7531 switch. - -Signed-off-by: Sean Wang -Signed-off-by: Landen Chao ---- - .../devicetree/bindings/net/dsa/mt7530.txt | 77 ++++++++++++++++++- - 1 file changed, 74 insertions(+), 3 deletions(-) - ---- a/Documentation/devicetree/bindings/net/dsa/mt7530.txt -+++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt -@@ -5,6 +5,7 @@ Required properties: - - - compatible: may be compatible = "mediatek,mt7530" - or compatible = "mediatek,mt7621" -+ or compatible = "mediatek,mt7531" - - #address-cells: Must be 1. - - #size-cells: Must be 0. - - mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part -@@ -32,10 +33,13 @@ Required properties for the child nodes - - - reg: Port address described must be 6 for CPU port and from 0 to 5 for - user ports. --- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled -- "cpu". -+- phy-mode: String, the follow value would be acceptable for port labeled "cpu" -+ If compatible mediatek,mt7530 or mediatek,mt7621 is set, -+ must be either "trgmii" or "rgmii" -+ If compatible mediatek,mt7531 is set, -+ must be either "sgmii", "1000base-x" or "2500base-x" - --Port 5 of the switch is muxed between: -+Port 5 of mt7530 and mt7621 switch is muxed between: - 1. GMAC5: GMAC5 can interface with another external MAC or PHY. - 2. PHY of port 0 or port 4: PHY interfaces with an external MAC like 2nd GMAC - of the SOC. Used in many setups where port 0/4 becomes the WAN port. -@@ -308,3 +312,70 @@ Example 3: MT7621: Port 5 is connected t - }; - }; - }; -+ -+Example 4: -+ -+ð { -+ gmac0: mac@0 { -+ compatible = "mediatek,eth-mac"; -+ reg = <0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ -+ &mdio0 { -+ switch@0 { -+ compatible = "mediatek,mt7531"; -+ reg = <0>; -+ reset-gpios = <&pio 54 0>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0>; -+ -+ port@0 { -+ reg = <0>; -+ label = "lan0"; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ label = "lan1"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ label = "lan2"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ label = "lan3"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ label = "wan"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ label = "cpu"; -+ ethernet = <&gmac0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ }; -+ }; -+ }; diff --git a/target/linux/mediatek/patches-5.4/0600-4-6-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch b/target/linux/mediatek/patches-5.4/0600-4-6-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch deleted file mode 100644 index 299ac24c79..0000000000 --- a/target/linux/mediatek/patches-5.4/0600-4-6-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch +++ /dev/null @@ -1,1096 +0,0 @@ -From patchwork Tue Dec 10 08:14:40 2019 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Landen Chao -X-Patchwork-Id: 1206959 -X-Patchwork-Delegate: davem@davemloft.net -Return-Path: -X-Original-To: patchwork-incoming-netdev@ozlabs.org -Delivered-To: patchwork-incoming-netdev@ozlabs.org -Authentication-Results: ozlabs.org; spf=none (no SPF record) - smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; - helo=vger.kernel.org; - envelope-from=netdev-owner@vger.kernel.org; - receiver=) -Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) - header.from=mediatek.com -Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; - unprotected) header.d=mediatek.com header.i=@mediatek.com - header.b="A6fsNqWU"; dkim-atps=neutral -Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) - by ozlabs.org (Postfix) with ESMTP id 47XCXz2fDsz9sPh - for ; - Tue, 10 Dec 2019 19:15:15 +1100 (AEDT) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1727198AbfLJIPC (ORCPT - ); - Tue, 10 Dec 2019 03:15:02 -0500 -Received: from mailgw02.mediatek.com ([210.61.82.184]:39119 "EHLO - mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by - vger.kernel.org with ESMTP id S1726750AbfLJIPC (ORCPT - ); Tue, 10 Dec 2019 03:15:02 -0500 -X-UUID: 38155314c18e497aacbec5bc0f664b9a-20191210 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=sEkoMPWKI3m+K/8A3kC0uuYTNxZZaGCvfLKvnEmwQQ4=; - b=A6fsNqWUmjxIiZPLPb43Hs36qwwvYXMLQ/LlU24IcsfBro20uMkDbzGq522r69u0071Qgekwc/zs4yujo0pz40jCfnAo38JIDP73w4ZyVGuOENM5gdE+qNNUednOVSi052hcMRhS7zpVD0Rfl7vKKOU42F7Tl+cadVzjUl0ow/s=; -X-UUID: 38155314c18e497aacbec5bc0f664b9a-20191210 -Received: from mtkcas09.mediatek.inc [(172.21.101.178)] by - mailgw02.mediatek.com (envelope-from ) - (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) - with ESMTP id 452927388; Tue, 10 Dec 2019 16:14:46 +0800 -Received: from mtkcas08.mediatek.inc (172.21.101.126) by - mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server - (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:31 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via - Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800 -From: Landen Chao -To: , , - , , - , -CC: , , - , - , , - , , - , Landen Chao -Subject: [PATCH net-next 4/6] net: dsa: mt7530: Add the support of MT7531 - switch -Date: Tue, 10 Dec 2019 16:14:40 +0800 -Message-ID: <6d608dd024edc90b09ba4fe35417b693847f973c.1575914275.git.landen.chao@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: -References: -MIME-Version: 1.0 -X-MTK: N -Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org - -Add new support for MT7531: - -MT7531 is the next generation of MT7530. It is also a 7-ports switch with -5 giga embedded phys, 2 cpu ports, and the same MAC logic of MT7530. Cpu -port 6 only supports HSGMII interface. Cpu port 5 supports either RGMII -or HSGMII in different HW sku. Due to HSGMII interface support, pll, and -pad setting are different from MT7530. This patch adds different initial -setting of MT7531. - -Signed-off-by: Landen Chao -Signed-off-by: Sean Wang ---- - drivers/net/dsa/Kconfig | 6 +- - drivers/net/dsa/mt7530.c | 643 ++++++++++++++++++++++++++++++++++++++- - drivers/net/dsa/mt7530.h | 144 +++++++++ - 3 files changed, 784 insertions(+), 9 deletions(-) - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -33,12 +33,12 @@ config NET_DSA_LANTIQ_GSWIP - the xrx200 / VR9 SoC. - - config NET_DSA_MT7530 -- tristate "MediaTek MT7530 and MT7621 Ethernet switch support" -+ tristate "MediaTek MT753x and MT7621 Ethernet switch support" - depends on NET_DSA - select NET_DSA_TAG_MTK - ---help--- -- This enables support for the MediaTek MT7530 and MT7621 Ethernet -- switch chip. -+ This enables support for the MediaTek MT7530, MT7531 and MT7621 -+ Ethernet switch chip. - - config NET_DSA_MV88E6060 - tristate "Marvell 88E6060 ethernet switch chip support" ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -234,6 +234,12 @@ mt7530_write(struct mt7530_priv *priv, u - } - - static u32 -+_mt7530_unlocked_read(struct mt7530_dummy_poll *p) -+{ -+ return mt7530_mii_read(p->priv, p->reg); -+} -+ -+static u32 - _mt7530_read(struct mt7530_dummy_poll *p) - { - struct mii_bus *bus = p->priv->bus; -@@ -287,6 +293,102 @@ mt7530_clear(struct mt7530_priv *priv, u - } - - static int -+mt7531_ind_mmd_phy_read(struct mt7530_priv *priv, int port, int devad, -+ int regnum) -+{ -+ struct mii_bus *bus = priv->bus; -+ struct mt7530_dummy_poll p; -+ u32 reg, val; -+ int ret; -+ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MDIO_CL45_ADDR | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) | -+ regnum; -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MDIO_CL45_READ | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad); -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ ret = val & MDIO_RW_DATA_MASK; -+out: -+ mutex_unlock(&bus->mdio_lock); -+ -+ return ret; -+} -+ -+static int -+mt7531_ind_mmd_phy_write(struct mt7530_priv *priv, int port, int devad, -+ int regnum, u32 data) -+{ -+ struct mii_bus *bus = priv->bus; -+ struct mt7530_dummy_poll p; -+ u32 val, reg; -+ int ret; -+ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MDIO_CL45_ADDR | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) | -+ regnum; -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MDIO_CL45_WRITE | MDIO_PHY_ADDR(port) | MDIO_DEV_ADDR(devad) | -+ data; -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+out: -+ mutex_unlock(&bus->mdio_lock); -+ -+ return ret; -+} -+ -+static int - mt7530_fdb_cmd(struct mt7530_priv *priv, enum mt7530_fdb_cmd cmd, u32 *rsp) - { - u32 val; -@@ -516,6 +618,83 @@ static int mt7530_phy_write(struct dsa_s - return mdiobus_write_nested(priv->bus, port, regnum, val); - } - -+static int -+mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ struct mii_bus *bus = priv->bus; -+ struct mt7530_dummy_poll p; -+ int ret; -+ u32 val; -+ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ val = MDIO_CL22_READ | MDIO_PHY_ADDR(port) | MDIO_REG_ADDR(regnum); -+ -+ mt7530_mii_write(priv, MT7531_PHY_IAC, val | PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ ret = val & MDIO_RW_DATA_MASK; -+out: -+ mutex_unlock(&bus->mdio_lock); -+ -+ return ret; -+} -+ -+static int -+mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum, -+ u16 data) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ struct mii_bus *bus = priv->bus; -+ struct mt7530_dummy_poll p; -+ int ret; -+ u32 reg; -+ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, -+ !(reg & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MDIO_CL22_WRITE | MDIO_PHY_ADDR(port) | MDIO_REG_ADDR(regnum) | -+ data; -+ -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, -+ !(reg & PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+out: -+ mutex_unlock(&bus->mdio_lock); -+ -+ return ret; -+} -+ - static void - mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset, - uint8_t *data) -@@ -1355,6 +1534,86 @@ mt7530_setup(struct dsa_switch *ds) - return 0; - } - -+static int mt7531_setup(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ struct mt7530_dummy_poll p; -+ u32 val, id; -+ int ret, i; -+ -+ /* Reset whole chip through gpio pin or memory-mapped registers for -+ * different type of hardware -+ */ -+ if (priv->mcm) { -+ reset_control_assert(priv->rstc); -+ usleep_range(1000, 1100); -+ reset_control_deassert(priv->rstc); -+ } else { -+ gpiod_set_value_cansleep(priv->reset, 0); -+ usleep_range(1000, 1100); -+ gpiod_set_value_cansleep(priv->reset, 1); -+ } -+ -+ /* Waiting for MT7530 got to stable */ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP); -+ ret = readx_poll_timeout(_mt7530_read, &p, val, val != 0, -+ 20, 1000000); -+ if (ret < 0) { -+ dev_err(priv->dev, "reset timeout\n"); -+ return ret; -+ } -+ -+ id = mt7530_read(priv, MT7531_CREV); -+ id >>= CHIP_NAME_SHIFT; -+ -+ if (id != MT7531_ID) { -+ dev_err(priv->dev, "chip %x can't be supported\n", id); -+ return -ENODEV; -+ } -+ -+ /* Reset the switch through internal reset */ -+ mt7530_write(priv, MT7530_SYS_CTRL, -+ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | -+ SYS_CTRL_REG_RST); -+ -+ priv->p6_interface = PHY_INTERFACE_MODE_NA; -+ -+ /* Enable PHY power, since phy_device has not yet been created -+ * provided for phy_[read,write]_mmd_indirect is called, we provide -+ * our own mt7531_ind_mmd_phy_[read,write] to complete this -+ * function. -+ */ -+ val = mt7531_ind_mmd_phy_read(priv, 0, PHY_DEV1F, -+ MT7531_PHY_DEV1F_REG_403); -+ val |= MT7531_PHY_EN_BYPASS_MODE; -+ val &= ~MT7531_PHY_POWER_OFF; -+ mt7531_ind_mmd_phy_write(priv, 0, PHY_DEV1F, -+ MT7531_PHY_DEV1F_REG_403, val); -+ -+ /* Enable and reset MIB counters */ -+ mt7530_mib_reset(ds); -+ -+ mt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ /* Disable forwarding by default on all ports */ -+ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, -+ PCR_MATRIX_CLR); -+ -+ if (dsa_is_cpu_port(ds, i)) -+ mt7530_cpu_port_enable(priv, i); -+ else -+ mt7530_port_disable(ds, i); -+ } -+ -+ /* Flush the FDB table */ -+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ - static bool mt7530_phy_supported(struct dsa_switch *ds, int port, - const struct phylink_link_state *state) - { -@@ -1392,6 +1651,49 @@ unsupported: - return false; - } - -+static bool mt7531_dual_sgmii_supported(struct mt7530_priv *priv) -+{ -+ u32 val; -+ -+ val = mt7530_read(priv, MT7531_TOP_SIG_SR); -+ return ((val & PAD_DUAL_SGMII_EN) != 0); -+} -+ -+static bool mt7531_phy_supported(struct dsa_switch *ds, int port, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_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: /* 2nd cpu port supports either rgmii or sgmii/8023z */ -+ if (!mt7531_dual_sgmii_supported(priv)) -+ return phy_interface_mode_is_rgmii(state->interface); -+ /* fall through */ -+ case 6: /* 1st cpu port supports sgmii/8023z only */ -+ if (state->interface != PHY_INTERFACE_MODE_SGMII && -+ !phy_interface_mode_is_8023z(state->interface)) -+ goto unsupported; -+ break; -+ default: -+ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, -+ port); -+ goto unsupported; -+ } -+ -+ return true; -+ -+unsupported: -+ return false; -+} -+ - static bool mt753x_phy_supported(struct dsa_switch *ds, int port, - const struct phylink_link_state *state) - { -@@ -1413,7 +1715,144 @@ mt7530_pad_setup(struct dsa_switch *ds, - * host which must be placed after the setup on the - * device side is all finished. - */ -- mt7623_pad_clk_setup(ds); -+ //mt7623_pad_clk_setup(ds); -+ } -+ -+ return 0; -+} -+ -+static int -+mt7531_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 xtal, val; -+ -+ if (mt7531_dual_sgmii_supported(priv)) -+ return 0; -+ -+ xtal = mt7530_read(priv, MT7531_HWTRAP) & HWTRAP_XTAL_FSEL_MASK; -+ -+ switch (xtal) { -+ case HWTRAP_XTAL_FSEL_25MHZ: -+ /* Step 1 : Disable MT7531 COREPLL */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val &= ~EN_COREPLL; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ /* Step 2: switch to XTAL output */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= SW_CLKSW; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_EN; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ /* Step 3: disable PLLGP and enable program PLLGP */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= SW_PLLGP; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ /* Step 4: program COREPLL output frequency to 500MHz */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_POSDIV_M; -+ val |= 2 << RG_COREPLL_POSDIV_S; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ usleep_range(25, 35); -+ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_SDM_PCW_M; -+ val |= 0x140000 << RG_COREPLL_SDM_PCW_S; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ /* Set feedback divide ratio update signal to high */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val |= RG_COREPLL_SDM_PCW_CHG; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ /* Wait for at least 16 XTAL clocks */ -+ usleep_range(10, 20); -+ -+ /* Step 5: set feedback divide ratio update signal to low */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_SDM_PCW_CHG; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ /* Enable 325M clock for SGMII */ -+ mt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000); -+ -+ /* Enable 250SSC clock for RGMII */ -+ mt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000); -+ -+ /* Step 6: Enable MT7531 PLL */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val |= RG_COREPLL_EN; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= EN_COREPLL; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ usleep_range(25, 35); -+ break; -+ case HWTRAP_XTAL_FSEL_40MHZ: -+ /* Step 1 : Disable MT7531 COREPLL */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val &= ~EN_COREPLL; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ /* Step 2: switch to XTAL output */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= SW_CLKSW; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_EN; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ /* Step 3: disable PLLGP and enable program PLLGP */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= SW_PLLGP; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ /* Step 4: program COREPLL output frequency to 500MHz */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_POSDIV_M; -+ val |= 2 << RG_COREPLL_POSDIV_S; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ usleep_range(25, 35); -+ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_SDM_PCW_M; -+ val |= 0x190000 << RG_COREPLL_SDM_PCW_S; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ /* Set feedback divide ratio update signal to high */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val |= RG_COREPLL_SDM_PCW_CHG; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ /* Wait for at least 16 XTAL clocks */ -+ usleep_range(10, 20); -+ -+ /* Step 5: set feedback divide ratio update signal to low */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_SDM_PCW_CHG; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ /* Enable 325M clock for SGMII */ -+ mt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000); -+ -+ /* Enable 250SSC clock for RGMII */ -+ mt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000); -+ -+ /* Step 6: Enable MT7531 PLL */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val |= RG_COREPLL_EN; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= EN_COREPLL; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ usleep_range(25, 35); -+ break; - } - - return 0; -@@ -1442,6 +1881,149 @@ mt7530_mac_setup(struct dsa_switch *ds, - return 0; - } - -+static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port) -+{ -+ u32 val; -+ -+ if (port != 5) { -+ dev_err(priv->dev, "RGMII mode is not available for port %d\n", -+ port); -+ return -EINVAL; -+ } -+ -+ val = mt7530_read(priv, MT7531_CLKGEN_CTRL); -+ val |= GP_CLK_EN; -+ val &= ~GP_MODE_MASK; -+ val |= GP_MODE(MT7531_GP_MODE_RGMII); -+ val |= TXCLK_NO_REVERSE; -+ val |= RXCLK_NO_DELAY; -+ val &= ~CLK_SKEW_IN_MASK; -+ val |= CLK_SKEW_IN(MT7531_CLK_SKEW_NO_CHG); -+ val &= ~CLK_SKEW_OUT_MASK; -+ val |= CLK_SKEW_OUT(MT7531_CLK_SKEW_NO_CHG); -+ mt7530_write(priv, MT7531_CLKGEN_CTRL, val); -+ -+ return 0; -+} -+ -+static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port, -+ const struct phylink_link_state *state) -+{ -+ u32 val; -+ -+ if (port != 5 && port != 6) -+ return -EINVAL; -+ -+ val = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port)); -+ val |= MT7531_SGMII_PHYA_PWD; -+ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val); -+ -+ val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); -+ val &= ~MT7531_RG_TPHY_SPEED_MASK; -+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -+ val |= MT7531_RG_TPHY_SPEED_3_125G; -+ mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); -+ -+ val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -+ val &= ~MT7531_SGMII_AN_ENABLE; -+ mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); -+ -+ val = mt7530_read(priv, MT7531_SGMII_MODE(port)); -+ val &= ~MT7531_SGMII_IF_MODE_MASK; -+ -+ switch (state->speed) { -+ case SPEED_10: -+ val |= MT7531_SGMII_FORCE_SPEED_10; -+ break; -+ case SPEED_100: -+ val |= MT7531_SGMII_FORCE_SPEED_100; -+ break; -+ case SPEED_2500: -+ case SPEED_1000: -+ val |= MT7531_SGMII_FORCE_SPEED_1000; -+ break; -+ }; -+ -+ val &= ~MT7531_SGMII_FORCE_DUPLEX; -+ /* For sgmii force mode, 0 is full duplex and 1 is half duplex */ -+ if (state->duplex == DUPLEX_HALF) -+ val |= MT7531_SGMII_FORCE_DUPLEX; -+ -+ mt7530_write(priv, MT7531_SGMII_MODE(port), val); -+ -+ val = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port)); -+ val &= ~MT7531_SGMII_PHYA_PWD; -+ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val); -+ -+ return 0; -+} -+ -+static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port, -+ const struct phylink_link_state *state) -+{ -+ u32 val; -+ -+ if (port != 5 && port != 6) -+ return -EINVAL; -+ -+ val = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port)); -+ val |= MT7531_SGMII_PHYA_PWD; -+ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val); -+ -+ switch (state->speed) { -+ case SPEED_10: -+ case SPEED_100: -+ case SPEED_1000: -+ val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); -+ val &= ~MT7531_RG_TPHY_SPEED_MASK; -+ mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); -+ break; -+ default: -+ dev_info(priv->dev, "invalid SGMII speed idx %d for port %d\n", -+ state->speed, port); -+ -+ return -EINVAL; -+ } -+ -+ val = mt7530_read(priv, MT7531_SGMII_MODE(port)); -+ val |= MT7531_SGMII_REMOTE_FAULT_DIS; -+ mt7530_write(priv, MT7531_SGMII_MODE(port), val); -+ -+ val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -+ val |= MT7531_SGMII_AN_RESTART; -+ mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); -+ -+ val = mt7530_read(priv, MT7531_QPHY_PWR_STATE_CTRL(port)); -+ val &= ~MT7531_SGMII_PHYA_PWD; -+ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), val); -+ -+ return 0; -+} -+ -+static int -+mt7531_mac_setup(struct dsa_switch *ds, int port, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ if (port < 5 || port >= MT7530_NUM_PORTS) { -+ dev_err(priv->dev, "port %d is not a MAC port\n", port); -+ return -EINVAL; -+ } -+ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ return mt7531_rgmii_setup(priv, port); -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return mt7531_sgmii_setup_mode_force(priv, port, state); -+ case PHY_INTERFACE_MODE_SGMII: -+ return mt7531_sgmii_setup_mode_an(priv, port, state); -+ default: -+ return -EINVAL; -+ } -+} -+ - static int mt753x_mac_setup(struct dsa_switch *ds, int port, unsigned int mode, - const struct phylink_link_state *state) - { -@@ -1473,22 +2055,23 @@ static void mt753x_phylink_mac_config(st - if (priv->p5_interface == state->interface) - break; - if (mt753x_mac_setup(ds, port, mode, state) < 0) -- goto unsupported; -+ break; -+ priv->p5_interface = state->interface; - break; - case 6: /* 1st cpu port */ - if (priv->p6_interface == state->interface) - break; - mt753x_pad_setup(ds, state); - if (mt753x_mac_setup(ds, port, mode, state) < 0) -- goto unsupported; -+ break; - priv->p6_interface = state->interface; - break; - default: -- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); - return; - } - -- if (phylink_autoneg_inband(mode)) { -+ if (phylink_autoneg_inband(mode) && -+ state->interface != PHY_INTERFACE_MODE_SGMII) { - dev_err(ds->dev, "%s: in-band negotiation unsupported\n", - __func__); - return; -@@ -1499,13 +2082,15 @@ static void mt753x_phylink_mac_config(st - mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 | - PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN); - mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | -- PMCR_BACKPR_EN | PMCR_FORCE_MODE; -+ PMCR_BACKPR_EN | PMCR_FORCE_MODE_ID(priv->id) | -+ PMCR_FORCE_LNK; - - /* Are we connected to external phy */ - if (port == 5 && dsa_is_user_port(ds, 5)) - mcr_new |= PMCR_EXT_PHY; - - switch (state->speed) { -+ case SPEED_2500: - case SPEED_1000: - mcr_new |= PMCR_FORCE_SPEED_1000; - if (priv->eee_enable & BIT(port)) -@@ -1529,6 +2114,27 @@ static void mt753x_phylink_mac_config(st - mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); - } - -+void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 val; -+ -+ val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -+ val |= MT7531_SGMII_AN_RESTART; -+ mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); -+} -+ -+static void -+mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ if (!priv->info->port_an_restart) -+ return; -+ -+ priv->info->port_an_restart(ds, port); -+} -+ - static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface) -@@ -1563,9 +2169,20 @@ static void mt753x_phylink_validate(stru - phylink_set_port_modes(mask); - phylink_set(mask, Autoneg); - -- if (state->interface == PHY_INTERFACE_MODE_TRGMII) { -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_TRGMII: - phylink_set(mask, 1000baseT_Full); -- } else { -+ break; -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ phylink_set(mask, 1000baseX_Full); -+ phylink_set(mask, 2500baseX_Full); -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ phylink_set(mask, 1000baseT_Full); -+ phylink_set(mask, 1000baseX_Full); -+ /* fall through */ -+ default: - phylink_set(mask, 10baseT_Half); - phylink_set(mask, 10baseT_Full); - phylink_set(mask, 100baseT_Half); -@@ -1577,6 +2194,7 @@ static void mt753x_phylink_validate(stru - if (port == 5) - phylink_set(mask, 1000baseX_Full); - } -+ break; - } - - phylink_set(mask, Pause); -@@ -1721,8 +2339,9 @@ static const struct dsa_switch_ops mt753 - .port_mirror_add = mt7530_port_mirror_add, - .port_mirror_del = mt7530_port_mirror_del, - .phylink_validate = mt753x_phylink_validate, -- .phylink_mac_link_state = mt7530_phylink_mac_link_state, -+ .phylink_mac_link_state = mt7530_phylink_mac_link_state, - .phylink_mac_config = mt753x_phylink_mac_config, -+ .phylink_mac_an_restart = mt753x_phylink_mac_an_restart, - .phylink_mac_link_down = mt7530_phylink_mac_link_down, - .phylink_mac_link_up = mt7530_phylink_mac_link_up, - .get_mac_eee = mt7530_get_mac_eee, -@@ -1748,11 +2367,22 @@ static const struct mt753x_info mt753x_t - .pad_setup = mt7530_pad_setup, - .mac_setup = mt7530_mac_setup, - }, -+ [ID_MT7531] = { -+ .id = ID_MT7531, -+ .setup = mt7531_setup, -+ .phy_read = mt7531_ind_phy_read, -+ .phy_write = mt7531_ind_phy_write, -+ .phy_supported = mt7531_phy_supported, -+ .pad_setup = mt7531_pad_setup, -+ .mac_setup = mt7531_mac_setup, -+ .port_an_restart = mt7531_sgmii_restart_an, -+ }, - }; - - static const struct of_device_id mt7530_of_match[] = { - { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, - { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, -+ { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, - { /* sentinel */ }, - }; - MODULE_DEVICE_TABLE(of, mt7530_of_match); ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -14,6 +14,7 @@ - enum mt753x_id { - ID_MT7530 = 0, - ID_MT7621 = 1, -+ ID_MT7531 = 2, - }; - - #define NUM_TRGMII_CTRL 5 -@@ -222,6 +223,19 @@ enum mt7530_vlan_port_attr { - #define PMCR_FORCE_LNK BIT(0) - #define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \ - PMCR_FORCE_SPEED_1000) -+#define MT7531_FORCE_LNK BIT(31) -+#define MT7531_FORCE_SPD BIT(30) -+#define MT7531_FORCE_DPX BIT(29) -+#define MT7531_FORCE_RX_FC BIT(28) -+#define MT7531_FORCE_TX_FC BIT(27) -+#define MT7531_FORCE_MODE (MT7531_FORCE_LNK | \ -+ MT7531_FORCE_SPD | \ -+ MT7531_FORCE_DPX | \ -+ MT7531_FORCE_RX_FC | \ -+ MT7531_FORCE_TX_FC) -+#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \ -+ MT7531_FORCE_MODE : \ -+ PMCR_FORCE_MODE) - - #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) - #define PMSR_EEE1G BIT(7) -@@ -258,12 +272,111 @@ enum mt7530_vlan_port_attr { - CCR_RX_OCT_CNT_BAD | \ - CCR_TX_OCT_CNT_GOOD | \ - CCR_TX_OCT_CNT_BAD) -+ -+/* SGMII registers */ -+#define MT7531_SGMII_REG_BASE 0x5000 -+#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \ -+ ((p) - 5) * 0x1000 + (r)) -+ -+/* SGMII PCS_CONTROL_1 */ -+#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00) -+#define MT7531_SGMII_LINK_STATUS BIT(18) -+#define MT7531_SGMII_AN_ENABLE BIT(12) -+#define MT7531_SGMII_AN_RESTART BIT(9) -+ -+/* Fields of SGMII_MODE */ -+#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20) -+#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8) -+#define MT7531_SGMII_FORCE_DUPLEX BIT(4) -+#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1) -+#define MT7531_SGMII_FORCE_SPEED_10 0x0 -+#define MT7531_SGMII_FORCE_SPEED_100 BIT(2) -+#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3) -+ -+/* Fields of QPHY_PWR_STATE_CTRL */ -+#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8) -+#define MT7531_SGMII_PHYA_PWD BIT(4) -+ -+/* Values of SGMII SPEED */ -+#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128) -+#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3)) -+#define MT7531_RG_TPHY_SPEED_1_25G 0x0 -+#define MT7531_RG_TPHY_SPEED_3_125G BIT(2) -+ - /* Register for system reset */ - #define MT7530_SYS_CTRL 0x7000 - #define SYS_CTRL_PHY_RST BIT(2) - #define SYS_CTRL_SW_RST BIT(1) - #define SYS_CTRL_REG_RST BIT(0) - -+/* Register for PHY Indirect Access Control */ -+#define MT7531_PHY_IAC 0x701C -+#define PHY_ACS_ST BIT(31) -+#define MDIO_REG_ADDR_MASK (0x1f << 25) -+#define MDIO_PHY_ADDR_MASK (0x1f << 20) -+#define MDIO_CMD_MASK (0x3 << 18) -+#define MDIO_ST_MASK (0x3 << 16) -+#define MDIO_RW_DATA_MASK (0xffff) -+#define MDIO_REG_ADDR(x) (((x) & 0x1f) << 25) -+#define MDIO_DEV_ADDR(x) (((x) & 0x1f) << 25) -+#define MDIO_PHY_ADDR(x) (((x) & 0x1f) << 20) -+#define MDIO_CMD(x) (((x) & 0x3) << 18) -+#define MDIO_ST(x) (((x) & 0x3) << 16) -+ -+enum mt7531_phy_iac_cmd { -+ MT7531_MDIO_ADDR = 0, -+ MT7531_MDIO_WRITE = 1, -+ MT7531_MDIO_READ = 2, -+ MT7531_MDIO_READ_CL45 = 3, -+}; -+ -+/* MDIO_ST: MDIO start field */ -+enum mt7531_mdio_st { -+ MT7531_MDIO_ST_CL45 = 0, -+ MT7531_MDIO_ST_CL22 = 1, -+}; -+ -+#define MDIO_CL22_READ (MDIO_ST(MT7531_MDIO_ST_CL22) | \ -+ MDIO_CMD(MT7531_MDIO_READ)) -+#define MDIO_CL22_WRITE (MDIO_ST(MT7531_MDIO_ST_CL22) | \ -+ MDIO_CMD(MT7531_MDIO_WRITE)) -+#define MDIO_CL45_ADDR (MDIO_ST(MT7531_MDIO_ST_CL45) | \ -+ MDIO_CMD(MT7531_MDIO_ADDR)) -+#define MDIO_CL45_READ (MDIO_ST(MT7531_MDIO_ST_CL45) | \ -+ MDIO_CMD(MT7531_MDIO_READ)) -+#define MDIO_CL45_WRITE (MDIO_ST(MT7531_MDIO_ST_CL45) | \ -+ MDIO_CMD(MT7531_MDIO_WRITE)) -+ -+#define MT7531_CLKGEN_CTRL 0x7500 -+#define CLK_SKEW_OUT(x) (((x) & 0x3) << 8) -+#define CLK_SKEW_OUT_MASK (0x3 << 8) -+#define CLK_SKEW_IN(x) (((x) & 0x3) << 6) -+#define CLK_SKEW_IN_MASK (0x3 << 6) -+#define RXCLK_NO_DELAY BIT(5) -+#define TXCLK_NO_REVERSE BIT(4) -+#define GP_MODE(x) (((x) & 0x3) << 1) -+#define GP_MODE_MASK (0x3 << 1) -+#define GP_CLK_EN BIT(0) -+ -+#define PHY_DEV1F 0x1f -+#define MT7531_PHY_DEV1F_REG_403 0x403 -+ -+#define MT7531_PHY_EN_BYPASS_MODE BIT(4) -+#define MT7531_PHY_POWER_OFF BIT(5) -+ -+enum mt7531_gp_mode { -+ MT7531_GP_MODE_RGMII = 0, -+ MT7531_GP_MODE_MII = 1, -+ MT7531_GP_MODE_REV_MII = 2 -+}; -+ -+enum mt7531_clk_skew { -+ MT7531_CLK_SKEW_NO_CHG = 0, -+ MT7531_CLK_SKEW_DLY_100PPS = 1, -+ MT7531_CLK_SKEW_DLY_200PPS = 2, -+ MT7531_CLK_SKEW_REVERSE = 3, -+}; -+ - /* Register for hw trap status */ - #define MT7530_HWTRAP 0x7800 - #define HWTRAP_XTAL_MASK (BIT(10) | BIT(9)) -@@ -271,6 +384,11 @@ enum mt7530_vlan_port_attr { - #define HWTRAP_XTAL_40MHZ (BIT(10)) - #define HWTRAP_XTAL_20MHZ (BIT(9)) - -+#define MT7531_HWTRAP 0x7800 -+#define HWTRAP_XTAL_FSEL_MASK BIT(7) -+#define HWTRAP_XTAL_FSEL_25MHZ BIT(7) -+#define HWTRAP_XTAL_FSEL_40MHZ 0 -+ - /* Register for hw trap modification */ - #define MT7530_MHWTRAP 0x7804 - #define MHWTRAP_PHY0_SEL BIT(20) -@@ -285,14 +403,34 @@ enum mt7530_vlan_port_attr { - #define MT7530_TOP_SIG_CTRL 0x7808 - #define TOP_SIG_CTRL_NORMAL (BIT(17) | BIT(16)) - -+#define MT7531_TOP_SIG_SR 0x780c -+#define PAD_DUAL_SGMII_EN BIT(1) -+ - #define MT7530_IO_DRV_CR 0x7810 - #define P5_IO_CLK_DRV(x) ((x) & 0x3) - #define P5_IO_DATA_DRV(x) (((x) & 0x3) << 4) - -+#define MT7531_PLLGP_EN 0x7820 -+#define EN_COREPLL BIT(2) -+#define SW_CLKSW BIT(1) -+#define SW_PLLGP BIT(0) -+ -+#define MT7531_PLLGP_CR0 0x78a8 -+#define RG_COREPLL_EN BIT(22) -+#define RG_COREPLL_POSDIV_S 23 -+#define RG_COREPLL_POSDIV_M 0x3800000 -+#define RG_COREPLL_SDM_PCW_S 1 -+#define RG_COREPLL_SDM_PCW_M 0x3ffffe -+#define RG_COREPLL_SDM_PCW_CHG BIT(0) -+ - #define MT7530_P6ECR 0x7830 - #define P6_INTF_MODE_MASK 0x3 - #define P6_INTF_MODE(x) ((x) & 0x3) - -+/* RGMII and SGMII PLL clock */ -+#define MT7531_ANA_PLLGP_CR2 0x78b0 -+#define MT7531_ANA_PLLGP_CR5 0x78bc -+ - /* Registers for TRGMII on the both side */ - #define MT7530_TRGMII_RCK_CTRL 0x7a00 - #define RX_RST BIT(31) -@@ -335,6 +473,9 @@ enum mt7530_vlan_port_attr { - #define CHIP_NAME_SHIFT 16 - #define MT7530_ID 0x7530 - -+#define MT7531_CREV 0x781C -+#define MT7531_ID 0x7531 -+ - /* Registers for core PLL access through mmd indirect */ - #define CORE_PLL_GROUP2 0x401 - #define RG_SYSPLL_EN_NORMAL BIT(15) -@@ -458,6 +599,8 @@ static const char *p5_intf_modes(unsigne - * port - * @mac_setup: Holding the way setting up the PHY attribute for a - * certain MAC port -+ * @port_an_restart Holding the way restarting 802.3z BaseX autonegotiation -+ * for a certain MAC port - */ - struct mt753x_info { - enum mt753x_id id; -@@ -471,6 +614,7 @@ struct mt753x_info { - const struct phylink_link_state *state); - int (*mac_setup)(struct dsa_switch *ds, int port, unsigned int mode, - const struct phylink_link_state *state); -+ void (*port_an_restart)(struct dsa_switch *ds, int port); - }; - - /* struct mt7530_priv - This is the main data structure for holding the state diff --git a/target/linux/mediatek/patches-5.4/0600-6-6-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch b/target/linux/mediatek/patches-5.4/0600-6-6-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch deleted file mode 100644 index 8919ad27e0..0000000000 --- a/target/linux/mediatek/patches-5.4/0600-6-6-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch +++ /dev/null @@ -1,138 +0,0 @@ -From patchwork Tue Dec 10 08:14:42 2019 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Landen Chao -X-Patchwork-Id: 1206964 -X-Patchwork-Delegate: davem@davemloft.net -Return-Path: -X-Original-To: patchwork-incoming-netdev@ozlabs.org -Delivered-To: patchwork-incoming-netdev@ozlabs.org -Authentication-Results: ozlabs.org; spf=none (no SPF record) - smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; - helo=vger.kernel.org; - envelope-from=netdev-owner@vger.kernel.org; - receiver=) -Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) - header.from=mediatek.com -Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; - unprotected) header.d=mediatek.com header.i=@mediatek.com - header.b="eagJVm76"; dkim-atps=neutral -Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) - by ozlabs.org (Postfix) with ESMTP id 47XCYF2fNjz9sR7 - for ; - Tue, 10 Dec 2019 19:15:29 +1100 (AEDT) -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1727295AbfLJIP0 (ORCPT - ); - Tue, 10 Dec 2019 03:15:26 -0500 -Received: from mailgw01.mediatek.com ([210.61.82.183]:21469 "EHLO - mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by - vger.kernel.org with ESMTP id S1726062AbfLJIO4 (ORCPT - ); Tue, 10 Dec 2019 03:14:56 -0500 -X-UUID: f9b456136baf42daba0957485d388010-20191210 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=BT+q/z4xoeKXCk+y25bvARvW/z0vRa1uB7kHqAjvpaw=; - b=eagJVm76XNgnVVvxDHR4QtcIyynPPYY4k7twyvlRAQeSnsJbABh1afLK+LlxnJ0TM069F+hNNzWXq7ZGru/I+gYhmqZcYCt/SkEYgxdTb0VNE+DIW0hmNAOoJ0i23gobJ3xa7JVRfIfeZcbjwRJSuqwzLBRZBLIFzqSs71VZx1Y=; -X-UUID: f9b456136baf42daba0957485d388010-20191210 -Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by - mailgw01.mediatek.com (envelope-from ) - (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) - with ESMTP id 1831961689; Tue, 10 Dec 2019 16:14:48 +0800 -Received: from mtkcas08.mediatek.inc (172.21.101.126) by - mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server - (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:32 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via - Frontend Transport; Tue, 10 Dec 2019 16:14:27 +0800 -From: Landen Chao -To: , , - , , - , -CC: , , - , - , , - , , - , Landen Chao -Subject: [PATCH net-next 6/6] arm64: dts: mt7622: add mt7531 dsa to - bananapi-bpi-r64 board -Date: Tue, 10 Dec 2019 16:14:42 +0800 -Message-ID: <62eef5503c117f48d4b41e94fd28d75e123590b4.1575914275.git.landen.chao@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: -References: -MIME-Version: 1.0 -X-MTK: N -Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org - -Add mt7531 dsa to bananapi-bpi-r64 board for 5 giga Ethernet ports support. - -Signed-off-by: Landen Chao ---- - .../dts/mediatek/mt7622-bananapi-bpi-r64.dts | 50 +++++++++++++++++++ - 1 file changed, 50 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -150,6 +150,56 @@ - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; -+ -+ switch@0 { -+ compatible = "mediatek,mt7531"; -+ reg = <0>; -+ reset-gpios = <&pio 54 0>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ label = "wan"; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ label = "lan0"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ label = "lan1"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ label = "lan2"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ label = "lan3"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ label = "cpu"; -+ ethernet = <&gmac0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ }; -+ }; -+ - }; - }; - diff --git a/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch b/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch new file mode 100644 index 0000000000..34a15334d6 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch @@ -0,0 +1,246 @@ +From: Russell King +Date: Wed, 26 Feb 2020 10:23:41 +0000 +Subject: [PATCH] net: phylink: propagate resolved link config via + mac_link_up() + +Propagate the resolved link parameters via the mac_link_up() call for +MACs that do not automatically track their PCS state. We propagate the +link parameters via function arguments so that inappropriate members +of struct phylink_link_state can't be accessed, and creating a new +structure just for this adds needless complexity to the API. + +Tested-by: Andre Przywara +Tested-by: Alexandre Belloni +Tested-by: Vladimir Oltean +Signed-off-by: Russell King +Signed-off-by: David S. Miller +--- + +--- a/Documentation/networking/sfp-phylink.rst ++++ b/Documentation/networking/sfp-phylink.rst +@@ -74,10 +74,13 @@ phylib to the sfp/phylink support. Plea + this documentation. + + 1. Optionally split the network driver's phylib update function into +- three parts dealing with link-down, link-up and reconfiguring the +- MAC settings. This can be done as a separate preparation commit. ++ two parts dealing with link-down and link-up. This can be done as ++ a separate preparation commit. + +- An example of this preparation can be found in git commit fc548b991fb0. ++ An older example of this preparation can be found in git commit ++ fc548b991fb0, although this was splitting into three parts; the ++ link-up part now includes configuring the MAC for the link settings. ++ Please see :c:func:`mac_link_up` for more information on this. + + 2. Replace:: + +@@ -207,6 +210,14 @@ this documentation. + using. This is particularly important for in-band negotiation + methods such as 1000base-X and SGMII. + ++ The :c:func:`mac_link_up` method is used to inform the MAC that the ++ link has come up. The call includes the negotiation mode and interface ++ for reference only. The finalised link parameters are also supplied ++ (speed, duplex and flow control/pause enablement settings) which ++ should be used to configure the MAC when the MAC and PCS are not ++ tightly integrated, or when the settings are not coming from in-band ++ negotiation. ++ + The :c:func:`mac_config` method is used to update the MAC with the + requested state, and must avoid unnecessarily taking the link down + when making changes to the MAC configuration. This means the +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -3653,9 +3653,11 @@ static void mvneta_mac_link_down(struct + mvneta_set_eee(pp, false); + } + +-static void mvneta_mac_link_up(struct phylink_config *config, unsigned int mode, +- phy_interface_t interface, +- struct phy_device *phy) ++static void mvneta_mac_link_up(struct phylink_config *config, ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + struct net_device *ndev = to_net_dev(config->dev); + struct mvneta_port *pp = netdev_priv(ndev); +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -58,8 +58,11 @@ static struct { + */ + static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state); +-static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode, +- phy_interface_t interface, struct phy_device *phy); ++static void mvpp2_mac_link_up(struct phylink_config *config, ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause); + + /* Queue modes */ + #define MVPP2_QDIST_SINGLE_MODE 0 +@@ -3467,8 +3470,9 @@ static void mvpp2_start_dev(struct mvpp2 + .interface = port->phy_interface, + }; + mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state); +- mvpp2_mac_link_up(&port->phylink_config, MLO_AN_INBAND, +- port->phy_interface, NULL); ++ mvpp2_mac_link_up(&port->phylink_config, NULL, ++ MLO_AN_INBAND, port->phy_interface, ++ SPEED_UNKNOWN, DUPLEX_UNKNOWN, false, false); + } + + netif_tx_start_all_queues(port->dev); +@@ -5124,8 +5128,11 @@ static void mvpp2_mac_config(struct phyl + mvpp2_port_enable(port); + } + +-static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode, +- phy_interface_t interface, struct phy_device *phy) ++static void mvpp2_mac_link_up(struct phylink_config *config, ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + struct net_device *dev = to_net_dev(config->dev); + struct mvpp2_port *port = netdev_priv(dev); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -445,9 +445,10 @@ static void mtk_mac_link_down(struct phy + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + +-static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode, +- phy_interface_t interface, +- struct phy_device *phy) ++static void mtk_mac_link_up(struct phylink_config *config, ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) + { + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -951,8 +951,10 @@ static void stmmac_mac_link_down(struct + } + + static void stmmac_mac_link_up(struct phylink_config *config, ++ struct phy_device *phy, + unsigned int mode, phy_interface_t interface, +- struct phy_device *phy) ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); + +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1488,9 +1488,10 @@ static void axienet_mac_link_down(struct + } + + static void axienet_mac_link_up(struct phylink_config *config, +- unsigned int mode, +- phy_interface_t interface, +- struct phy_device *phy) ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + /* nothing meaningful to do */ + } +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -447,8 +447,11 @@ static void phylink_mac_link_up(struct p + struct net_device *ndev = pl->netdev; + + pl->cur_interface = link_state.interface; +- pl->ops->mac_link_up(pl->config, pl->cur_link_an_mode, +- pl->cur_interface, pl->phydev); ++ pl->ops->mac_link_up(pl->config, pl->phydev, ++ pl->cur_link_an_mode, pl->cur_interface, ++ link_state.speed, link_state.duplex, ++ !!(link_state.pause & MLO_PAUSE_TX), ++ !!(link_state.pause & MLO_PAUSE_RX)); + + if (ndev) + netif_carrier_on(ndev); +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -91,9 +91,10 @@ struct phylink_mac_ops { + void (*mac_an_restart)(struct phylink_config *config); + void (*mac_link_down)(struct phylink_config *config, unsigned int mode, + phy_interface_t interface); +- void (*mac_link_up)(struct phylink_config *config, unsigned int mode, +- phy_interface_t interface, +- struct phy_device *phy); ++ void (*mac_link_up)(struct phylink_config *config, ++ struct phy_device *phy, unsigned int mode, ++ phy_interface_t interface, int speed, int duplex, ++ bool tx_pause, bool rx_pause); + }; + + #if 0 /* For kernel-doc purposes only. */ +@@ -217,19 +218,34 @@ void mac_link_down(struct phylink_config + /** + * mac_link_up() - allow the link to come up + * @config: a pointer to a &struct phylink_config. ++ * @phy: any attached phy + * @mode: link autonegotiation mode + * @interface: link &typedef phy_interface_t mode +- * @phy: any attached phy ++ * @speed: link speed ++ * @duplex: link duplex ++ * @tx_pause: link transmit pause enablement status ++ * @rx_pause: link receive pause enablement status + * +- * If @mode is not an in-band negotiation mode (as defined by +- * phylink_autoneg_inband()), allow the link to come up. If @phy +- * is non-%NULL, configure Energy Efficient Ethernet by calling ++ * Configure the MAC for an established link. ++ * ++ * @speed, @duplex, @tx_pause and @rx_pause indicate the finalised link ++ * settings, and should be used to configure the MAC block appropriately ++ * where these settings are not automatically conveyed from the PCS block, ++ * or if in-band negotiation (as defined by phylink_autoneg_inband(@mode)) ++ * is disabled. ++ * ++ * Note that when 802.3z in-band negotiation is in use, it is possible ++ * that the user wishes to override the pause settings, and this should ++ * be allowed when considering the implementation of this method. ++ * ++ * If in-band negotiation mode is disabled, allow the link to come up. If ++ * @phy is non-%NULL, configure Energy Efficient Ethernet by calling + * phy_init_eee() and perform appropriate MAC configuration for EEE. + * Interface type selection must be done in mac_config(). + */ +-void mac_link_up(struct phylink_config *config, unsigned int mode, +- phy_interface_t interface, +- struct phy_device *phy); ++void mac_link_up(struct phylink_config *config, struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause); + #endif + + struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -529,9 +529,11 @@ void dsa_port_phylink_mac_link_down(stru + EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_link_down); + + void dsa_port_phylink_mac_link_up(struct phylink_config *config, ++ struct phy_device *phydev, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev) ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); + struct dsa_switch *ds = dp->ds; diff --git a/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch b/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch new file mode 100644 index 0000000000..f74bc30d9e --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch @@ -0,0 +1,143 @@ +From: Russell King +Date: Wed, 26 Feb 2020 10:23:46 +0000 +Subject: [PATCH] net: dsa: propagate resolved link config via mac_link_up() + +Propagate the resolved link configuration down via DSA's +phylink_mac_link_up() operation to allow split PCS/MAC to work. + +Tested-by: Vladimir Oltean +Signed-off-by: Russell King +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1276,7 +1276,9 @@ EXPORT_SYMBOL(b53_phylink_mac_link_down) + void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev) ++ struct phy_device *phydev, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + struct b53_device *dev = ds->priv; + +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -337,7 +337,9 @@ void b53_phylink_mac_link_down(struct ds + void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev); ++ struct phy_device *phydev, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause); + int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering); + int b53_vlan_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan); +--- a/drivers/net/dsa/bcm_sf2.c ++++ b/drivers/net/dsa/bcm_sf2.c +@@ -635,7 +635,9 @@ static void bcm_sf2_sw_mac_link_down(str + static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev) ++ struct phy_device *phydev, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); + struct ethtool_eee *p = &priv->dev->ports[port].eee; +--- a/drivers/net/dsa/lantiq_gswip.c ++++ b/drivers/net/dsa/lantiq_gswip.c +@@ -1517,7 +1517,9 @@ static void gswip_phylink_mac_link_down( + static void gswip_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev) ++ struct phy_device *phydev, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + struct gswip_priv *priv = ds->priv; + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1452,7 +1452,9 @@ static void mt7530_phylink_mac_link_down + static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev) ++ struct phy_device *phydev, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + struct mt7530_priv *priv = ds->priv; + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -652,7 +652,9 @@ static void mv88e6xxx_mac_link_down(stru + + static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface, +- struct phy_device *phydev) ++ struct phy_device *phydev, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + if (mode == MLO_AN_FIXED) + mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP); +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -830,7 +830,9 @@ static void sja1105_mac_link_down(struct + static void sja1105_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev) ++ struct phy_device *phydev, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause) + { + sja1105_inhibit_tx(ds->priv, BIT(port), false); + } +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -401,7 +401,9 @@ struct dsa_switch_ops { + void (*phylink_mac_link_up)(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev); ++ struct phy_device *phydev, ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause); + void (*phylink_fixed_state)(struct dsa_switch *ds, int port, + struct phylink_link_state *state); + /* +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -544,7 +544,8 @@ void dsa_port_phylink_mac_link_up(struct + return; + } + +- ds->ops->phylink_mac_link_up(ds, dp->index, mode, interface, phydev); ++ ds->ops->phylink_mac_link_up(ds, dp->index, mode, interface, phydev, ++ speed, duplex, tx_pause, rx_pause); + } + EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_link_up); + +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -180,9 +180,11 @@ void dsa_port_phylink_mac_link_down(stru + unsigned int mode, + phy_interface_t interface); + void dsa_port_phylink_mac_link_up(struct phylink_config *config, ++ struct phy_device *phydev, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev); ++ int speed, int duplex, ++ bool tx_pause, bool rx_pause); + extern const struct phylink_mac_ops dsa_port_phylink_mac_ops; + + /* slave.c */ diff --git a/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch b/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch new file mode 100644 index 0000000000..30ce641486 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch @@ -0,0 +1,145 @@ +From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= +Date: Fri, 27 Mar 2020 15:44:12 +0100 +Subject: [PATCH] net: dsa: mt7530: use resolved link config in mac_link_up() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Convert the mt7530 switch driver to use the finalised link +parameters in mac_link_up() rather than the parameters in mac_config(). + +Signed-off-by: René van Dorst +Tested-by: Sean Wang +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -490,17 +490,6 @@ mt7530_mib_reset(struct dsa_switch *ds) + mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE); + } + +-static void +-mt7530_port_set_status(struct mt7530_priv *priv, int port, int enable) +-{ +- u32 mask = PMCR_TX_EN | PMCR_RX_EN | PMCR_FORCE_LNK; +- +- if (enable) +- mt7530_set(priv, MT7530_PMCR_P(port), mask); +- else +- mt7530_clear(priv, MT7530_PMCR_P(port), mask); +-} +- + static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum) + { + struct mt7530_priv *priv = ds->priv; +@@ -674,7 +663,7 @@ mt7530_port_enable(struct dsa_switch *ds + priv->ports[port].enable = true; + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, + priv->ports[port].pm); +- mt7530_port_set_status(priv, port, 0); ++ mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + + mutex_unlock(&priv->reg_mutex); + +@@ -697,7 +686,7 @@ mt7530_port_disable(struct dsa_switch *d + priv->ports[port].enable = false; + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, + PCR_MATRIX_CLR); +- mt7530_port_set_status(priv, port, 0); ++ mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + + mutex_unlock(&priv->reg_mutex); + } +@@ -1407,8 +1396,7 @@ static void mt7530_phylink_mac_config(st + + mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port)); + mcr_new = mcr_cur; +- mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 | +- PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN); ++ mcr_new &= ~PMCR_LINK_SETTINGS_MASK; + mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | + PMCR_BACKPR_EN | PMCR_FORCE_MODE; + +@@ -1416,26 +1404,6 @@ static void mt7530_phylink_mac_config(st + if (port == 5 && dsa_is_user_port(ds, 5)) + mcr_new |= PMCR_EXT_PHY; + +- switch (state->speed) { +- case SPEED_1000: +- mcr_new |= PMCR_FORCE_SPEED_1000; +- if (priv->eee_enable & BIT(port)) +- mcr_new |= PMCR_FORCE_EEE1G; +- break; +- case SPEED_100: +- mcr_new |= PMCR_FORCE_SPEED_100; +- if (priv->eee_enable & BIT(port)) +- mcr_new |= PMCR_FORCE_EEE100; +- break; +- } +- if (state->duplex == DUPLEX_FULL) { +- mcr_new |= PMCR_FORCE_FDX; +- if (state->pause & MLO_PAUSE_TX) +- mcr_new |= PMCR_TX_FC_EN; +- if (state->pause & MLO_PAUSE_RX) +- mcr_new |= PMCR_RX_FC_EN; +- } +- + if (mcr_new != mcr_cur) + mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); + } +@@ -1446,7 +1414,7 @@ static void mt7530_phylink_mac_link_down + { + struct mt7530_priv *priv = ds->priv; + +- mt7530_port_set_status(priv, port, 0); ++ mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + } + + static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port, +@@ -1457,8 +1425,31 @@ static void mt7530_phylink_mac_link_up(s + bool tx_pause, bool rx_pause) + { + struct mt7530_priv *priv = ds->priv; ++ u32 mcr; + +- mt7530_port_set_status(priv, port, 1); ++ mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; ++ ++ switch (speed) { ++ case SPEED_1000: ++ mcr |= PMCR_FORCE_SPEED_1000; ++ if (priv->eee_enable & BIT(port)) ++ mcr_new |= PMCR_FORCE_EEE1G; ++ break; ++ case SPEED_100: ++ mcr |= PMCR_FORCE_SPEED_100; ++ if (priv->eee_enable & BIT(port)) ++ mcr_new |= 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; ++ } ++ ++ mt7530_set(priv, MT7530_PMCR_P(port), mcr); + } + + static void mt7530_phylink_validate(struct dsa_switch *ds, int port, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -222,6 +222,10 @@ enum mt7530_vlan_port_attr { + #define PMCR_FORCE_LNK BIT(0) + #define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \ + PMCR_FORCE_SPEED_1000) ++#define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ ++ PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ ++ PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ ++ PMCR_FORCE_FDX | PMCR_FORCE_LNK) + + #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) + #define PMSR_EEE1G BIT(7) diff --git a/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch b/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch new file mode 100644 index 0000000000..5ae3376290 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch @@ -0,0 +1,458 @@ +From: Landen Chao +Date: Fri, 4 Sep 2020 22:21:57 +0800 +Subject: [PATCH] net: dsa: mt7530: Extend device data ready for adding a + new hardware + +Add a structure holding required operations for each device such as device +initialization, PHY port read or write, a checker whether PHY interface is +supported on a certain port, MAC port setup for either bus pad or a +specific PHY interface. + +The patch is done for ready adding a new hardware MT7531, and keep the +same setup logic of existing hardware. + +Signed-off-by: Landen Chao +Signed-off-by: Sean Wang +--- + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -372,8 +372,9 @@ mt7530_fdb_write(struct mt7530_priv *pri + mt7530_write(priv, MT7530_ATA1 + (i * 4), reg[i]); + } + ++/* Setup TX circuit including relevant PAD and driving */ + static int +-mt7530_pad_clk_setup(struct dsa_switch *ds, int mode) ++mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) + { + struct mt7530_priv *priv = ds->priv; + u32 ncpo1, ssc_delta, trgint, i, xtal; +@@ -387,7 +388,7 @@ mt7530_pad_clk_setup(struct dsa_switch * + return -EINVAL; + } + +- switch (mode) { ++ switch (interface) { + case PHY_INTERFACE_MODE_RGMII: + trgint = 0; + /* PLL frequency: 125MHz */ +@@ -409,7 +410,8 @@ mt7530_pad_clk_setup(struct dsa_switch * + } + break; + default: +- dev_err(priv->dev, "xMII mode %d not supported\n", mode); ++ dev_err(priv->dev, "xMII interface %d not supported\n", ++ interface); + return -EINVAL; + } + +@@ -1344,12 +1346,11 @@ mt7530_setup(struct dsa_switch *ds) + return 0; + } + +-static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port, +- unsigned int mode, +- const struct phylink_link_state *state) ++static bool ++mt7530_phy_mode_supported(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state) + { + struct mt7530_priv *priv = ds->priv; +- u32 mcr_cur, mcr_new; + + switch (port) { + case 0: /* Internal phy */ +@@ -1358,33 +1359,114 @@ static void mt7530_phylink_mac_config(st + case 3: + case 4: + if (state->interface != PHY_INTERFACE_MODE_GMII) +- return; ++ goto unsupported; + break; + case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ +- if (priv->p5_interface == state->interface) +- break; + if (!phy_interface_mode_is_rgmii(state->interface) && + state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_GMII) +- return; ++ goto unsupported; ++ break; ++ case 6: /* 1st cpu port */ ++ if (state->interface != PHY_INTERFACE_MODE_RGMII && ++ state->interface != PHY_INTERFACE_MODE_TRGMII) ++ goto unsupported; ++ break; ++ default: ++ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, ++ port); ++ goto unsupported; ++ } ++ ++ return true; ++ ++unsupported: ++ return false; ++} ++ ++static bool ++mt753x_phy_mode_supported(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_mode_supported(ds, port, state); ++} ++ ++static int ++mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->pad_setup(ds, state->interface); ++} ++ ++static int ++mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ /* Only need to setup port5. */ ++ if (port != 5) ++ return 0; ++ ++ mt7530_setup_port5(priv->ds, interface); ++ ++ return 0; ++} ++ ++static int ++mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->mac_port_config(ds, port, mode, state->interface); ++} ++ ++static void ++mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 mcr_cur, mcr_new; ++ ++ if (!mt753x_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: /* 2nd cpu port with phy of port 0 or 4 / external phy */ ++ if (priv->p5_interface == state->interface) ++ break; ++ ++ if (mt753x_mac_config(ds, port, mode, state) < 0) ++ goto unsupported; + +- mt7530_setup_port5(ds, state->interface); + break; + case 6: /* 1st cpu port */ + if (priv->p6_interface == state->interface) + break; + +- if (state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_TRGMII) +- return; ++ mt753x_pad_setup(ds, state); + +- /* Setup TX circuit incluing relevant PAD and driving */ +- mt7530_pad_clk_setup(ds, state->interface); ++ if (mt753x_mac_config(ds, port, mode, state) < 0) ++ goto unsupported; + + priv->p6_interface = state->interface; + break; + default: +- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); ++unsupported: ++ dev_err(ds->dev, "%s: unsupported %s port: %i\n", ++ __func__, phy_modes(state->interface), port); + return; + } + +@@ -1452,61 +1534,44 @@ static void mt7530_phylink_mac_link_up(s + mt7530_set(priv, MT7530_PMCR_P(port), mcr); + } + +-static void mt7530_phylink_validate(struct dsa_switch *ds, int port, +- unsigned long *supported, +- struct phylink_link_state *state) ++static void ++mt7530_mac_port_validate(struct dsa_switch *ds, int port, ++ unsigned long *supported) + { ++ if (port == 5) ++ phylink_set(supported, 1000baseX_Full); ++} ++ ++static void ++mt753x_phylink_validate(struct dsa_switch *ds, int port, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + +- switch (port) { +- case 0: /* Internal phy */ +- case 1: +- case 2: +- case 3: +- case 4: +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_GMII) +- goto unsupported; +- break; +- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ +- if (state->interface != PHY_INTERFACE_MODE_NA && +- !phy_interface_mode_is_rgmii(state->interface) && +- state->interface != PHY_INTERFACE_MODE_MII && +- state->interface != PHY_INTERFACE_MODE_GMII) +- goto unsupported; +- break; +- case 6: /* 1st cpu port */ +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_TRGMII) +- goto unsupported; +- break; +- default: +- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); +-unsupported: ++ if (state->interface != PHY_INTERFACE_MODE_NA && ++ !mt753x_phy_mode_supported(ds, port, state)) { + linkmode_zero(supported); + return; + } + + phylink_set_port_modes(mask); +- phylink_set(mask, Autoneg); + +- if (state->interface == PHY_INTERFACE_MODE_TRGMII) { +- phylink_set(mask, 1000baseT_Full); +- } else { ++ if (state->interface != PHY_INTERFACE_MODE_TRGMII) { + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); +- +- if (state->interface != PHY_INTERFACE_MODE_MII) { +- phylink_set(mask, 1000baseT_Half); +- phylink_set(mask, 1000baseT_Full); +- if (port == 5) +- phylink_set(mask, 1000baseX_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); + +@@ -1602,12 +1667,45 @@ static int mt7530_set_mac_eee(struct dsa + return 0; + } + ++static int ++mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port, ++ struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->mac_port_get_state(ds, port, state); ++} ++ ++static int ++mt753x_setup(struct dsa_switch *ds) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->sw_setup(ds); ++} ++ ++static int ++mt753x_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_read(ds, port, regnum); ++} ++ ++static int ++mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_write(ds, port, regnum, val); ++} ++ + static const struct dsa_switch_ops mt7530_switch_ops = { + .get_tag_protocol = mtk_get_tag_protocol, +- .setup = mt7530_setup, ++ .setup = mt753x_setup, + .get_strings = mt7530_get_strings, +- .phy_read = mt7530_phy_read, +- .phy_write = mt7530_phy_write, ++ .phy_read = mt753x_phy_read, ++ .phy_write = mt753x_phy_write, + .get_ethtool_stats = mt7530_get_ethtool_stats, + .get_sset_count = mt7530_get_sset_count, + .port_enable = mt7530_port_enable, +@@ -1624,18 +1722,43 @@ static const struct dsa_switch_ops mt753 + .port_vlan_del = mt7530_port_vlan_del, + .port_mirror_add = mt7530_port_mirror_add, + .port_mirror_del = mt7530_port_mirror_del, +- .phylink_validate = mt7530_phylink_validate, +- .phylink_mac_link_state = mt7530_phylink_mac_link_state, +- .phylink_mac_config = mt7530_phylink_mac_config, ++ .phylink_validate = mt753x_phylink_validate, ++ .phylink_mac_link_state = mt753x_phylink_mac_link_state, ++ .phylink_mac_config = mt753x_phylink_mac_config, + .phylink_mac_link_down = mt7530_phylink_mac_link_down, + .phylink_mac_link_up = mt7530_phylink_mac_link_up, + .get_mac_eee = mt7530_get_mac_eee, + .set_mac_eee = mt7530_set_mac_eee, + }; + ++static const struct mt753x_info mt753x_table[] = { ++ [ID_MT7621] = { ++ .id = ID_MT7621, ++ .sw_setup = mt7530_setup, ++ .phy_read = mt7530_phy_read, ++ .phy_write = mt7530_phy_write, ++ .pad_setup = mt7530_pad_clk_setup, ++ .phy_mode_supported = mt7530_phy_mode_supported, ++ .mac_port_validate = mt7530_mac_port_validate, ++ .mac_port_get_state = mt7530_phylink_mac_link_state, ++ .mac_port_config = mt7530_mac_config, ++ }, ++ [ID_MT7530] = { ++ .id = ID_MT7530, ++ .sw_setup = mt7530_setup, ++ .phy_read = mt7530_phy_read, ++ .phy_write = mt7530_phy_write, ++ .pad_setup = mt7530_pad_clk_setup, ++ .phy_mode_supported = mt7530_phy_mode_supported, ++ .mac_port_validate = mt7530_mac_port_validate, ++ .mac_port_get_state = mt7530_phylink_mac_link_state, ++ .mac_port_config = mt7530_mac_config, ++ }, ++}; ++ + static const struct of_device_id mt7530_of_match[] = { +- { .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, }, +- { .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, }, ++ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, ++ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, mt7530_of_match); +@@ -1673,8 +1796,21 @@ mt7530_probe(struct mdio_device *mdiodev + /* Get the hardware identifier from the devicetree node. + * We will need it for some of the clock and regulator setup. + */ +- priv->id = (unsigned int)(unsigned long) +- of_device_get_match_data(&mdiodev->dev); ++ 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; ++ ++ priv->id = priv->info->id; + + if (priv->id == ID_MT7530) { + priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -11,7 +11,7 @@ + #define MT7530_NUM_FDB_RECORDS 2048 + #define MT7530_ALL_MEMBERS 0xff + +-enum { ++enum mt753x_id { + ID_MT7530 = 0, + ID_MT7621 = 1, + }; +@@ -451,6 +451,40 @@ static const char *p5_intf_modes(unsigne + } + } + ++/* struct mt753x_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 ++ */ ++struct mt753x_info { ++ enum mt753x_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); ++ 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); ++}; ++ + /* struct mt7530_priv - This is the main data structure for holding the state + * of the driver + * @dev: The device pointer +@@ -476,6 +510,7 @@ struct mt7530_priv { + struct regulator *core_pwr; + struct regulator *io_pwr; + struct gpio_desc *reset; ++ const struct mt753x_info *info; + unsigned int id; + bool mcm; + phy_interface_t p6_interface; diff --git a/target/linux/mediatek/patches-5.4/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch b/target/linux/mediatek/patches-5.4/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch new file mode 100644 index 0000000000..1e6126eb7f --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch @@ -0,0 +1,1510 @@ +From: Landen Chao +Date: Fri, 4 Sep 2020 22:21:59 +0800 +Subject: [PATCH] net: dsa: mt7530: Add the support of MT7531 switch + +Add new support for MT7531: + +MT7531 is the next generation of MT7530. It is also a 7-ports switch with +5 giga embedded phys, 2 cpu ports, and the same MAC logic of MT7530. Cpu +port 6 only supports SGMII interface. Cpu port 5 supports either RGMII +or SGMII in different HW sku, but cannot be muxed to PHY of port 0/4 like +mt7530. Due to SGMII interface support, pll, and pad setting are different +from MT7530. This patch adds different initial setting, and SGMII phylink +handlers of MT7531. + +MT7531 SGMII interface can be configured in following mode: +- 'SGMII AN mode' with in-band negotiation capability + which is compatible with PHY_INTERFACE_MODE_SGMII. +- 'SGMII force mode' without in-band negotiation + which is compatible with 10B/8B encoding of + PHY_INTERFACE_MODE_1000BASEX with fixed full-duplex and fixed pause. +- 2.5 times faster clocked 'SGMII force mode' without in-band negotiation + which is compatible with 10B/8B encoding of + PHY_INTERFACE_MODE_2500BASEX with fixed full-duplex and fixed pause. + +Signed-off-by: Landen Chao +Signed-off-by: Sean Wang +--- + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -234,6 +234,12 @@ mt7530_write(struct mt7530_priv *priv, u + } + + static u32 ++_mt7530_unlocked_read(struct mt7530_dummy_poll *p) ++{ ++ return mt7530_mii_read(p->priv, p->reg); ++} ++ ++static u32 + _mt7530_read(struct mt7530_dummy_poll *p) + { + struct mii_bus *bus = p->priv->bus; +@@ -483,6 +489,108 @@ mt7530_pad_clk_setup(struct dsa_switch * + return 0; + } + ++static bool mt7531_dual_sgmii_supported(struct mt7530_priv *priv) ++{ ++ u32 val; ++ ++ val = mt7530_read(priv, MT7531_TOP_SIG_SR); ++ ++ return (val & PAD_DUAL_SGMII_EN) != 0; ++} ++ ++static int ++mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 val; ++ u32 top_sig; ++ u32 hwstrap; ++ u32 xtal; ++ ++ if (mt7531_dual_sgmii_supported(priv)) ++ return 0; ++ ++ val = mt7530_read(priv, MT7531_CREV); ++ top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR); ++ hwstrap = mt7530_read(priv, MT7531_HWTRAP); ++ if ((val & CHIP_REV_M) > 0) ++ xtal = (top_sig & PAD_MCM_SMI_EN) ? HWTRAP_XTAL_FSEL_40MHZ : ++ HWTRAP_XTAL_FSEL_25MHZ; ++ else ++ xtal = hwstrap & HWTRAP_XTAL_FSEL_MASK; ++ ++ /* Step 1 : Disable MT7531 COREPLL */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val &= ~EN_COREPLL; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ /* Step 2: switch to XTAL output */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= SW_CLKSW; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_EN; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ /* Step 3: disable PLLGP and enable program PLLGP */ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= SW_PLLGP; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ ++ /* Step 4: program COREPLL output frequency to 500MHz */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_POSDIV_M; ++ val |= 2 << RG_COREPLL_POSDIV_S; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ usleep_range(25, 35); ++ ++ switch (xtal) { ++ case HWTRAP_XTAL_FSEL_25MHZ: ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_SDM_PCW_M; ++ val |= 0x140000 << RG_COREPLL_SDM_PCW_S; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ break; ++ case HWTRAP_XTAL_FSEL_40MHZ: ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_SDM_PCW_M; ++ val |= 0x190000 << RG_COREPLL_SDM_PCW_S; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ break; ++ }; ++ ++ /* Set feedback divide ratio update signal to high */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val |= RG_COREPLL_SDM_PCW_CHG; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ /* Wait for at least 16 XTAL clocks */ ++ usleep_range(10, 20); ++ ++ /* Step 5: set feedback divide ratio update signal to low */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val &= ~RG_COREPLL_SDM_PCW_CHG; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ /* Enable 325M clock for SGMII */ ++ mt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000); ++ ++ /* Enable 250SSC clock for RGMII */ ++ mt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000); ++ ++ /* Step 6: Enable MT7531 PLL */ ++ val = mt7530_read(priv, MT7531_PLLGP_CR0); ++ val |= RG_COREPLL_EN; ++ mt7530_write(priv, MT7531_PLLGP_CR0, val); ++ ++ val = mt7530_read(priv, MT7531_PLLGP_EN); ++ val |= EN_COREPLL; ++ mt7530_write(priv, MT7531_PLLGP_EN, val); ++ usleep_range(25, 35); ++ ++ return 0; ++} ++ + static void + mt7530_mib_reset(struct dsa_switch *ds) + { +@@ -507,6 +615,217 @@ static int mt7530_phy_write(struct dsa_s + return mdiobus_write_nested(priv->bus, port, regnum, val); + } + ++static int ++mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, ++ int regnum) ++{ ++ struct mii_bus *bus = priv->bus; ++ struct mt7530_dummy_poll p; ++ u32 reg, val; ++ int ret; ++ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MT7531_MDIO_CL45_ADDR | MT7531_MDIO_PHY_ADDR(port) | ++ MT7531_MDIO_DEV_ADDR(devad) | regnum; ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MT7531_MDIO_CL45_READ | MT7531_MDIO_PHY_ADDR(port) | ++ MT7531_MDIO_DEV_ADDR(devad); ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ ret = val & MT7531_MDIO_RW_DATA_MASK; ++out: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int ++mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, ++ int regnum, u32 data) ++{ ++ struct mii_bus *bus = priv->bus; ++ struct mt7530_dummy_poll p; ++ u32 val, reg; ++ int ret; ++ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MT7531_MDIO_CL45_ADDR | MT7531_MDIO_PHY_ADDR(port) | ++ MT7531_MDIO_DEV_ADDR(devad) | regnum; ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MT7531_MDIO_CL45_WRITE | MT7531_MDIO_PHY_ADDR(port) | ++ MT7531_MDIO_DEV_ADDR(devad) | data; ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++out: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int ++mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum) ++{ ++ struct mii_bus *bus = priv->bus; ++ struct mt7530_dummy_poll p; ++ int ret; ++ u32 val; ++ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ val = MT7531_MDIO_CL22_READ | MT7531_MDIO_PHY_ADDR(port) | ++ MT7531_MDIO_REG_ADDR(regnum); ++ ++ mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, ++ !(val & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ ret = val & MT7531_MDIO_RW_DATA_MASK; ++out: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int ++mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, ++ u16 data) ++{ ++ struct mii_bus *bus = priv->bus; ++ struct mt7530_dummy_poll p; ++ int ret; ++ u32 reg; ++ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); ++ ++ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, ++ !(reg & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++ reg = MT7531_MDIO_CL22_WRITE | MT7531_MDIO_PHY_ADDR(port) | ++ MT7531_MDIO_REG_ADDR(regnum) | data; ++ ++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); ++ ++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, ++ !(reg & MT7531_PHY_ACS_ST), 20, 100000); ++ if (ret < 0) { ++ dev_err(priv->dev, "poll timeout\n"); ++ goto out; ++ } ++ ++out: ++ mutex_unlock(&bus->mdio_lock); ++ ++ return ret; ++} ++ ++static int ++mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ int devad; ++ int ret; ++ ++ if (regnum & MII_ADDR_C45) { ++ devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f; ++ ret = mt7531_ind_c45_phy_read(priv, port, devad, ++ regnum & MII_REGADDR_C45_MASK); ++ } else { ++ ret = mt7531_ind_c22_phy_read(priv, port, regnum); ++ } ++ ++ return ret; ++} ++ ++static int ++mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum, ++ u16 data) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ int devad; ++ int ret; ++ ++ if (regnum & MII_ADDR_C45) { ++ devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f; ++ ret = mt7531_ind_c45_phy_write(priv, port, devad, ++ regnum & MII_REGADDR_C45_MASK, ++ data); ++ } else { ++ ret = mt7531_ind_c22_phy_write(priv, port, regnum, data); ++ } ++ ++ return ret; ++} ++ + static void + mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset, + uint8_t *data) +@@ -623,9 +942,14 @@ unlock_exit: + } + + static int +-mt7530_cpu_port_enable(struct mt7530_priv *priv, +- int port) ++mt753x_cpu_port_enable(struct dsa_switch *ds, int port) + { ++ struct mt7530_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 Mediatek header mode on the cpu port */ + mt7530_write(priv, MT7530_PVC_P(port), + PORT_SPEC_TAG); +@@ -638,7 +962,7 @@ mt7530_cpu_port_enable(struct mt7530_pri + mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port)); + + /* CPU port gets connected to all user ports of +- * the switch ++ * the switch. + */ + mt7530_write(priv, MT7530_PCR_P(port), + PCR_MATRIX(dsa_user_ports(priv->ds))); +@@ -1132,27 +1456,42 @@ mt7530_port_vlan_del(struct dsa_switch * + return 0; + } + +-static int mt7530_port_mirror_add(struct dsa_switch *ds, int port, ++static int mt753x_mirror_port_get(unsigned int id, u32 val) ++{ ++ return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) : ++ MIRROR_PORT(val); ++} ++ ++static int mt753x_mirror_port_set(unsigned int id, u32 val) ++{ ++ return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) : ++ MIRROR_PORT(val); ++} ++ ++static int mt753x_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) + { + struct mt7530_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 = mt7530_read(priv, MT7530_MFC); ++ val = mt7530_read(priv, MT753X_MIRROR_REG(priv->id)); + + /* MT7530 only supports one monitor port */ +- if (val & MIRROR_EN && MIRROR_PORT(val) != mirror->to_local_port) ++ monitor_port = mt753x_mirror_port_get(priv->id, val); ++ if (val & MT753X_MIRROR_EN(priv->id) && ++ monitor_port != mirror->to_local_port) + return -EEXIST; + +- val |= MIRROR_EN; +- val &= ~MIRROR_MASK; +- val |= mirror->to_local_port; +- mt7530_write(priv, MT7530_MFC, val); ++ val |= MT753X_MIRROR_EN(priv->id); ++ val &= ~MT753X_MIRROR_MASK(priv->id); ++ val |= mt753x_mirror_port_set(priv->id, mirror->to_local_port); ++ mt7530_write(priv, MT753X_MIRROR_REG(priv->id), val); + + val = mt7530_read(priv, MT7530_PCR_P(port)); + if (ingress) { +@@ -1167,7 +1506,7 @@ static int mt7530_port_mirror_add(struct + return 0; + } + +-static void mt7530_port_mirror_del(struct dsa_switch *ds, int port, ++static void mt753x_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) + { + struct mt7530_priv *priv = ds->priv; +@@ -1184,9 +1523,9 @@ static void mt7530_port_mirror_del(struc + mt7530_write(priv, MT7530_PCR_P(port), val); + + if (!priv->mirror_rx && !priv->mirror_tx) { +- val = mt7530_read(priv, MT7530_MFC); +- val &= ~MIRROR_EN; +- mt7530_write(priv, MT7530_MFC, val); ++ val = mt7530_read(priv, MT753X_MIRROR_REG(priv->id)); ++ val &= ~MT753X_MIRROR_EN(priv->id); ++ mt7530_write(priv, MT753X_MIRROR_REG(priv->id), val); + } + } + +@@ -1292,7 +1631,7 @@ mt7530_setup(struct dsa_switch *ds) + PCR_MATRIX_CLR); + + if (dsa_is_cpu_port(ds, i)) +- mt7530_cpu_port_enable(priv, i); ++ mt753x_cpu_port_enable(ds, i); + else + mt7530_port_disable(ds, i); + +@@ -1346,6 +1685,118 @@ mt7530_setup(struct dsa_switch *ds) + return 0; + } + ++static int ++mt7531_setup(struct dsa_switch *ds) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ struct mt7530_dummy_poll p; ++ u32 val, id; ++ int ret, i; ++ ++ /* Reset whole chip through gpio pin or memory-mapped registers for ++ * different type of hardware ++ */ ++ if (priv->mcm) { ++ reset_control_assert(priv->rstc); ++ usleep_range(1000, 1100); ++ reset_control_deassert(priv->rstc); ++ } else { ++ gpiod_set_value_cansleep(priv->reset, 0); ++ usleep_range(1000, 1100); ++ gpiod_set_value_cansleep(priv->reset, 1); ++ } ++ ++ /* Waiting for MT7530 got to stable */ ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP); ++ ret = readx_poll_timeout(_mt7530_read, &p, val, val != 0, ++ 20, 1000000); ++ if (ret < 0) { ++ dev_err(priv->dev, "reset timeout\n"); ++ return ret; ++ } ++ ++ id = mt7530_read(priv, MT7531_CREV); ++ id >>= CHIP_NAME_SHIFT; ++ ++ if (id != MT7531_ID) { ++ dev_err(priv->dev, "chip %x can't be supported\n", id); ++ return -ENODEV; ++ } ++ ++ /* Reset the switch through internal reset */ ++ mt7530_write(priv, MT7530_SYS_CTRL, ++ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | ++ SYS_CTRL_REG_RST); ++ ++ if (mt7531_dual_sgmii_supported(priv)) { ++ priv->p5_intf_sel = P5_INTF_SEL_GMAC5_SGMII; ++ ++ /* Let ds->slave_mii_bus be able to access external phy. */ ++ mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO11_RG_RXD2_MASK, ++ MT7531_EXT_P_MDC_11); ++ mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO12_RG_RXD3_MASK, ++ MT7531_EXT_P_MDIO_12); ++ } else { ++ priv->p5_intf_sel = P5_INTF_SEL_GMAC5; ++ } ++ dev_dbg(ds->dev, "P5 support %s interface\n", ++ p5_intf_modes(priv->p5_intf_sel)); ++ ++ mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK, ++ MT7531_GPIO0_INTERRUPT); ++ ++ /* Let phylink decide the interface later. */ ++ priv->p5_interface = PHY_INTERFACE_MODE_NA; ++ priv->p6_interface = PHY_INTERFACE_MODE_NA; ++ ++ /* Enable PHY core PLL, since phy_device has not yet been created ++ * provided for phy_[read,write]_mmd_indirect is called, we provide ++ * our own mt7531_ind_mmd_phy_[read,write] to complete this ++ * function. ++ */ ++ val = mt7531_ind_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR, ++ MDIO_MMD_VEND2, CORE_PLL_GROUP4); ++ val |= MT7531_PHY_PLL_BYPASS_MODE; ++ val &= ~MT7531_PHY_PLL_OFF; ++ mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2, ++ CORE_PLL_GROUP4, val); ++ ++ /* BPDU to CPU port */ ++ mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK, ++ BIT(MT7530_CPU_PORT)); ++ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK, ++ MT753X_BPDU_CPU_ONLY); ++ ++ /* Enable and reset MIB counters */ ++ mt7530_mib_reset(ds); ++ ++ for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ /* Disable forwarding by default on all ports */ ++ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, ++ PCR_MATRIX_CLR); ++ ++ mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR); ++ ++ if (dsa_is_cpu_port(ds, i)) ++ mt753x_cpu_port_enable(ds, i); ++ else ++ mt7530_port_disable(ds, i); ++ ++ /* Enable consistent egress tag */ ++ mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK, ++ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); ++ } ++ ++ ds->configure_vlan_while_not_filtering = true; ++ ++ /* Flush the FDB table */ ++ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + static bool + mt7530_phy_mode_supported(struct dsa_switch *ds, int port, + const struct phylink_link_state *state) +@@ -1384,6 +1835,47 @@ unsupported: + return false; + } + ++static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port) ++{ ++ return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII); ++} ++ ++static bool ++mt7531_phy_supported(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_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: /* 2nd cpu port supports either rgmii or sgmii/8023z */ ++ if (mt7531_is_rgmii_port(priv, port)) ++ return phy_interface_mode_is_rgmii(state->interface); ++ fallthrough; ++ case 6: /* 1st cpu port supports sgmii/8023z only */ ++ if (state->interface != PHY_INTERFACE_MODE_SGMII && ++ !phy_interface_mode_is_8023z(state->interface)) ++ goto unsupported; ++ break; ++ default: ++ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, ++ port); ++ goto unsupported; ++ } ++ ++ return true; ++ ++unsupported: ++ return false; ++} ++ + static bool + mt753x_phy_mode_supported(struct dsa_switch *ds, int port, + const struct phylink_link_state *state) +@@ -1416,6 +1908,227 @@ mt7530_mac_config(struct dsa_switch *ds, + return 0; + } + ++static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, ++ phy_interface_t interface, ++ struct phy_device *phydev) ++{ ++ u32 val; ++ ++ if (!mt7531_is_rgmii_port(priv, port)) { ++ dev_err(priv->dev, "RGMII mode is not available for port %d\n", ++ port); ++ return -EINVAL; ++ } ++ ++ val = mt7530_read(priv, MT7531_CLKGEN_CTRL); ++ val |= GP_CLK_EN; ++ val &= ~GP_MODE_MASK; ++ val |= GP_MODE(MT7531_GP_MODE_RGMII); ++ val &= ~CLK_SKEW_IN_MASK; ++ val |= CLK_SKEW_IN(MT7531_CLK_SKEW_NO_CHG); ++ val &= ~CLK_SKEW_OUT_MASK; ++ val |= CLK_SKEW_OUT(MT7531_CLK_SKEW_NO_CHG); ++ val |= TXCLK_NO_REVERSE | RXCLK_NO_DELAY; ++ ++ /* Do not adjust rgmii delay when vendor phy driver presents. */ ++ if (!phydev || phy_driver_is_genphy(phydev)) { ++ val &= ~(TXCLK_NO_REVERSE | RXCLK_NO_DELAY); ++ switch (interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ val |= TXCLK_NO_REVERSE; ++ val |= RXCLK_NO_DELAY; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ val |= TXCLK_NO_REVERSE; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ val |= RXCLK_NO_DELAY; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ mt7530_write(priv, MT7531_CLKGEN_CTRL, val); ++ ++ return 0; ++} ++ ++static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port, ++ unsigned long *supported) ++{ ++ /* Port5 supports ethier RGMII or SGMII. ++ * Port6 supports SGMII only. ++ */ ++ switch (port) { ++ case 5: ++ if (mt7531_is_rgmii_port(priv, port)) ++ break; ++ fallthrough; ++ case 6: ++ phylink_set(supported, 1000baseX_Full); ++ phylink_set(supported, 2500baseX_Full); ++ phylink_set(supported, 2500baseT_Full); ++ } ++} ++ ++static void ++mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ unsigned int val; ++ ++ /* For adjusting speed and duplex of SGMII force mode. */ ++ if (interface != PHY_INTERFACE_MODE_SGMII || ++ phylink_autoneg_inband(mode)) ++ return; ++ ++ /* SGMII force mode setting */ ++ val = mt7530_read(priv, MT7531_SGMII_MODE(port)); ++ val &= ~MT7531_SGMII_IF_MODE_MASK; ++ ++ switch (speed) { ++ case SPEED_10: ++ val |= MT7531_SGMII_FORCE_SPEED_10; ++ break; ++ case SPEED_100: ++ val |= MT7531_SGMII_FORCE_SPEED_100; ++ break; ++ case SPEED_1000: ++ val |= MT7531_SGMII_FORCE_SPEED_1000; ++ break; ++ } ++ ++ /* MT7531 SGMII 1G force mode can only work in full duplex mode, ++ * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. ++ */ ++ if ((speed == SPEED_10 || speed == SPEED_100) && ++ duplex != DUPLEX_FULL) ++ val |= MT7531_SGMII_FORCE_HALF_DUPLEX; ++ ++ mt7530_write(priv, MT7531_SGMII_MODE(port), val); ++} ++ ++static bool mt753x_is_mac_port(u32 port) ++{ ++ return (port == 5 || port == 6); ++} ++ ++static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port, ++ phy_interface_t interface) ++{ ++ u32 val; ++ ++ if (!mt753x_is_mac_port(port)) ++ return -EINVAL; ++ ++ mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), ++ MT7531_SGMII_PHYA_PWD); ++ ++ val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); ++ val &= ~MT7531_RG_TPHY_SPEED_MASK; ++ /* Setup 2.5 times faster clock for 2.5Gbps data speeds with 10B/8B ++ * encoding. ++ */ ++ val |= (interface == PHY_INTERFACE_MODE_2500BASEX) ? ++ MT7531_RG_TPHY_SPEED_3_125G : MT7531_RG_TPHY_SPEED_1_25G; ++ mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); ++ ++ mt7530_clear(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); ++ ++ /* MT7531 SGMII 1G and 2.5G force mode can only work in full duplex ++ * mode, no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. ++ */ ++ mt7530_rmw(priv, MT7531_SGMII_MODE(port), ++ MT7531_SGMII_IF_MODE_MASK | MT7531_SGMII_REMOTE_FAULT_DIS, ++ MT7531_SGMII_FORCE_SPEED_1000); ++ ++ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); ++ ++ return 0; ++} ++ ++static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port, ++ phy_interface_t interface) ++{ ++ if (!mt753x_is_mac_port(port)) ++ return -EINVAL; ++ ++ mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), ++ MT7531_SGMII_PHYA_PWD); ++ ++ mt7530_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port), ++ MT7531_RG_TPHY_SPEED_MASK, MT7531_RG_TPHY_SPEED_1_25G); ++ ++ mt7530_set(priv, MT7531_SGMII_MODE(port), ++ MT7531_SGMII_REMOTE_FAULT_DIS | ++ MT7531_SGMII_SPEED_DUPLEX_AN); ++ ++ mt7530_rmw(priv, MT7531_PCS_SPEED_ABILITY(port), ++ MT7531_SGMII_TX_CONFIG_MASK, 1); ++ ++ mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); ++ ++ mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_RESTART); ++ ++ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); ++ ++ return 0; ++} ++ ++static void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 val; ++ ++ /* Only restart AN when AN is enabled */ ++ val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); ++ if (val & MT7531_SGMII_AN_ENABLE) { ++ val |= MT7531_SGMII_AN_RESTART; ++ mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); ++ } ++} ++ ++static int ++mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ struct phy_device *phydev; ++ const struct dsa_port *dp; ++ ++ if (!mt753x_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: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ dp = dsa_to_port(ds, port); ++ phydev = dp->slave->phydev; ++ return mt7531_rgmii_setup(priv, port, interface, phydev); ++ case PHY_INTERFACE_MODE_SGMII: ++ return mt7531_sgmii_setup_mode_an(priv, port, interface); ++ case PHY_INTERFACE_MODE_NA: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ if (phylink_autoneg_inband(mode)) ++ return -EINVAL; ++ ++ return mt7531_sgmii_setup_mode_force(priv, port, interface); ++ default: ++ return -EINVAL; ++ } ++ ++ return -EINVAL; ++} ++ + static int + mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state) +@@ -1451,6 +2164,8 @@ mt753x_phylink_mac_config(struct dsa_swi + if (mt753x_mac_config(ds, port, mode, state) < 0) + goto unsupported; + ++ if (priv->p5_intf_sel != P5_DISABLED) ++ priv->p5_interface = state->interface; + break; + case 6: /* 1st cpu port */ + if (priv->p6_interface == state->interface) +@@ -1470,7 +2185,8 @@ unsupported: + return; + } + +- if (phylink_autoneg_inband(mode)) { ++ if (phylink_autoneg_inband(mode) && ++ state->interface != PHY_INTERFACE_MODE_SGMII) { + dev_err(ds->dev, "%s: in-band negotiation unsupported\n", + __func__); + return; +@@ -1480,7 +2196,7 @@ unsupported: + 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 | PMCR_FORCE_MODE; ++ PMCR_BACKPR_EN | PMCR_FORCE_MODE_ID(priv->id); + + /* Are we connected to external phy */ + if (port == 5 && dsa_is_user_port(ds, 5)) +@@ -1490,7 +2206,18 @@ unsupported: + mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); + } + +-static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port, ++static void ++mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ if (!priv->info->mac_pcs_an_restart) ++ return; ++ ++ priv->info->mac_pcs_an_restart(ds, port); ++} ++ ++static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) + { +@@ -1499,7 +2226,19 @@ static void mt7530_phylink_mac_link_down + mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + } + +-static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port, ++static void mt753x_mac_pcs_link_up(struct dsa_switch *ds, int port, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ if (!priv->info->mac_pcs_link_up) ++ return; ++ ++ priv->info->mac_pcs_link_up(ds, port, mode, interface, speed, duplex); ++} ++ ++static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, + struct phy_device *phydev, +@@ -1509,18 +2248,29 @@ static void mt7530_phylink_mac_link_up(s + struct mt7530_priv *priv = ds->priv; + u32 mcr; + ++ mt753x_mac_pcs_link_up(ds, port, mode, interface, speed, duplex); ++ + mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; + ++ /* MT753x MAC works in 1G full duplex mode for all up-clocked ++ * variants. ++ */ ++ if (interface == PHY_INTERFACE_MODE_TRGMII || ++ (phy_interface_mode_is_8023z(interface))) { ++ speed = SPEED_1000; ++ duplex = DUPLEX_FULL; ++ } ++ + switch (speed) { + case SPEED_1000: + mcr |= PMCR_FORCE_SPEED_1000; + if (priv->eee_enable & BIT(port)) +- mcr_new |= PMCR_FORCE_EEE1G; ++ mcr |= PMCR_FORCE_EEE1G; + break; + case SPEED_100: + mcr |= PMCR_FORCE_SPEED_100; + if (priv->eee_enable & BIT(port)) +- mcr_new |= PMCR_FORCE_EEE100; ++ mcr |= PMCR_FORCE_EEE100; + break; + } + if (duplex == DUPLEX_FULL) { +@@ -1534,6 +2284,45 @@ static void mt7530_phylink_mac_link_up(s + mt7530_set(priv, MT7530_PMCR_P(port), mcr); + } + ++static int ++mt7531_cpu_port_config(struct dsa_switch *ds, int port) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ phy_interface_t interface; ++ int speed; ++ ++ switch (port) { ++ case 5: ++ if (mt7531_is_rgmii_port(priv, port)) ++ interface = PHY_INTERFACE_MODE_RGMII; ++ else ++ interface = PHY_INTERFACE_MODE_2500BASEX; ++ ++ priv->p5_interface = interface; ++ break; ++ case 6: ++ interface = PHY_INTERFACE_MODE_2500BASEX; ++ ++ mt7531_pad_setup(ds, interface); ++ ++ priv->p6_interface = interface; ++ break; ++ }; ++ ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++ speed = SPEED_2500; ++ else ++ speed = SPEED_1000; ++ ++ mt7531_mac_config(ds, port, MLO_AN_FIXED, interface); ++ mt7530_write(priv, MT7530_PMCR_P(port), ++ PMCR_CPU_PORT_SETTING(priv->id)); ++ mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL, ++ speed, DUPLEX_FULL, true, true); ++ ++ return 0; ++} ++ + static void + mt7530_mac_port_validate(struct dsa_switch *ds, int port, + unsigned long *supported) +@@ -1542,6 +2331,14 @@ mt7530_mac_port_validate(struct dsa_swit + phylink_set(supported, 1000baseX_Full); + } + ++static void mt7531_mac_port_validate(struct dsa_switch *ds, int port, ++ unsigned long *supported) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ mt7531_sgmii_validate(priv, port, supported); ++} ++ + static void + mt753x_phylink_validate(struct dsa_switch *ds, int port, + unsigned long *supported, +@@ -1558,7 +2355,8 @@ mt753x_phylink_validate(struct dsa_switc + + phylink_set_port_modes(mask); + +- if (state->interface != PHY_INTERFACE_MODE_TRGMII) { ++ if (state->interface != PHY_INTERFACE_MODE_TRGMII || ++ !phy_interface_mode_is_8023z(state->interface)) { + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); +@@ -1577,6 +2375,11 @@ mt753x_phylink_validate(struct dsa_switc + + 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 +@@ -1667,6 +2470,63 @@ static int mt7530_set_mac_eee(struct dsa + return 0; + } + ++#ifdef notyet ++static int ++mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port, ++ struct phylink_link_state *state) ++{ ++ u32 status, val; ++ u16 config_reg; ++ ++ status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); ++ state->link = !!(status & MT7531_SGMII_LINK_STATUS); ++ if (state->interface == PHY_INTERFACE_MODE_SGMII && ++ (status & MT7531_SGMII_AN_ENABLE)) { ++ val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port)); ++ config_reg = val >> 16; ++ ++ switch (config_reg & LPA_SGMII_SPD_MASK) { ++ case LPA_SGMII_1000: ++ state->speed = SPEED_1000; ++ break; ++ case LPA_SGMII_100: ++ state->speed = SPEED_100; ++ break; ++ case LPA_SGMII_10: ++ state->speed = SPEED_10; ++ break; ++ default: ++ dev_err(priv->dev, "invalid sgmii PHY speed\n"); ++ state->link = false; ++ return -EINVAL; ++ } ++ ++ if (config_reg & LPA_SGMII_FULL_DUPLEX) ++ state->duplex = DUPLEX_FULL; ++ else ++ state->duplex = DUPLEX_HALF; ++ } ++ ++ return 0; ++} ++#endif ++ ++static int ++mt7531_phylink_mac_link_state(struct dsa_switch *ds, int port, ++ struct phylink_link_state *state) ++{ ++#ifdef notyet ++ struct mt7530_priv *priv = ds->priv; ++ ++ if (state->interface == PHY_INTERFACE_MODE_SGMII) ++ return mt7531_sgmii_pcs_get_state_an(priv, port, state); ++#else ++ return mt7530_phylink_mac_link_state(ds, port, state); ++#endif ++ ++ return -EOPNOTSUPP; ++} ++ + static int + mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +@@ -1720,13 +2580,14 @@ static const struct dsa_switch_ops mt753 + .port_vlan_prepare = mt7530_port_vlan_prepare, + .port_vlan_add = mt7530_port_vlan_add, + .port_vlan_del = mt7530_port_vlan_del, +- .port_mirror_add = mt7530_port_mirror_add, +- .port_mirror_del = mt7530_port_mirror_del, ++ .port_mirror_add = mt753x_port_mirror_add, ++ .port_mirror_del = mt753x_port_mirror_del, + .phylink_validate = mt753x_phylink_validate, + .phylink_mac_link_state = mt753x_phylink_mac_link_state, + .phylink_mac_config = mt753x_phylink_mac_config, +- .phylink_mac_link_down = mt7530_phylink_mac_link_down, +- .phylink_mac_link_up = mt7530_phylink_mac_link_up, ++ .phylink_mac_an_restart = mt753x_phylink_mac_an_restart, ++ .phylink_mac_link_down = mt753x_phylink_mac_link_down, ++ .phylink_mac_link_up = mt753x_phylink_mac_link_up, + .get_mac_eee = mt7530_get_mac_eee, + .set_mac_eee = mt7530_set_mac_eee, + }; +@@ -1754,11 +2615,26 @@ static const struct mt753x_info mt753x_t + .mac_port_get_state = mt7530_phylink_mac_link_state, + .mac_port_config = mt7530_mac_config, + }, ++ [ID_MT7531] = { ++ .id = ID_MT7531, ++ .sw_setup = mt7531_setup, ++ .phy_read = mt7531_ind_phy_read, ++ .phy_write = mt7531_ind_phy_write, ++ .pad_setup = mt7531_pad_setup, ++ .cpu_port_config = mt7531_cpu_port_config, ++ .phy_mode_supported = mt7531_phy_supported, ++ .mac_port_validate = mt7531_mac_port_validate, ++ .mac_port_get_state = mt7531_phylink_mac_link_state, ++ .mac_port_config = mt7531_mac_config, ++ .mac_pcs_an_restart = mt7531_sgmii_restart_an, ++ .mac_pcs_link_up = mt7531_sgmii_link_up_force, ++ }, + }; + + static const struct of_device_id mt7530_of_match[] = { + { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, + { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, ++ { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, mt7530_of_match); +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -14,6 +14,7 @@ + enum mt753x_id { + ID_MT7530 = 0, + ID_MT7621 = 1, ++ ID_MT7531 = 2, + }; + + #define NUM_TRGMII_CTRL 5 +@@ -41,6 +42,33 @@ enum mt753x_id { + #define MIRROR_PORT(x) ((x) & 0x7) + #define MIRROR_MASK 0x7 + ++/* Registers for CPU forward control */ ++#define MT7531_CFC 0x4 ++#define MT7531_MIRROR_EN BIT(19) ++#define MT7531_MIRROR_MASK (MIRROR_MASK << 16) ++#define MT7531_MIRROR_PORT_GET(x) (((x) >> 16) & MIRROR_MASK) ++#define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16) ++#define MT7531_CPU_PMAP_MASK GENMASK(7, 0) ++ ++#define MT753X_MIRROR_REG(id) (((id) == ID_MT7531) ? \ ++ MT7531_CFC : MT7530_MFC) ++#define MT753X_MIRROR_EN(id) (((id) == ID_MT7531) ? \ ++ MT7531_MIRROR_EN : MIRROR_EN) ++#define MT753X_MIRROR_MASK(id) (((id) == ID_MT7531) ? \ ++ MT7531_MIRROR_MASK : MIRROR_MASK) ++ ++/* Registers for BPDU and PAE frame control*/ ++#define MT753X_BPC 0x24 ++#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0) ++ ++enum mt753x_bpdu_port_fw { ++ MT753X_BPDU_FOLLOW_MFC, ++ MT753X_BPDU_CPU_EXCLUDE = 4, ++ MT753X_BPDU_CPU_INCLUDE = 5, ++ MT753X_BPDU_CPU_ONLY = 6, ++ MT753X_BPDU_DROP = 7, ++}; ++ + /* Registers for address table access */ + #define MT7530_ATA1 0x74 + #define STATIC_EMP 0 +@@ -222,10 +250,30 @@ enum mt7530_vlan_port_attr { + #define PMCR_FORCE_LNK BIT(0) + #define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \ + PMCR_FORCE_SPEED_1000) ++#define MT7531_FORCE_LNK BIT(31) ++#define MT7531_FORCE_SPD BIT(30) ++#define MT7531_FORCE_DPX BIT(29) ++#define MT7531_FORCE_RX_FC BIT(28) ++#define MT7531_FORCE_TX_FC BIT(27) ++#define MT7531_FORCE_MODE (MT7531_FORCE_LNK | \ ++ MT7531_FORCE_SPD | \ ++ MT7531_FORCE_DPX | \ ++ MT7531_FORCE_RX_FC | \ ++ MT7531_FORCE_TX_FC) ++#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \ ++ MT7531_FORCE_MODE : \ ++ PMCR_FORCE_MODE) + #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ + PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ + PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ + PMCR_FORCE_FDX | PMCR_FORCE_LNK) ++#define PMCR_CPU_PORT_SETTING(id) (PMCR_FORCE_MODE_ID((id)) | \ ++ 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_1000 | \ ++ PMCR_FORCE_FDX | PMCR_FORCE_LNK) + + #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) + #define PMSR_EEE1G BIT(7) +@@ -245,6 +293,10 @@ enum mt7530_vlan_port_attr { + #define LPI_THRESH(x) ((x & 0xFFF) << 4) + #define LPI_MODE_EN BIT(0) + ++/* Register for port debug count */ ++#define MT7531_DBG_CNT(x) (0x3018 + (x) * 0x100) ++#define MT7531_DIS_CLR BIT(31) ++ + /* Register for MIB */ + #define MT7530_PORT_MIB_COUNTER(x) (0x4000 + (x) * 0x100) + #define MT7530_MIB_CCR 0x4fe0 +@@ -262,12 +314,118 @@ enum mt7530_vlan_port_attr { + CCR_RX_OCT_CNT_BAD | \ + CCR_TX_OCT_CNT_GOOD | \ + CCR_TX_OCT_CNT_BAD) ++ ++/* MT7531 SGMII register group */ ++#define MT7531_SGMII_REG_BASE 0x5000 ++#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \ ++ ((p) - 5) * 0x1000 + (r)) ++ ++/* Register forSGMII PCS_CONTROL_1 */ ++#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00) ++#define MT7531_SGMII_LINK_STATUS BIT(18) ++#define MT7531_SGMII_AN_ENABLE BIT(12) ++#define MT7531_SGMII_AN_RESTART BIT(9) ++ ++/* Register for SGMII PCS_SPPED_ABILITY */ ++#define MT7531_PCS_SPEED_ABILITY(p) MT7531_SGMII_REG(p, 0x08) ++#define MT7531_SGMII_TX_CONFIG_MASK GENMASK(15, 0) ++#define MT7531_SGMII_TX_CONFIG BIT(0) ++ ++/* Register for SGMII_MODE */ ++#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20) ++#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8) ++#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1) ++#define MT7531_SGMII_FORCE_DUPLEX BIT(4) ++#define MT7531_SGMII_FORCE_SPEED_MASK GENMASK(3, 2) ++#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3) ++#define MT7531_SGMII_FORCE_SPEED_100 BIT(2) ++#define MT7531_SGMII_FORCE_SPEED_10 0 ++#define MT7531_SGMII_SPEED_DUPLEX_AN BIT(1) ++ ++enum mt7531_sgmii_force_duplex { ++ MT7531_SGMII_FORCE_FULL_DUPLEX = 0, ++ MT7531_SGMII_FORCE_HALF_DUPLEX = 0x10, ++}; ++ ++/* Fields of QPHY_PWR_STATE_CTRL */ ++#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8) ++#define MT7531_SGMII_PHYA_PWD BIT(4) ++ ++/* Values of SGMII SPEED */ ++#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128) ++#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3)) ++#define MT7531_RG_TPHY_SPEED_1_25G 0x0 ++#define MT7531_RG_TPHY_SPEED_3_125G BIT(2) ++ + /* Register for system reset */ + #define MT7530_SYS_CTRL 0x7000 + #define SYS_CTRL_PHY_RST BIT(2) + #define SYS_CTRL_SW_RST BIT(1) + #define SYS_CTRL_REG_RST BIT(0) + ++/* Register for PHY Indirect Access Control */ ++#define MT7531_PHY_IAC 0x701C ++#define MT7531_PHY_ACS_ST BIT(31) ++#define MT7531_MDIO_REG_ADDR_MASK (0x1f << 25) ++#define MT7531_MDIO_PHY_ADDR_MASK (0x1f << 20) ++#define MT7531_MDIO_CMD_MASK (0x3 << 18) ++#define MT7531_MDIO_ST_MASK (0x3 << 16) ++#define MT7531_MDIO_RW_DATA_MASK (0xffff) ++#define MT7531_MDIO_REG_ADDR(x) (((x) & 0x1f) << 25) ++#define MT7531_MDIO_DEV_ADDR(x) (((x) & 0x1f) << 25) ++#define MT7531_MDIO_PHY_ADDR(x) (((x) & 0x1f) << 20) ++#define MT7531_MDIO_CMD(x) (((x) & 0x3) << 18) ++#define MT7531_MDIO_ST(x) (((x) & 0x3) << 16) ++ ++enum mt7531_phy_iac_cmd { ++ MT7531_MDIO_ADDR = 0, ++ MT7531_MDIO_WRITE = 1, ++ MT7531_MDIO_READ = 2, ++ MT7531_MDIO_READ_CL45 = 3, ++}; ++ ++/* MDIO_ST: MDIO start field */ ++enum mt7531_mdio_st { ++ MT7531_MDIO_ST_CL45 = 0, ++ MT7531_MDIO_ST_CL22 = 1, ++}; ++ ++#define MT7531_MDIO_CL22_READ (MT7531_MDIO_ST(MT7531_MDIO_ST_CL22) | \ ++ MT7531_MDIO_CMD(MT7531_MDIO_READ)) ++#define MT7531_MDIO_CL22_WRITE (MT7531_MDIO_ST(MT7531_MDIO_ST_CL22) | \ ++ MT7531_MDIO_CMD(MT7531_MDIO_WRITE)) ++#define MT7531_MDIO_CL45_ADDR (MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \ ++ MT7531_MDIO_CMD(MT7531_MDIO_ADDR)) ++#define MT7531_MDIO_CL45_READ (MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \ ++ MT7531_MDIO_CMD(MT7531_MDIO_READ)) ++#define MT7531_MDIO_CL45_WRITE (MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \ ++ MT7531_MDIO_CMD(MT7531_MDIO_WRITE)) ++ ++/* Register for RGMII clock phase */ ++#define MT7531_CLKGEN_CTRL 0x7500 ++#define CLK_SKEW_OUT(x) (((x) & 0x3) << 8) ++#define CLK_SKEW_OUT_MASK GENMASK(9, 8) ++#define CLK_SKEW_IN(x) (((x) & 0x3) << 6) ++#define CLK_SKEW_IN_MASK GENMASK(7, 6) ++#define RXCLK_NO_DELAY BIT(5) ++#define TXCLK_NO_REVERSE BIT(4) ++#define GP_MODE(x) (((x) & 0x3) << 1) ++#define GP_MODE_MASK GENMASK(2, 1) ++#define GP_CLK_EN BIT(0) ++ ++enum mt7531_gp_mode { ++ MT7531_GP_MODE_RGMII = 0, ++ MT7531_GP_MODE_MII = 1, ++ MT7531_GP_MODE_REV_MII = 2 ++}; ++ ++enum mt7531_clk_skew { ++ MT7531_CLK_SKEW_NO_CHG = 0, ++ MT7531_CLK_SKEW_DLY_100PPS = 1, ++ MT7531_CLK_SKEW_DLY_200PPS = 2, ++ MT7531_CLK_SKEW_REVERSE = 3, ++}; ++ + /* Register for hw trap status */ + #define MT7530_HWTRAP 0x7800 + #define HWTRAP_XTAL_MASK (BIT(10) | BIT(9)) +@@ -275,6 +433,16 @@ enum mt7530_vlan_port_attr { + #define HWTRAP_XTAL_40MHZ (BIT(10)) + #define HWTRAP_XTAL_20MHZ (BIT(9)) + ++#define MT7531_HWTRAP 0x7800 ++#define HWTRAP_XTAL_FSEL_MASK BIT(7) ++#define HWTRAP_XTAL_FSEL_25MHZ BIT(7) ++#define HWTRAP_XTAL_FSEL_40MHZ 0 ++/* Unique fields of (M)HWSTRAP for MT7531 */ ++#define XTAL_FSEL_S 7 ++#define XTAL_FSEL_M BIT(7) ++#define PHY_EN BIT(6) ++#define CHG_STRAP BIT(8) ++ + /* Register for hw trap modification */ + #define MT7530_MHWTRAP 0x7804 + #define MHWTRAP_PHY0_SEL BIT(20) +@@ -289,14 +457,37 @@ enum mt7530_vlan_port_attr { + #define MT7530_TOP_SIG_CTRL 0x7808 + #define TOP_SIG_CTRL_NORMAL (BIT(17) | BIT(16)) + ++#define MT7531_TOP_SIG_SR 0x780c ++#define PAD_DUAL_SGMII_EN BIT(1) ++#define PAD_MCM_SMI_EN BIT(0) ++ + #define MT7530_IO_DRV_CR 0x7810 + #define P5_IO_CLK_DRV(x) ((x) & 0x3) + #define P5_IO_DATA_DRV(x) (((x) & 0x3) << 4) + ++#define MT7531_CHIP_REV 0x781C ++ ++#define MT7531_PLLGP_EN 0x7820 ++#define EN_COREPLL BIT(2) ++#define SW_CLKSW BIT(1) ++#define SW_PLLGP BIT(0) ++ + #define MT7530_P6ECR 0x7830 + #define P6_INTF_MODE_MASK 0x3 + #define P6_INTF_MODE(x) ((x) & 0x3) + ++#define MT7531_PLLGP_CR0 0x78a8 ++#define RG_COREPLL_EN BIT(22) ++#define RG_COREPLL_POSDIV_S 23 ++#define RG_COREPLL_POSDIV_M 0x3800000 ++#define RG_COREPLL_SDM_PCW_S 1 ++#define RG_COREPLL_SDM_PCW_M 0x3ffffe ++#define RG_COREPLL_SDM_PCW_CHG BIT(0) ++ ++/* Registers for RGMII and SGMII PLL clock */ ++#define MT7531_ANA_PLLGP_CR2 0x78b0 ++#define MT7531_ANA_PLLGP_CR5 0x78bc ++ + /* Registers for TRGMII on the both side */ + #define MT7530_TRGMII_RCK_CTRL 0x7a00 + #define RX_RST BIT(31) +@@ -335,10 +526,25 @@ enum mt7530_vlan_port_attr { + #define MT7530_P5RGMIITXCR 0x7b04 + #define CSR_RGMII_TXC_CFG(x) ((x) & 0x1f) + ++/* Registers for GPIO mode */ ++#define MT7531_GPIO_MODE0 0x7c0c ++#define MT7531_GPIO0_MASK GENMASK(3, 0) ++#define MT7531_GPIO0_INTERRUPT 1 ++ ++#define MT7531_GPIO_MODE1 0x7c10 ++#define MT7531_GPIO11_RG_RXD2_MASK GENMASK(15, 12) ++#define MT7531_EXT_P_MDC_11 (2 << 12) ++#define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16) ++#define MT7531_EXT_P_MDIO_12 (2 << 16) ++ + #define MT7530_CREV 0x7ffc + #define CHIP_NAME_SHIFT 16 + #define MT7530_ID 0x7530 + ++#define MT7531_CREV 0x781C ++#define CHIP_REV_M 0x0f ++#define MT7531_ID 0x7531 ++ + /* Registers for core PLL access through mmd indirect */ + #define CORE_PLL_GROUP2 0x401 + #define RG_SYSPLL_EN_NORMAL BIT(15) +@@ -355,6 +561,10 @@ enum mt7530_vlan_port_attr { + #define RG_SYSPLL_DDSFBK_EN BIT(12) + #define RG_SYSPLL_BIAS_EN BIT(11) + #define RG_SYSPLL_BIAS_LPF_EN BIT(10) ++#define MT7531_PHY_PLL_OFF BIT(5) ++#define MT7531_PHY_PLL_BYPASS_MODE BIT(4) ++ ++#define MT753X_CTRL_PHY_ADDR 0 + + #define CORE_PLL_GROUP5 0x404 + #define RG_LCDDS_PCW_NCPO1(x) ((x) & 0xffff) +@@ -433,6 +643,7 @@ enum p5_interface_select { + P5_INTF_SEL_PHY_P0, + P5_INTF_SEL_PHY_P4, + P5_INTF_SEL_GMAC5, ++ P5_INTF_SEL_GMAC5_SGMII, + }; + + static const char *p5_intf_modes(unsigned int p5_interface) +@@ -446,6 +657,8 @@ static const char *p5_intf_modes(unsigne + return "PHY P4"; + case P5_INTF_SEL_GMAC5: + return "GMAC5"; ++ case P5_INTF_SEL_GMAC5_SGMII: ++ return "GMAC5_SGMII"; + default: + return "unknown"; + } +@@ -466,6 +679,10 @@ static const char *p5_intf_modes(unsigne + * 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 mt753x_info { + enum mt753x_id id; +@@ -474,6 +691,7 @@ struct mt753x_info { + 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, +@@ -483,6 +701,10 @@ struct mt753x_info { + 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); ++ void (*mac_pcs_link_up)(struct dsa_switch *ds, int port, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex); + }; + + /* struct mt7530_priv - This is the main data structure for holding the state diff --git a/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch b/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch new file mode 100644 index 0000000000..8c3fe52089 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch @@ -0,0 +1,71 @@ +From: Landen Chao +Subject: [PATCH net-next 6/6] arm64: dts: mt7622: add mt7531 dsa to + bananapi-bpi-r64 board +Date: Tue, 10 Dec 2019 16:14:42 +0800 + +Add mt7531 dsa to bananapi-bpi-r64 board for 5 giga Ethernet ports support. + +Signed-off-by: Landen Chao +--- + .../dts/mediatek/mt7622-bananapi-bpi-r64.dts | 50 +++++++++++++++++++ + 1 file changed, 50 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -150,6 +150,56 @@ + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; ++ ++ switch@0 { ++ compatible = "mediatek,mt7531"; ++ reg = <0>; ++ reset-gpios = <&pio 54 0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ label = "wan"; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ label = "lan0"; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ label = "lan1"; ++ }; ++ ++ port@3 { ++ reg = <3>; ++ label = "lan2"; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ label = "lan3"; ++ }; ++ ++ port@6 { ++ reg = <6>; ++ label = "cpu"; ++ ethernet = <&gmac0>; ++ phy-mode = "2500base-x"; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ }; ++ }; ++ + }; + }; + diff --git a/target/linux/mediatek/patches-5.4/0999-hnat.patch b/target/linux/mediatek/patches-5.4/0999-hnat.patch index cd0ad54c7e..50850a906e 100644 --- a/target/linux/mediatek/patches-5.4/0999-hnat.patch +++ b/target/linux/mediatek/patches-5.4/0999-hnat.patch @@ -147,7 +147,7 @@ #include "mtk_eth_soc.h" -@@ -1319,8 +1321,16 @@ static int mtk_poll_rx(struct napi_struc +@@ -1320,8 +1322,16 @@ static int mtk_poll_rx(struct napi_struc (trxd.rxd2 & RX_DMA_VTAG)) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), RX_DMA_VID(trxd.rxd3)); @@ -166,7 +166,7 @@ skip_rx: ring->data[idx] = new_data; -@@ -2251,6 +2261,9 @@ static int mtk_open(struct net_device *d +@@ -2255,6 +2265,9 @@ static int mtk_open(struct net_device *d mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); refcount_set(ð->dma_refcnt, 1); @@ -176,7 +176,7 @@ } else refcount_inc(ð->dma_refcnt); -@@ -2312,6 +2325,9 @@ static int mtk_stop(struct net_device *d +@@ -2316,6 +2329,9 @@ static int mtk_stop(struct net_device *d mtk_dma_free(eth); @@ -186,7 +186,7 @@ return 0; } -@@ -2825,6 +2841,27 @@ static int mtk_set_rxnfc(struct net_devi +@@ -2829,6 +2845,27 @@ static int mtk_set_rxnfc(struct net_devi return ret; } @@ -214,7 +214,7 @@ static const struct ethtool_ops mtk_ethtool_ops = { .get_link_ksettings = mtk_get_link_ksettings, .set_link_ksettings = mtk_set_link_ksettings, -@@ -2856,6 +2893,9 @@ static const struct net_device_ops mtk_n +@@ -2860,6 +2897,9 @@ static const struct net_device_ops mtk_n #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = mtk_poll_controller, #endif @@ -224,7 +224,7 @@ }; static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) -@@ -3198,6 +3238,7 @@ static const struct mtk_soc_data mt7622_ +@@ -3202,6 +3242,7 @@ static const struct mtk_soc_data mt7622_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7622_CLKS_BITMAP, .required_pctl = false, diff --git a/target/linux/mediatek/patches-5.4/1000-eth-gdm-config-backport.patch b/target/linux/mediatek/patches-5.4/1000-eth-gdm-config-backport.patch index 38addd36ed..a2acadfd90 100644 --- a/target/linux/mediatek/patches-5.4/1000-eth-gdm-config-backport.patch +++ b/target/linux/mediatek/patches-5.4/1000-eth-gdm-config-backport.patch @@ -1,6 +1,6 @@ --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2236,6 +2236,31 @@ static int mtk_start_dma(struct mtk_eth +@@ -2240,6 +2240,31 @@ static int mtk_start_dma(struct mtk_eth return 0; } @@ -32,7 +32,7 @@ static int mtk_open(struct net_device *dev) { struct mtk_mac *mac = netdev_priv(dev); -@@ -2256,6 +2281,8 @@ static int mtk_open(struct net_device *d +@@ -2260,6 +2285,8 @@ static int mtk_open(struct net_device *d if (err) return err; @@ -41,7 +41,7 @@ napi_enable(ð->tx_napi); napi_enable(ð->rx_napi); mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); -@@ -2311,6 +2338,8 @@ static int mtk_stop(struct net_device *d +@@ -2315,6 +2342,8 @@ static int mtk_stop(struct net_device *d if (!refcount_dec_and_test(ð->dma_refcnt)) return 0; @@ -50,7 +50,7 @@ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); napi_disable(ð->tx_napi); -@@ -2494,8 +2523,6 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -2498,8 +2527,6 @@ static int mtk_hw_init(struct mtk_eth *e /* disable delay and normal interrupt */ mtk_tx_irq_disable(eth, ~0); mtk_rx_irq_disable(eth, ~0); @@ -59,7 +59,7 @@ /* FE int grouping */ mtk_w32(eth, MTK_TX_DONE_INT, MTK_PDMA_INT_GRP1); -@@ -2504,19 +2531,6 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -2508,19 +2535,6 @@ static int mtk_hw_init(struct mtk_eth *e mtk_w32(eth, MTK_RX_DONE_INT, MTK_QDMA_INT_GRP2); mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); diff --git a/target/linux/mediatek/patches-5.4/1011-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch b/target/linux/mediatek/patches-5.4/1011-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch index 1c2e08aca2..50b5e59697 100644 --- a/target/linux/mediatek/patches-5.4/1011-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch +++ b/target/linux/mediatek/patches-5.4/1011-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch @@ -37,7 +37,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -2472,6 +2473,12 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -2476,6 +2477,12 @@ static int mtk_hw_init(struct mtk_eth *e if (ret) goto err_disable_pm; @@ -50,7 +50,7 @@ Signed-off-by: Felix Fietkau if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { ret = device_reset(eth->dev); if (ret) { -@@ -3074,6 +3081,16 @@ static int mtk_probe(struct platform_dev +@@ -3078,6 +3085,16 @@ static int mtk_probe(struct platform_dev } } diff --git a/target/linux/mvebu/cortexa9/base-files/etc/uci-defaults/05_fix-compat-version b/target/linux/mvebu/cortexa9/base-files/etc/uci-defaults/05_fix-compat-version deleted file mode 100644 index 5965fdc2f5..0000000000 --- a/target/linux/mvebu/cortexa9/base-files/etc/uci-defaults/05_fix-compat-version +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright (C) 2020 OpenWrt.org -# - -. /lib/functions.sh - -case "$(board_name)" in - linksys,wrt1200ac|\ - linksys,wrt1900ac-v1|\ - linksys,wrt1900ac-v2|\ - linksys,wrt1900acs|\ - linksys,wrt3200acm|\ - linksys,wrt32x|\ - solidrun,clearfog-base-a1|\ - solidrun,clearfog-pro-a1) - uci set system.@system[0].compat_version="1.1" - uci commit system - ;; -esac - -exit 0 diff --git a/target/linux/mvebu/image/cortexa9.mk b/target/linux/mvebu/image/cortexa9.mk index 824f142a8b..7f746e553b 100644 --- a/target/linux/mvebu/image/cortexa9.mk +++ b/target/linux/mvebu/image/cortexa9.mk @@ -8,8 +8,7 @@ define Device/dsa-migration DEVICE_COMPAT_VERSION := 1.1 - DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA \ - (early adopters with DSA already set up may just force-flash keeping existing config) + DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA endef define Device/buffalo_ls421de diff --git a/target/linux/ramips/image/mt7620.mk b/target/linux/ramips/image/mt7620.mk index 149b666aad..5b9dd16bce 100644 --- a/target/linux/ramips/image/mt7620.mk +++ b/target/linux/ramips/image/mt7620.mk @@ -930,6 +930,7 @@ define Device/ravpower_wd03 DEVICE_VENDOR := Ravpower DEVICE_MODEL := WD03 DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci + DEFAULT := n endef TARGET_DEVICES += ravpower_wd03 diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 681062ad71..c8d286a8e2 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -107,8 +107,7 @@ endef define Device/dsa-migration DEVICE_COMPAT_VERSION := 1.1 - DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA \ - (early adopters with DSA already set up may just force-flash keeping existing config) + DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA endef define Device/adslr_g7 diff --git a/target/linux/ramips/mt7621/base-files/etc/uci-defaults/05_fix-compat-version b/target/linux/ramips/mt7621/base-files/etc/uci-defaults/05_fix-compat-version deleted file mode 100644 index 09cce180e4..0000000000 --- a/target/linux/ramips/mt7621/base-files/etc/uci-defaults/05_fix-compat-version +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (C) 2020 OpenWrt.org -# - -uci set system.@system[0].compat_version="1.1" -uci commit system - -exit 0 diff --git a/tools/fakeroot/Makefile b/tools/fakeroot/Makefile index 2df893d64d..9ab2679626 100644 --- a/tools/fakeroot/Makefile +++ b/tools/fakeroot/Makefile @@ -10,6 +10,8 @@ PKG_VERSION:=1.24 PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz PKG_SOURCE_URL:=http://deb.debian.org/debian/pool/main/f/fakeroot PKG_HASH:=2e045b3160370b8ab4d44d1f8d267e5d1d555f1bb522d650e7167b09477266ed +PKG_LICENSE:=GPL-3.0-or-later +PKG_LICENSE_FILES:=COPYING include $(INCLUDE_DIR)/host-build.mk @@ -17,4 +19,7 @@ HOST_CONFIGURE_VARS += \ ac_cv_header_sys_capability_h=no \ ac_cv_func_capset=no +HOST_CONFIGURE_ARGS += \ + --with-ipc=tcp + $(eval $(call HostBuild)) diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c index 501b396343..dca68fa8a8 100644 --- a/tools/firmware-utils/src/tplink-safeloader.c +++ b/tools/firmware-utils/src/tplink-safeloader.c @@ -77,6 +77,7 @@ struct device_info { const char *support_list; char support_trail; const char *soft_ver; + uint32_t soft_ver_compat_level; struct flash_partition_entry partitions[MAX_PARTITIONS+1]; const char *first_sysupgrade_partition; const char *last_sysupgrade_partition; @@ -84,7 +85,7 @@ struct device_info { /** The content of the soft-version structure */ struct __attribute__((__packed__)) soft_version { - uint32_t magic; + uint32_t data_len; uint32_t zero; uint8_t pad1; uint8_t version_major; @@ -95,7 +96,6 @@ struct __attribute__((__packed__)) soft_version { uint8_t month; uint8_t day; uint32_t rev; - uint8_t pad2; }; @@ -1298,6 +1298,38 @@ static struct device_info boards[] = { .last_sysupgrade_partition = "file-system" }, + /** Firmware layout for the EAP245 v3 */ + { + .id = "EAP245-V3", + .support_list = + "SupportList:\r\n" + "EAP245(TP-Link|UN|AC1750-D):3.0\r\n", + .support_trail = '\xff', + .soft_ver = NULL, + .soft_ver_compat_level = 1, + + /** Firmware partition with dynamic kernel/rootfs split */ + .partitions = { + {"factroy-boot", 0x00000, 0x40000}, + {"fs-uboot", 0x40000, 0x40000}, + {"partition-table", 0x80000, 0x10000}, + {"default-mac", 0x90000, 0x01000}, + {"support-list", 0x91000, 0x00100}, + {"product-info", 0x91100, 0x00400}, + {"soft-version", 0x92000, 0x00100}, + {"radio", 0xa0000, 0x10000}, + {"extra-para", 0xb0000, 0x10000}, + {"firmware", 0xc0000, 0xe40000}, + {"config", 0xf00000, 0x30000}, + {"mutil-log", 0xf30000, 0x80000}, + {"oops", 0xfb0000, 0x40000}, + {NULL, 0, 0} + }, + + .first_sysupgrade_partition = "os-image", + .last_sysupgrade_partition = "file-system" + }, + /** Firmware layout for the TL-WA850RE v2 */ { .id = "TLWA850REV2", @@ -2140,8 +2172,13 @@ static inline uint8_t bcd(uint8_t v) { /** Generates the soft-version partition */ -static struct image_partition_entry make_soft_version(uint32_t rev) { - struct image_partition_entry entry = alloc_image_partition("soft-version", sizeof(struct soft_version)); +static struct image_partition_entry make_soft_version(struct device_info *info, uint32_t rev) { + size_t part_len = sizeof(struct soft_version); + if (info->soft_ver_compat_level > 0) + part_len += sizeof(uint32_t); + + struct image_partition_entry entry = + alloc_image_partition("soft-version", part_len+1); struct soft_version *s = (struct soft_version *)entry.data; time_t t; @@ -2153,7 +2190,8 @@ static struct image_partition_entry make_soft_version(uint32_t rev) { struct tm *tm = gmtime(&t); - s->magic = htonl(0x0000000c); + /* Partition contents size, minus 8 byte header and trailing byte */ + s->data_len = htonl(entry.size-9); s->zero = 0; s->pad1 = 0xff; @@ -2167,7 +2205,11 @@ static struct image_partition_entry make_soft_version(uint32_t rev) { s->day = bcd(tm->tm_mday); s->rev = htonl(rev); - s->pad2 = 0xff; + if (info->soft_ver_compat_level > 0) + *(uint32_t *)(entry.data + sizeof(struct soft_version)) = + htonl(info->soft_ver_compat_level); + + entry.data[entry.size-1] = 0xff; return entry; } @@ -2479,7 +2521,7 @@ static void build_image(const char *output, if (info->soft_ver) parts[1] = make_soft_version_from_string(info->soft_ver); else - parts[1] = make_soft_version(rev); + parts[1] = make_soft_version(info, rev); parts[2] = make_support_list(info); parts[3] = read_file("os-image", kernel_image, false, NULL); @@ -2503,6 +2545,9 @@ static void build_image(const char *output, } else if (strcasecmp(info->id, "ARCHER-C6-V2-US") == 0) { const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00}; parts[5] = put_data("extra-para", mdat, 11); + } else if (strcasecmp(info->id, "EAP245-V3") == 0) { + const char mdat[10] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}; + parts[5] = put_data("extra-para", mdat, 10); } size_t len;